Skip to content

Commit

Permalink
Should now usable with user given bounds.
Browse files Browse the repository at this point in the history
  • Loading branch information
gialmisi committed Aug 6, 2021
1 parent 1b29643 commit 54d5456
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 38 deletions.
43 changes: 12 additions & 31 deletions desdeo_mcdm/interactive/NautilusNavigator.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,30 +169,20 @@ class NautilusNavigator(InteractiveMethod):
Args:
pareto_front (np.ndarray): A two dimensional numpy array
representing a Pareto front with objective vectors on each of its
rows.
representing a Pareto front with objective vectors on each of its
rows.
ideal (np.ndarray): The ideal objective vector of the problem
being represented by the Pareto front.
being represented by the Pareto front.
nadir (np.ndarray): The nadir objective vector of the problem
being represented by the Pareto front.
objective_names (Optional[List[str]], optional): Names of the
objectives. List must match the number of columns in
pareto_front. Defaults to 'f1', 'f2', 'f3', ...
minimize (Optional[List[int]], optional): Multipliers for each
objective. '-1' indicates maximization and '1' minimization.
Defaults to all objective values being minimized.
being represented by the Pareto front.
Raises:
NautilusNavigatorException: One or more dimension mismatches are
encountered among the supplies arguments.
"""

def __init__(
self,
pareto_front: np.ndarray,
ideal: np.ndarray,
nadir: np.ndarray,
objective_names: Optional[List[str]] = None,
self, pareto_front: np.ndarray, ideal: np.ndarray, nadir: np.ndarray,
):
if not pareto_front.ndim == 2:
raise NautilusNavigatorException(
Expand All @@ -210,15 +200,6 @@ def __init__(
if not ideal.shape == nadir.shape:
raise NautilusNavigatorException("The dimensions of the ideal and nadir point do not match.")

if objective_names:
if not len(objective_names) == ideal.shape[0]:
raise NautilusNavigatorException(
"The supplied objective names must have a length equal to " "the number of objectives."
)
self._objective_names = objective_names
else:
self._objective_names = [f"f{i+1}" for i in range(ideal.shape[0])]

self._ideal = ideal
self._nadir = nadir

Expand Down Expand Up @@ -331,7 +312,7 @@ def update(
speed (int): An integer value between 1-5 indicating the navigation speed.
go_to_previous (bool): If True, the parameters indicate the state
of a previous state, and the request is handled accordingly.
stop (bool): If the navigation should stop. If True, self.update return None.
stop (bool): If the navigation should stop. If True, returns a request with self's current state.
step_number (Optional[int], optional): Current step number, or
previous step number if go_to_previous is True. Defaults to None.
nav_point (Optional[np.ndarray], optional): The current
Expand All @@ -358,8 +339,13 @@ def update(
Returns:
NautilusNavigatorRequest: Some of the given parameters are erroneous.
"""

# if stop navigation, return request with current state
if stop:
return NautilusNavigatorRequest.init_with_method(self)

# go to a previous state
if go_to_previous:
elif go_to_previous:
self._step_number = step_number
self._navigation_point = nav_point
self._reachable_lb = lower_bounds
Expand All @@ -383,11 +369,6 @@ def update(
self._reference_point = ref_point
self._projection_index = proj_i

elif stop:
# new reference point given, also update speed
self._reference_point = ref_point
self._current_speed = speed

new_nav = self.calculate_navigation_point(
self._pareto_front[self._projection_index], self._navigation_point, self._steps_remaining,
)
Expand Down
16 changes: 9 additions & 7 deletions tests/test_nautilus_navigator.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def nadir(pareto_front):


@pytest.fixture()
def fun():
def asf_problem():
fun = NautilusNavigator.solve_nautilus_asf_problem
return fun

Expand All @@ -42,7 +42,7 @@ def asf(ideal, nadir):


class TestRefPointProjection:
def test_no_bounds(self, fun, pareto_front, ideal, nadir, asf):
def test_no_bounds(self, asf_problem, pareto_front, ideal, nadir, asf):
"""Test the projection to the Pareto front without specifying any bounds.
"""
bounds = np.repeat(np.nan, ideal.size)
Expand All @@ -56,15 +56,17 @@ def test_no_bounds(self, fun, pareto_front, ideal, nadir, asf):
]

for ref_point in ref_points:
proj_i = fun(pareto_front, list(range(0, pareto_front.shape[0])), np.array(ref_point), ideal, nadir, bounds)
proj_i = asf_problem(
pareto_front, list(range(0, pareto_front.shape[0])), np.array(ref_point), ideal, nadir, bounds
)

# The projection should be the point on the Pareto front with the shortest distance to the reference point
# (metric dictated by use ASF)
should_be = np.argmin(asf(pareto_front, ref_point))

assert proj_i == should_be

def test_w_subset_i(self, fun, pareto_front, ideal, nadir, asf):
def test_w_subset_i(self, asf_problem, pareto_front, ideal, nadir, asf):
"""Test the projection to a subset of the Pareto front.
"""
bounds = np.repeat(np.nan, ideal.size)
Expand All @@ -83,7 +85,7 @@ def test_w_subset_i(self, fun, pareto_front, ideal, nadir, asf):
filtered_pf[~pf_mask] = np.nan

for ref_point in ref_points:
proj_i = fun(pareto_front, subset, np.array(ref_point), ideal, nadir, bounds)
proj_i = asf_problem(pareto_front, subset, np.array(ref_point), ideal, nadir, bounds)

# The projection should be the point on the Pareto front with the shortest distance to the reference point
# (metric dictated by use ASF)
Expand All @@ -92,7 +94,7 @@ def test_w_subset_i(self, fun, pareto_front, ideal, nadir, asf):

assert proj_i == should_be

def test_w_subset_i_and_bounds(self, fun, pareto_front, ideal, nadir, asf):
def test_w_subset_i_and_bounds(self, asf_problem, pareto_front, ideal, nadir, asf):
"""Test the projection to a subset of the Pareto front.
"""
bounds = np.array([np.nan, 1.9, np.nan, np.nan])
Expand All @@ -113,7 +115,7 @@ def test_w_subset_i_and_bounds(self, fun, pareto_front, ideal, nadir, asf):
filtered_pf[bound_mask] = np.nan

for ref_point in ref_points:
proj_i = fun(pareto_front, subset, np.array(ref_point), ideal, nadir, bounds)
proj_i = asf_problem(pareto_front, subset, np.array(ref_point), ideal, nadir, bounds)

# The projection should be the point on the Pareto front with the shortest distance to the reference point
# (metric dictated by use ASF)
Expand Down

0 comments on commit 54d5456

Please sign in to comment.