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_args(): vectors = np.array([[1, 1, 1], [2, 2, 2], [4, 5, 6.0]]) dscalarizer = DiscreteScalarizer( lambda x, a=1: a * np.sum(x, axis=1), scalarizer_args={"a": 2} ) res = dscalarizer(vectors) assert np.array_equal(res, [6, 12, 30])
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_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"]
raise ScalarSolverException( "None of the supplied vectors adhere to the given " "constraint function.") tmp = np.copy(vectors) tmp[bad_con_mask] = np.nan return np.nanargmin(self._scalarizer(tmp)) if __name__ == "__main__": from desdeo_tools.scalarization.ASF import PointMethodASF ideal = np.array([0, 0, 0, 0]) nadir = np.array([1, 1, 1, 1]) asf = PointMethodASF(nadir, ideal) dscalarizer = DiscreteScalarizer(asf, {"reference_point": None}) 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]]) z = np.array([0.4, 0.2, 0.6, 0.8]) dscalarizer._scalarizer_args = {"reference_point": z} print(asf(non_dominated_points, reference_point=z)) res = dminimizer.minimize(non_dominated_points) print(non_dominated_points[res])
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
def test_discrete_1d(): vector = np.array([1, 2, 3.0]) dscalarizer = DiscreteScalarizer(lambda x: np.sum(x, axis=1)) res_1d = dscalarizer(vector) assert np.array_equal(res_1d, [6.0])
def test_discrete(): vectors = np.array([[1, 1, 1], [2, 2, 2], [4, 5, 6.0]]) dscalarizer = DiscreteScalarizer(lambda x: np.sum(x, axis=1)) res = dscalarizer(vectors) assert np.array_equal(res, [3, 6, 15])