Skip to content

Commit

Permalink
Merge branch 'master' of github.com:industrial-optimization-group/des…
Browse files Browse the repository at this point in the history
…deo-mcdm
  • Loading branch information
gialmisi committed Jun 8, 2021
2 parents e1061d6 + b3d46a0 commit adef488
Show file tree
Hide file tree
Showing 18 changed files with 1,316 additions and 122 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# desdeo-mcdm

Contains interactive optimization methods for solving multiobjective optimizaton problems. This package is part of the DESDEO framework.
Contains interactive optimization methods for solving multiobjective optimization problems. This package is part of the DESDEO framework.

## Installation

Expand Down
14 changes: 7 additions & 7 deletions desdeo_mcdm/interactive/ENautilus.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def __init__(
if objective_names:
if not len(objective_names) == ideal.shape[0]:
raise ENautilusException(
"The supplied objective names must have a leangth equal to " "the numbr of objectives."
"The supplied objective names must have a length equal to " "the number of objectives."
)
self._objective_names = objective_names
else:
Expand All @@ -186,7 +186,7 @@ def __init__(
# in objective space!
self._pareto_front = pareto_front

# bounds of the rechable region
# bounds of the reachable region
self._reachable_ub = self._nadir
self._reachable_lb = self._ideal

Expand All @@ -211,7 +211,7 @@ def start(self) -> ENautilusInitialRequest:
def iterate(
self, request: Union[ENautilusInitialRequest, ENautilusRequest]
) -> Union[ENautilusRequest, ENautilusStopRequest]:
"""Perform the next logical iteratino step based on the given request type.
"""Perform the next logical iteration step based on the given request type.
"""
if type(request) is ENautilusInitialRequest:
Expand All @@ -223,7 +223,7 @@ def iterate(
return request

def handle_initial_request(self, request: ENautilusInitialRequest) -> ENautilusRequest:
"""Handles the initial request by parsing the response appropiately.
"""Handles the initial request by parsing the response appropriately.
"""
self._n_iterations = request.response["n_iterations"]
Expand Down Expand Up @@ -277,7 +277,7 @@ def handle_request(self, request: ENautilusRequest) -> Union[ENautilusRequest, E
def calculate_representative_points(
self, pareto_front: np.ndarray, subset_indices: List[int], n_points: int
) -> np.ndarray:
"""Calcualtes the most representative points on the Pareto front. The points are clustered using k-means.
"""Calculates the most representative points on the Pareto front. The points are clustered using k-means.
Args:
pareto_front (np.ndarray): The Pareto front.
Expand Down Expand Up @@ -307,7 +307,7 @@ def calculate_representative_points(
def calculate_intermediate_points(
self, preferred_point: np.ndarray, zbars: np.ndarray, n_iterations_left: int,
) -> np.ndarray:
"""Calcualtes the intermediate points between representative points an a preferred point.
"""Calculates the intermediate points between representative points an a preferred point.
Args:
preferred_point (np.ndarray): The preferred point, 1D array.
Expand All @@ -328,7 +328,7 @@ def calculate_bounds(
Args:
pareto_front (np.ndarray): The Pareto optimal front.
intermediate_points (np.ndarray): The current intermedaite points as a 2D array.
intermediate_points (np.ndarray): The current intermediate points as a 2D array.
Returns:
Tuple[np.ndarray, np.ndarray]: The lower and upper bounds for each of the intermediate points.
Expand Down
40 changes: 20 additions & 20 deletions desdeo_mcdm/interactive/NIMBUS.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(self, method: NIMBUS, ref: np.ndarray):
"\n\t4. values which may be impaired until some upper bound is reached '>='"
"\n\t5. values which are free to change '0'"
"\nProvide the aspiration levels and upper bounds as a vector. For categories 1, 3, and 5,"
"the value in the vector at the objective's position is ignored. Suppy also the number of maximum"
"the value in the vector at the objective's position is ignored. Supply also the number of maximum"
"solutions to be generated."
)

Expand Down Expand Up @@ -87,7 +87,7 @@ def validator(self, response: Dict) -> None:
is_valid_cls = map(lambda x: x in self._valid_classifications, response["classifications"],)

if not all(list(is_valid_cls)):
raise NimbusException(f"Invalid classificaiton found in {response['classifications']}")
raise NimbusException(f"Invalid classification found in {response['classifications']}")

# check the levels
if len(np.array(response["levels"]).squeeze()) != self._method._problem.n_of_objectives:
Expand Down Expand Up @@ -142,7 +142,7 @@ def __init__(
):
msg = (
"Please specify which solutions shown you would like to save for later viewing. Supply the "
"indices of such solutions as a list, or supply an empty list if none of the shown soulutions "
"indices of such solutions as a list, or supply an empty list if none of the shown solutions "
"should be saved."
)
content = {
Expand Down Expand Up @@ -203,7 +203,7 @@ def __init__(
self, solution_vectors: List[np.ndarray], objective_vectors: List[np.ndarray],
):
msg = (
"Would you like to see intermediate solutions between two previusly computed solutions? "
"Would you like to see intermediate solutions between two previously computed solutions? "
"If so, please supply two indices corresponding to the solutions."
)

Expand Down Expand Up @@ -267,7 +267,7 @@ class NimbusMostPreferredRequest(BaseRequest):
Note:
The objective vector at position 'i' in `objective_vectors` should correspond to the decision variables at
position 'i' in `solution_vectors`. Only the two first entries in each of the lists is relevant. The preferred
position 'i' in `solution_vectors`. Only the two first entries in each of the lists are relevant. The preferred
solution will be selected from `objective_vectors`.
"""
Expand Down Expand Up @@ -467,7 +467,7 @@ def handle_classification_request(
"""Handles a classification request.
Args:
request (NimbusClassificationReuest): A classification request with the
request (NimbusClassificationRequest): A classification request with the
response attribute set.
Returns:
Expand Down Expand Up @@ -545,15 +545,15 @@ def handle_intermediate_solutions_request(
def handle_most_preferred_request(
self, request: NimbusMostPreferredRequest
) -> Tuple[Union[NimbusClassificationRequest, NimbusStopRequest], SimplePlotRequest]:
"""Handles a preferres solution request.
"""Handles a preferred solution request.
Args:
request (NimbusMostPreferredRequest): A NIMBUS preferred solution request with the
response attribute set.
Returns:
Tuple[Union[NimbusClassificationRequest, NimbusStopRequest], SimplePlotRequest]:
Return a classificaiton request if the decision maker wishes to continue. If the
Return a classification request if the decision maker wishes to continue. If the
decision maker wishes to stop, return a stop request. Also return a plot
request with all the solutions saved so far.
"""
Expand Down Expand Up @@ -611,18 +611,18 @@ def request_most_preferred_solution(
def compute_intermediate_solutions(
self, solutions: np.ndarray, n_desired: int,
) -> Tuple[NimbusSaveRequest, SimplePlotRequest]:
"""Computs intermediate solution between two solutions computed earlier.
"""Computes intermediate solution between two solutions computed earlier.
Args:
solutions (np.ndarray): The solutions between which the intermediat solutions should
solutions (np.ndarray): The solutions between which the intermediate solutions should
be computed.
n_desired (int): The number of intermediate solutions desired.
Raises:
NimbusException
Returns:
Tuple[NimbusSaveRequest, SimplePlotRequest]: A save request with the compured intermediate
Tuple[NimbusSaveRequest, SimplePlotRequest]: A save request with the computed intermediate
points, and a plot request to visualize said points.
"""
# vector between the two solutions
Expand Down Expand Up @@ -676,7 +676,7 @@ def compute_intermediate_solutions(
intermediate_solutions[i] = self._problem.decision_variables[res["x"]]
intermediate_objectives[i] = self._problem.objectives[res["x"]]

# create appropiate requests
# create appropriate requests
save_request = NimbusSaveRequest(list(intermediate_solutions), list(intermediate_objectives))

msg = "Computed intermediate solutions"
Expand Down Expand Up @@ -730,7 +730,7 @@ def calculate_new_solutions(
impaire_until_inds: np.ndarray,
free_inds: np.ndarray,
) -> Tuple[NimbusSaveRequest, SimplePlotRequest]:
"""Calcualtes new solutions based on classifications supplied by the decision maker by
"""Calculates new solutions based on classifications supplied by the decision maker by
solving ASF problems.
Args:
Expand All @@ -744,7 +744,7 @@ def calculate_new_solutions(
free_inds (np.ndarray): Indices of objectives which may change freely.
Returns:
Tuple[NimbusSaveRequest, SimplePlotRequest]: A save request with the newly computed soutions, and
Tuple[NimbusSaveRequest, SimplePlotRequest]: A save request with the newly computed solutions, and
a plot request to visualize said solutions.
"""
results = []
Expand Down Expand Up @@ -960,14 +960,14 @@ def iterate(
Union[NimbusClassificationRequest, NimbusSaveRequest, NimbusIntermediateSolutionsRequest,],
Union[SimplePlotRequest, None],
]:
"""Implements a finite state machine to iterate over the different steps defined in Synchronous NIMBUS based on a supllied request.
"""Implements a finite state machine to iterate over the different steps defined in Synchronous NIMBUS based on a supplied request.
Args:
request (Union[NimbusClassificationRequest,NimbusSaveRequest,NimbusIntermediateSolutionsRequest,NimbusMostPreferredRequest,NimbusStopRequest,]):
A request based on the next step in the NIMBUS algorithm is taken.
Raises:
NimbusException: If a wrong type of request is supllied based on the current state NIMBUS is in.
NimbusException: If a wrong type of request is supplied based on the current state NIMBUS is in.
Returns:
Tuple[Union[NimbusClassificationRequest,NimbusSaveRequest,NimbusIntermediateSolutionsRequest,],Union[SimplePlotRequest, None],]:
Expand Down Expand Up @@ -1141,7 +1141,7 @@ def f_2(xs: np.ndarray):

print(classification_request.content["objective_values"])

# Ploting F1!
# Plotting F1!
plt.scatter(x1, y, label="Range")
plt.scatter(-15, 0, label="P1", c="r")
plt.scatter(-18, 0, label="P2", c="r")
Expand All @@ -1152,7 +1152,7 @@ def f_2(xs: np.ndarray):

plt.show()

# Ploting F2!
# Plotting F2!
plt.scatter(x2, y, label="Range")
plt.scatter(-6, 0, label="P1", c="r")
plt.scatter(-9, 0, label="P2", c="r")
Expand All @@ -1171,7 +1171,7 @@ def f_2(xs: np.ndarray):
print(save_request.content["objectives"])
print(save_request.content["solutions"])

# Ploting F1!
# Plotting F1!
plt.scatter(x1, y, label="Range")
plt.scatter(-15, 0, label="P1", c="r")
plt.scatter(-18, 0, label="P2", c="r")
Expand All @@ -1182,7 +1182,7 @@ def f_2(xs: np.ndarray):

plt.show()

# Ploting F2!
# Plotting F2!
plt.scatter(x2, y, label="Range")
plt.scatter(-6, 0, label="P1", c="r")
plt.scatter(-9, 0, label="P2", c="r")
Expand Down
4 changes: 2 additions & 2 deletions desdeo_mcdm/interactive/Nautilus.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def validate_preferences(n_objectives: int, response: Dict) -> None:
raise NautilusException(msg)
elif not (1 <= max(response["preference_info"]) <= n_objectives):
msg = "The minimum index of importance must be greater or equal "
"to 1 and the maximum index of improtance must be less "
"to 1 and the maximum index of importance must be less "
"than or equal to the number of objectives in the "
"problem, which is {}. Check the indices {}" \
.format(n_objectives, response["preference_info"])
Expand Down Expand Up @@ -359,7 +359,7 @@ def __init__(
if objective_names:
if not len(objective_names) == ideal.shape[0]:
raise NautilusException(
"The supplied objective names must have a length equal to " "the numbr of objectives."
"The supplied objective names must have a length equal to " "the number of objectives."
)
self._objective_names = objective_names
else:
Expand Down
20 changes: 10 additions & 10 deletions desdeo_mcdm/interactive/NautilusNavigator.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def __init__(
step_number: int,
steps_remaining: int,
distance: float,
allowed_speeds: [int],
allowed_speeds: List[int],
current_speed: int,
navigation_point: np.ndarray,
):
Expand All @@ -36,7 +36,7 @@ def __init__(
"desired, please set `go_to_previous` to True, otherwise it should "
"be False. "
"Lastly, if stopping is desired, `stop` should be True, "
"otherweise it should be set to False."
"otherwise it should be set to False."
)
content = {
"message": msg,
Expand Down Expand Up @@ -182,7 +182,7 @@ def __init__(
if objective_names:
if not len(objective_names) == ideal.shape[0]:
raise NautilusNavigatorException(
"The supplied objective names must have a leangth equal to " "the numbr of objectives."
"The supplied objective names must have a length equal to " "the number of objectives."
)
self._objective_names = objective_names
else:
Expand All @@ -203,7 +203,7 @@ def __init__(
# in objective space!
self._pareto_front = pareto_front

# bounds of the rechable region
# bounds of the reachable region
self._reachable_ub = self._nadir
self._reachable_lb = self._ideal

Expand Down Expand Up @@ -295,7 +295,7 @@ def update(
distance: Optional[float] = None,
steps_remaining: Optional[int] = None,
) -> Optional[NautilusNavigatorRequest]:
"""Update the inernal state of self.
"""Update the internal state of self.
Args:
ref_point (np.ndarray): A reference point given by a decision maker.
Expand All @@ -309,10 +309,10 @@ def update(
navigation point. Relevant if go_to_previous is True. Defaults to
None.
lower_bounds (Optional[np.ndarray], optional): Lower bounds of
the reachable objective vector valus. Relevant if go_to_previous
the reachable objective vector values. Relevant if go_to_previous
is True. Defaults to None.
upper_bounds (Optional[np.ndarray], optional): Upper bounds of
the reachable objective vector valus. Relevant if go_to_previous
the reachable objective vector values. Relevant if go_to_previous
is True. Defaults to None.
reachable_idx (Optional[List[int]], optional): Indices of the
reachable Pareto optimal solutions. Relevant if go_to_previous is
Expand All @@ -324,7 +324,7 @@ def update(
navigation. Relevant if go_to_previous is True. Defaults to None.
Returns:
NautilusNavigatorRequest: Some of the given parameters are erraneous.
NautilusNavigatorRequest: Some of the given parameters are erroneous.
"""
# go to a previous state
if go_to_previous:
Expand Down Expand Up @@ -405,10 +405,10 @@ def calculate_reachable_point_indices(
return reachable_idx

def solve_nautilus_asf_problem(
self, pareto_f: np.ndarray, subset_indices: [int], ref_point: np.ndarray, ideal: np.ndarray, nadir: np.ndarray,
self, pareto_f: np.ndarray, subset_indices: List[int], ref_point: np.ndarray, ideal: np.ndarray, nadir: np.ndarray,
) -> int:
"""Forms and solves the achievement scalarizing function to find the
closesto point on the Pareto optimal front to the given reference
closest point on the Pareto optimal front to the given reference
point.
Args:
Expand Down

0 comments on commit adef488

Please sign in to comment.