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
Example #2
0
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"]
Example #4
0
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)
Example #5
0
    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']
Example #6
0
    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