def solve_nautilus_asf_problem( self, pareto_f: np.ndarray, subset_indices: [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 point. Args: pareto_f (np.ndarray): The whole Pareto optimal front. subset_indices ([type]): Indices of the currently reachable solutions. ref_point (np.ndarray): The reference point indicating a decision maker's preference. ideal (np.ndarray): Ideal point. nadir (np.ndarray): Nadir point. Returns: int: Index of the closest point according the minimized value of the ASF. """ asf = PointMethodASF(nadir, ideal) scalarizer = DiscreteScalarizer(asf, {"reference_point": ref_point}) solver = DiscreteMinimizer(scalarizer) tmp = np.copy(pareto_f) mask = np.zeros(tmp.shape[0], dtype=bool) mask[subset_indices] = True tmp[~mask] = np.nan res = solver.minimize(tmp) return res
def test_discrete_solver(): ideal = np.array([0, 0, 0, 0]) nadir = np.array([1, 1, 1, 1]) asf = PointMethodASF(nadir, ideal) dscalarizer = DiscreteScalarizer(asf, {"reference_point": nadir}) dminimizer = DiscreteMinimizer(dscalarizer) non_dominated_points = np.array([ [0.2, 0.4, 0.6, 0.8], [0.4, 0.2, 0.6, 0.8], [0.6, 0.4, 0.2, 0.8], [0.4, 0.8, 0.6, 0.2], ]) # first occurrence res_ind = dminimizer.minimize(non_dominated_points) assert res_ind == 0 dscalarizer._scalarizer_args = { "reference_point": np.array([0.6, 0.4, 0.2, 0.8]) } res_ind = dminimizer.minimize(non_dominated_points) assert res_ind == 2
def solve_nautilus_asf_problem( pareto_f: np.ndarray, subset_indices: List[int], ref_point: np.ndarray, ideal: np.ndarray, nadir: np.ndarray, user_bounds: np.ndarray, ) -> int: """Forms and solves the achievement scalarizing function to find the closest point on the Pareto optimal front to the given reference point. Args: pareto_f (np.ndarray): The whole Pareto optimal front. subset_indices ([type]): Indices of the currently reachable solutions. ref_point (np.ndarray): The reference point indicating a decision maker's preference. ideal (np.ndarray): Ideal point. nadir (np.ndarray): Nadir point. user_bounds (np.ndarray): Bounds given by the user (the DM) for each objective,which should not be exceeded. A 1D array where NaN's indicate 'no bound is given' for the respective objective value. Returns: int: Index of the closest point according the minimized value of the ASF. """ asf = PointMethodASF(nadir, ideal) scalarizer = DiscreteScalarizer(asf, {"reference_point": ref_point}) solver = DiscreteMinimizer(scalarizer) # Copy the front and filter out the reachable solutions. # If user bounds are given, filter out solutions outside the those bounds. # Infeasible solutions on the pareto font are set to be NaNs. tmp = np.copy(pareto_f) mask = np.zeros(tmp.shape[0], dtype=bool) mask[subset_indices] = True tmp[~mask] = np.nan # indices of solutions with one or more objective value exceeding the user bounds. bound_mask = np.any(tmp > user_bounds, axis=1) tmp[bound_mask] = np.nan res = solver.minimize(tmp) return res["x"]
def test_discrete_solver_with_con(): ideal = np.array([0, 0, 0, 0]) nadir = np.array([1, 1, 1, 1]) asf = PointMethodASF(nadir, ideal) con = lambda x: x[:, 0] > 0.2 dscalarizer = DiscreteScalarizer(asf, {"reference_point": nadir}) dminimizer = DiscreteMinimizer(dscalarizer, constraint_evaluator=con) non_dominated_points = np.array([ [0.2, 0.4, 0.6, 0.8], [0.4, 0.2, 0.6, 0.8], [0.6, 0.4, 0.2, 0.8], [0.4, 0.8, 0.6, 0.2], ]) # first occurrence with first point invalid res_ind = dminimizer.minimize(non_dominated_points) assert res_ind == 1 # first point as closest, but invalid dscalarizer._scalarizer_args = { "reference_point": np.array([0.2, 0.4, 0.6, 0.8]) } res_ind = dminimizer.minimize(non_dominated_points) assert res_ind == 1 # all points invalid dminimizer._constraint_evaluator = lambda x: x[:, 0] > 1.0 with pytest.raises(ScalarSolverException): _ = dminimizer.minimize(non_dominated_points)
def solve_asf( self, problem: Union[MOProblem, DiscreteDataProblem], ref_point: np.ndarray, method: Optional[ScalarMethod] = None, ): """ Solve the achievement scalarizing function Args: problem (MOProblem): The problem ref_point: A reference point method (Optional[ScalarMethod], optional): A method provided to the scalar minimizer Returns: np.ndarray: The decision vector which solves the achievement scalarizing function """ asf = SimpleASF(np.ones(ref_point.shape)) if isinstance(problem, MOProblem): scalarizer = Scalarizer( lambda x: problem.evaluate(x).objectives, asf, scalarizer_args={"reference_point": np.atleast_2d(ref_point)}, ) if problem.n_of_constraints > 0: _con_eval = lambda x: problem.evaluate(x).constraints.squeeze() else: _con_eval = None solver = ScalarMinimizer( scalarizer, problem.get_variable_bounds(), constraint_evaluator=_con_eval, method=method, ) res = solver.minimize(problem.get_variable_upper_bounds() / 2) if res["success"]: return res["x"] else: raise ParetoNavigatorException( "Could solve achievement scalarizing function") else: # Discrete case # Find closest objective to ref point scalarizer = DiscreteScalarizer(asf, {"reference_point": ref_point}) solver = DiscreteMinimizer(scalarizer) res = solver.minimize(problem.objectives) return res['x']
def solve_asf( self, ref_point: np.ndarray, x0: np.ndarray, preferential_factors: np.ndarray, nadir: np.ndarray, utopian: np.ndarray, objectives: Callable, variable_vectors: Optional[np.ndarray] = None, variable_bounds: Optional[np.ndarray] = None, method: Union[ScalarMethod, str, None] = None, ) -> dict: """ Solve Achievement scalarizing function. Args: ref_point (np.ndarray): Reference point. x0 (np.ndarray): Initial values for decision variables. preferential_factors (np.ndarray): Preferential factors on how much would the Decision Maker wish to improve the values of each objective function. nadir (np.ndarray): Nadir vector. utopian (np.ndarray): Utopian vector. objectives (np.ndarray): The objective function values for each input vector. variable_bounds (Optional[np.ndarray)]: Lower and upper bounds of each variable as a 2D numpy array. If undefined variables, None instead. method (Union[ScalarMethod, str, None]): The optimization method the scalarizer should be minimized with. Returns: dict: A dictionary with at least the following entries: 'x' indicating the optimal variables found, 'fun' the optimal value of the optimized function, and 'success' a boolean indicating whether the optimization was conducted successfully. """ if method != "discrete": # non discrete case if variable_bounds is None: # set all bounds as [-inf, inf] variable_bounds = np.array([[-np.inf, np.inf]] * x0.shape[0]) # scalarize problem using reference point asf = ReferencePointASF(preferential_factors, nadir, utopian, rho=1e-4) asf_scalarizer = Scalarizer( evaluator=objectives, scalarizer=asf, scalarizer_args={"reference_point": ref_point}) # minimize minimizer = ScalarMinimizer(asf_scalarizer, variable_bounds, method=method) return minimizer.minimize(x0) else: # discrete case # scalarize problem using reference point asf = ReferencePointASF(preferential_factors, nadir, utopian, rho=1e-4) asf_scalarizer = DiscreteScalarizer( asf, scalarizer_args={"reference_point": ref_point}) # minimize the discrete problem minimizer = DiscreteMinimizer(asf_scalarizer) res = minimizer.minimize(objectives) return res