예제 #1
0
    def calculate_bounds(
        self,
        objectives: Callable,
        n_objectives: int,
        x0: np.ndarray,
        epsilons: np.ndarray,
        bounds: Union[np.ndarray, None],
        constraints: Optional[Callable],
        method: Union[ScalarMethod, str, None],
    ) -> np.ndarray:
        """
        Calculate the new bounds using Epsilon constraint method.

        Args:
            objectives (np.ndarray): The objective function values for each input vector.
            n_objectives (int): Total number of objectives.
            x0 (np.ndarray): Initial values for decision variables.
            epsilons (np.ndarray): Previous iteration point.
            bounds (Union[np.ndarray, None]): Bounds for decision variables.
            constraints (Callable): Constraints of the problem.
            method (Union[ScalarMethod, str, None]): The optimization method the scalarizer should be minimized with.

        Returns:
            np.ndarray: New lower bounds for objective functions.
        """

        new_lower_bounds: np.ndarray = [None] * n_objectives

        # set polish to False
        method_e: ScalarMethod = ScalarMethod(
            lambda x, _, **y: differential_evolution(x, **y),
            method_args={"disp": False, "polish": False, "tol": 0.000001, "popsize": 10, "maxiter": 50000},
            use_scipy=True,
        )

        # solve new lower bounds for each objective
        for i in range(n_objectives):
            eps = ECM.EpsilonConstraintMethod(
                objectives,
                i,
                # take out the objective to be minimized
                np.array([val for ind, val in enumerate(epsilons) if ind != i]),
                constraints=constraints,
            )
            cons_evaluate = eps.evaluate_constraints
            scalarized_objective = Scalarizer(objectives, eps)

            minimizer = ScalarMinimizer(
                scalarized_objective, bounds, constraint_evaluator=cons_evaluate, method=method_e
            )
            res = minimizer.minimize(x0)

            # store objective function values as new lower bounds
            new_lower_bounds[i] = objectives(res["x"])[0][i]

        return new_lower_bounds
예제 #2
0
def test_dummy_cons():
    method = ScalarMethod(dummy_minimizer)
    solver = ScalarMinimizer(simple_problem, np.array([[0, 0, 0], [1, 1, 1]]),
                             simple_constr, method)

    res = solver.minimize(np.array([0.5, 0.5, 0.1]))

    assert res["success"]

    res = solver.minimize(np.array([0.5, 0.5, 0.5]))

    assert not res["success"]
예제 #3
0
def test_dummy_no_cons():
    method = ScalarMethod(dummy_minimizer)
    solver = ScalarMinimizer(simple_problem, np.array([[0, 0, 0], [1, 1, 1]]),
                             None, method)

    x0 = np.array([0.5, 0.5, 0.5])
    res = solver.minimize(x0)

    assert np.array_equal(res["x"], x0)
    assert res["success"]
    assert (res["message"] ==
            "I just retruned the initial guess as the optimal solution.")
예제 #4
0
    def __init__(
        self,
        problem: MOProblem,
        starting_point: np.ndarray,
        ideal: np.ndarray,
        nadir: np.ndarray,
        epsilon: float = 1e-6,
        objective_names: Optional[List[str]] = None,
        minimize: Optional[List[int]] = None,
    ):

        if not ideal.shape == nadir.shape:
            raise NautilusException("The dimensions of the ideal and nadir point do not match.")

        if not ideal.shape == starting_point.shape:
            raise NautilusException("The dimension of the ideal and starting point do not match.")

        if all(np.less(nadir, starting_point)):
            raise NautilusException("Starting point cannot be worse than nadir point.")

        if objective_names:
            if not len(objective_names) == ideal.shape[0]:
                raise NautilusException(
                    "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])]

        if minimize:
            if not len(objective_names) == ideal.shape[0]:
                raise NautilusException("The minimize list must have " "as many elements as there are objectives.")
            self._minimize = minimize
        else:
            self._minimize = [1 for _ in range(ideal.shape[0])]

        # initialize method with problem
        super().__init__(problem)
        self._problem = problem
        self._objectives: Callable = lambda x: self._problem.evaluate(x).objectives
        self._variable_bounds: Union[np.ndarray, None] = problem.get_variable_bounds()
        self._constraints: Optional[Callable] = lambda x: self._problem.evaluate(x).constraints

        # Used to calculate the utopian point from the ideal point
        self._epsilon = epsilon
        self._ideal = ideal
        self._nadir = nadir
        self._starting_point = starting_point

        # calculate utopian vector
        self._utopian = np.array([ideal_i - self._epsilon for ideal_i in self._ideal])

        # bounds of the reachable region
        self._lower_bounds: List[np.ndarray] = []
        self._upper_bounds: List[np.ndarray] = []

        # current iteration step number
        self._step_number = 1

        # iteration points
        self._zs: np.ndarray = []

        # solutions, objectives, and distances for each iteration
        self._xs: np.ndarray = []
        self._fs: np.ndarray = []
        self._ds: np.ndarray = []

        # The current reference point
        self._q: Union[None, np.ndarray] = None

        # preference information
        self._preference_method = None
        self._preference_info = None
        self._preferential_factors = None

        # number of total iterations and iterations left
        self._n_iterations = None
        self._n_iterations_left = None

        # flags for the iteration phase
        # not utilized atm
        self._use_previous_preference: bool = False
        self._step_back: bool = False
        self._short_step: bool = False
        self._first_iteration: bool = True

        # evolutionary method for minimizing
        self._method_de: ScalarMethod = ScalarMethod(
            lambda x, _, **y: differential_evolution(x, **y),
            method_args={"disp": False, "polish": False, "tol": 0.000001, "popsize": 10, "maxiter": 50000},
            use_scipy=True,
        )
예제 #5
0
    def __init__(
        self,
        problem: Union[MOProblem, DiscreteDataProblem],
        ideal: np.ndarray,
        nadir: np.ndarray,
        epsilon: float = 1e-6,
        objective_names: Optional[List[str]] = None,
        minimize: Optional[List[int]] = None,
    ):

        if not ideal.shape == nadir.shape:
            raise RPMException(
                "The dimensions of the ideal and nadir point do not match.")

        if objective_names:
            if not len(objective_names) == ideal.shape[0]:
                raise RPMException(
                    "The supplied objective names must have a leangth 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])
            ]

        if minimize:
            if not len(objective_names) == ideal.shape[0]:
                raise RPMException("The minimize list must have "
                                   "as many elements as there are objectives.")
            self._minimize = minimize
        else:
            self._minimize = [1 for _ in range(ideal.shape[0])]

        self._ideal = ideal
        self._nadir = nadir
        self._utopian = ideal - epsilon
        self._n_objectives = self._ideal.shape[0]

        # current iteration step number
        self._h = 1

        # solutions in decision and objective space, distances and referation points for each iteration
        self._xs = [None] * 10
        self._fs = [None] * 10
        self._ds = [None] * 10
        self._qs = [None] * 10

        # perturbed reference points
        self._pqs = [None] * 10

        # additional solutions
        self._axs = [None] * 10
        self._afs = [None] * 10

        # current reference point
        self._q: Union[None, np.ndarray] = None

        # weighting vector for achievement function
        self._w: np.ndarray = []

        self._problem = problem

        if isinstance(problem, MOProblem):
            # initialize method with MOProblem
            self._objectives: Callable = lambda x: self._problem.evaluate(
                x).objectives
            self._variable_bounds: Union[np.ndarray,
                                         None] = problem.get_variable_bounds()
            self._variable_vectors = None
            self._constraints: Optional[
                Callable] = lambda x: self._problem.evaluate(x).constraints

            # evolutionary method for minimizing
            self._method_de: ScalarMethod = ScalarMethod(
                lambda x, _, **y: differential_evolution(x, **y),
                method_args={
                    "disp": False,
                    "polish": False,
                    "tol": 0.000001,
                    "popsize": 10,
                    "maxiter": 50000
                },
                use_scipy=True,
            )
        else:
            # Initialize the method with DiscreteData
            self._objectives = problem.objectives
            self._variable_bounds = None  # TODO: check me
            self._variable_vectors = problem.decision_variables
            self._constraints = None  # TODO: check me

            self._method_de = "discrete"
예제 #6
0
    x1 = np.linspace(min(f1_range), max(f1_range), 1000)
    x2 = np.linspace(min(f2_range), max(f2_range), 1000)
    y = np.linspace(0, 0, 1000)

    problem = MOProblem(variables=varsl,
                        objectives=[f1, f2],
                        ideal=np.array([-20, -12]),
                        nadir=np.array([-14, 0.5]))

    from desdeo_mcdm.interactive.NIMBUS import NIMBUS
    from scipy.optimize import minimize, differential_evolution

    scalar_method = ScalarMethod(
        lambda x, _, **y: differential_evolution(x, **y),
        use_scipy=True,
        method_args={
            "polish": True,
            "disp": True
        })

    method = NIMBUS(problem, scalar_method)

    classification_request, plot_request = method.start()

    # print(classification_request.content.keys())
    # print(classification_request.content["message"])

    print(classification_request.content["objective_values"])

    #Ploting F1!
    plt.scatter(x1, y, label="Range")