:py:mod:`desdeo_mcdm.interactive`
=================================

.. py:module:: desdeo_mcdm.interactive

.. autoapi-nested-parse::

   This module contains interactive methods and related requests implemented as classes.



Submodules
----------
.. toctree::
   :titlesonly:
   :maxdepth: 1

   ENautilus/index.rst
   InteractiveMethod/index.rst
   NIMBUS/index.rst
   Nautilus/index.rst
   NautilusNavigator/index.rst
   NautilusV2/index.rst
   ParetoNavigator/index.rst
   ReferencePointMethod/index.rst


Package Contents
----------------

Classes
~~~~~~~

.. autoapisummary::

   desdeo_mcdm.interactive.ParetoNavigator
   desdeo_mcdm.interactive.ParetoNavigatorInitialRequest
   desdeo_mcdm.interactive.ParetoNavigatorRequest
   desdeo_mcdm.interactive.ParetoNavigatorSolutionRequest
   desdeo_mcdm.interactive.ParetoNavigatorStopRequest
   desdeo_mcdm.interactive.ENautilus
   desdeo_mcdm.interactive.ENautilusInitialRequest
   desdeo_mcdm.interactive.ENautilusRequest
   desdeo_mcdm.interactive.ENautilusStopRequest
   desdeo_mcdm.interactive.Nautilus
   desdeo_mcdm.interactive.NautilusV2
   desdeo_mcdm.interactive.NautilusInitialRequest
   desdeo_mcdm.interactive.NautilusRequest
   desdeo_mcdm.interactive.NautilusStopRequest
   desdeo_mcdm.interactive.NautilusNavigator
   desdeo_mcdm.interactive.NautilusNavigatorRequest
   desdeo_mcdm.interactive.NIMBUS
   desdeo_mcdm.interactive.NimbusClassificationRequest
   desdeo_mcdm.interactive.NimbusIntermediateSolutionsRequest
   desdeo_mcdm.interactive.NimbusMostPreferredRequest
   desdeo_mcdm.interactive.NimbusSaveRequest
   desdeo_mcdm.interactive.NimbusStopRequest
   desdeo_mcdm.interactive.RPMInitialRequest
   desdeo_mcdm.interactive.RPMRequest
   desdeo_mcdm.interactive.RPMStopRequest
   desdeo_mcdm.interactive.ReferencePointMethod



Functions
~~~~~~~~~

.. autoapisummary::

   desdeo_mcdm.interactive.validate_preferences
   desdeo_mcdm.interactive.validate_response
   desdeo_mcdm.interactive.validate_n2_preferences
   desdeo_mcdm.interactive.validate_n_iterations



.. py:class:: ParetoNavigator(problem: Union[desdeo_problem.problem.MOProblem, desdeo_problem.problem.DiscreteDataProblem], pareto_optimal_solutions: Optional[numpy.ndarray] = None, scalar_method: Optional[desdeo_tools.solver.ScalarSolver.ScalarMethod] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   Paretonavigator as described in 'Pareto navigator for interactive nonlinear
   multiobjective optimization' (2008) [Petri Eskelinen · Kaisa Miettinen ·
   Kathrin Klamroth · Jussi Hakanen].

   :param problem: The problem to be solved.
   :type problem: MOProblem
   :param pareto_optimal_solutions: Some pareto optimal solutions to construct the polyhedral set.
   :type pareto_optimal_solutions: np.ndarray
   :param scalar_method: (Optional[ScalarMethod], optional): The scalar method used to solve asf

   .. note::

      pareto_optimal_solutions must be provided for problems of type MOProblem.
          For DiscreteDataProblems if no pareto optimal solutions are provided
          the method will use the objective values from the problem.

   .. py:method:: start()

      Start the solving process

      :returns: Initial request
      :rtype: ParetoNavigatorInitialRequest


   .. py:method:: iterate(request: Union[ParetoNavigatorInitialRequest, ParetoNavigatorRequest, ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]) -> Union[ParetoNavigatorRequest, ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]

      Perform the next logical iteration step based on the given request type.

      :param request (Union[ParetoNavigatorInitialRequest: ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]):
                                                           A ParetoNavigatorRequest
      :param ParetoNavigatorRequest: ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]):
                                     A ParetoNavigatorRequest
      :param : ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]):
               A ParetoNavigatorRequest

      :returns:     A new request with content depending on the Decision Maker's preferences.
      :rtype: Union[ParetoNavigatorRequest, ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]


   .. py:method:: handle_initial_request(request: ParetoNavigatorInitialRequest) -> ParetoNavigatorRequest

      Handles the initial request.

      :param request: Initial request
      :type request: ParetoNavigatorInitialRequest

      :returns: A navigation request
      :rtype: ParetoNavigatorRequest


   .. py:method:: handle_request(request: ParetoNavigatorRequest) -> Union[ParetoNavigatorRequest, ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]

      Handles a navigation request.

      :param request: A request
      :type request: ParetoNavigatorRequest

      :returns:     Next request corresponding the DM's preferences
      :rtype: Union[ParetoNavigatorRequest, ParetoNavigatorSolutionRequest, ParetoNavigatorStopRequest]


   .. py:method:: handle_solution_request(request: ParetoNavigatorSolutionRequest) -> Union[ParetoNavigatorRequest, ParetoNavigatorStopRequest]

      Handle a solution request

      :param request: A solution request
      :type request: ParetoNavigatorSolutionRequest

      :returns:     A navigation request or a stop request depending on whether
                    the DM wishes to continue or stop
      :rtype: Union[ParetoNavigatorRequest, ParetoNavigatorStopRequest]


   .. py:method:: calculate_extremes(points: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray]

      Calculate the minimum and maximum points of a given array.

      :param points: A two dimensional array
      :type points: np.ndarray

      :returns: The min and max values of each column
      :rtype: Tuple[np.ndarray, np.ndarray]


   .. py:method:: calculate_speed(given_speed: int) -> float

      Calculate a speed value from given integer value.

      :param given_speed: a speed value where 1 is slowest and 5 fastest
      :type given_speed: int

      :returns:

                A speed value calculated from given integer value.
                    Is between 0 and 1
      :rtype: float

      .. note::

         The denominator 10 is not mentioned in the article, but it is included
         because the navigation speed seems to be too fast without it.


   .. py:method:: calculate_weights(ideal: numpy.ndarray, nadir: numpy.ndarray)

      Calculate the scaling coefficients w from ideal and nadir.

      :param ideal: Ideal vector
      :type ideal: np.ndarray
      :param nadir: Nadir vector
      :type nadir: np.ndarray

      :returns: The scaling coefficients
      :rtype: np.ndarray


   .. py:method:: polyhedral_set_eq(po_solutions: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray]

      Construct a polyhedral set as convex hull from the set of pareto optimal solutions

      :param po_solutions: Some pareto optimal solutions
      :type po_solutions: np.ndarray

      :returns:

                Matrix A and vector b from the
                    convex hull inequality representation Az <= b
      :rtype: Tuple[np.ndarray, np.ndarray]


   .. py:method:: construct_lppp_A(weights, A)

      The matrix A used in the linear parametric programming problem

      :param weights: Scaling coefficients
      :type weights: np.ndarray
      :param A: Matrix A from the convex hull representation Ax < b
      :type A: np.ndarray

      :returns: The matrix A' in the linear parametric programming problem A'x<b'
      :rtype: np.ndarray


   .. py:method:: calculate_direction(current_solution: numpy.ndarray, ref_point: numpy.ndarray)

      Calculate a new direction from current solution and a given reference point

      :param current_solution: The current solution
      :type current_solution: np.ndarray
      :param ref_point: A reference point
      :type ref_point: np.ndarray

      :returns: A new direction
      :rtype: np.ndarray


   .. py:method:: classification_to_ref_point(classifications, ideal, nadir, current_solution)

      Transform classifications to a reference point

      :param classifications: Classification for each objective
      :type classifications: np.ndarray
      :param ideal: Ideal point
      :type ideal: np.ndarray
      :param nadir: Nadir point
      :type nadir: np.ndarray
      :param current_solution: Current solution
      :type current_solution: np.ndarray

      :returns: A reference point which is constructed from the classifications
      :rtype: np.ndarray


   .. py:method:: solve_linear_parametric_problem(current_sol: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray, direction: numpy.ndarray, a: float, A: numpy.ndarray, b: numpy.ndarray) -> numpy.ndarray

      Solves the linear parametric programming problem as defined in (3)

      :param current_sol: Current solution
      :type current_sol: np.ndarray
      :param ideal: Ideal vector
      :type ideal: np.ndarray
      :param nadir: Nadir vector
      :type nadir: np.ndarray
      :param direction: Navigation direction
      :type direction: np.ndarray
      :param a: Alpha in problem (3)
      :type a: float
      :param A: Matrix A from Az <= b
      :type A: np.ndarray
      :param b: Vector b from Az <= b
      :type b: np.ndarray

      :returns:

                Optimal vector from the linear parametric programming problem.
                    This is the new solution to be used in the navigation.
      :rtype: np.ndarray


   .. py:method:: solve_asf(problem: Union[desdeo_problem.problem.MOProblem, desdeo_problem.problem.DiscreteDataProblem], ref_point: numpy.ndarray, method: Optional[desdeo_tools.solver.ScalarSolver.ScalarMethod] = None)

      Solve the achievement scalarizing function

      :param problem: The problem
      :type problem: MOProblem
      :param ref_point: A reference point
      :param method: A method provided to the scalar minimizer
      :type method: Optional[ScalarMethod], optional

      :returns: The decision vector which solves the achievement scalarizing function
      :rtype: np.ndarray



.. py:exception:: ParetoNavigatorException

   Bases: :py:obj:`Exception`

   Raised when an exception related to Pareto Navigator is encountered.


.. py:class:: ParetoNavigatorInitialRequest(ideal: numpy.ndarray, nadir: numpy.ndarray, allowed_speeds: numpy.ndarray, po_solutions: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the Decision Maker's initial preferences for the first iteration round.

   :param ideal: Ideal vector
   :type ideal: np.ndarray
   :param nadir: Nadir vector
   :type nadir: np.ndarray
   :param allowed_speeds: Allowed movement speeds
   :type allowed_speeds: np.ndarray
   :param po_solutions: (np.ndarray): A set of pareto optimal solutions

   .. py:attribute:: msg
      :annotation: = Please specify a starting point as 'preferred_solution'.

      Or specify a reference point as 'reference_point'.

   .. py:method:: init_with_method(method: desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod)
      :classmethod:

      Initialize request with given instance of ParetoNavigator.

      :param method: Instance of ReferencePointMethod-class.
      :type method: ParetoNavigator

      :returns: Initial request.
      :rtype: ParetoNavigatorInitialRequest



.. py:class:: ParetoNavigatorRequest(current_solution: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray, allowed_speeds: numpy.ndarray, valid_classifications: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle navigation preferences after the first iteration round.

   :param current_solution: Current solution.
   :type current_solution: np.ndarray
   :param ideal: Ideal vector.
   :type ideal: np.ndarray
   :param nadir: Nadir vector.
   :type nadir: np.ndarray
   :param allowed_speeds: Allowed movement speeds
   :type allowed_speeds: np.ndarray
   :param valid_classifications: Valid classifications
   :type valid_classifications: np.ndarray

   .. py:method:: init_with_method(method: desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod)
      :classmethod:

      Initialize request with given instance of ParetoNavigator.

      :param method: Instance of ParetoNavigator-class.
      :type method: ParetoNavigator

      :returns: Initial request.
      :rtype: ParetoNavigatorRequest



.. py:class:: ParetoNavigatorSolutionRequest(approx_solution: numpy.ndarray, pareto_optimal_solution: numpy.ndarray, objective_values: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle requests to see pareto optimal solution.

   :param approx_solution: The approximated solution received by navigation
   :type approx_solution: np.ndarray
   :param pareto_optimal_solution: A pareto optimal solution (decision variables).
   :type pareto_optimal_solution: np.ndarray
   :param objective_values: Objective vector.
   :type objective_values: np.ndarray


.. py:class:: ParetoNavigatorStopRequest(approx_solution: numpy.ndarray, final_solution: numpy.ndarray, objective_values: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle termination.

   :param approx_solution: The approximated solution received by navigation.
   :type approx_solution: np.ndarray
   :param final_solution: Solution (decision variables).
   :type final_solution: np.ndarray
   :param objective_values: Objective values.
   :type objective_values: np.ndarray


.. py:class:: ENautilus(pareto_front: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray, objective_names: Optional[List[str]] = None, variables: Optional[numpy.ndarray] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   The base class for interactive methods.

   :param problem: The problem being solved in an interactive method.
   :type problem: MOProblem

   .. py:method:: start() -> ENautilusInitialRequest


   .. py:method:: iterate(request: Union[ENautilusInitialRequest, ENautilusRequest]) -> Union[ENautilusRequest, ENautilusStopRequest]

      Perform the next logical iteration step based on the given request type.




   .. py:method:: handle_initial_request(request: ENautilusInitialRequest) -> ENautilusRequest

      Handles the initial request by parsing the response appropriately.




   .. py:method:: handle_request(request: ENautilusRequest) -> Union[ENautilusRequest, ENautilusStopRequest]

      Handles the intermediate requests.




   .. py:method:: calculate_representative_points(pareto_front: numpy.ndarray, subset_indices: List[int], n_points: int) -> numpy.ndarray

      Calculates the most representative points on the Pareto front. The points are clustered using k-means.

      :param pareto_front: The Pareto front.
      :type pareto_front: np.ndarray
      :param subset_indices: A list of indices representing the
                             subset of the points on the Pareto front for which the
                             representative points should be calculated.
      :type subset_indices: List[int]
      :param n_points: The number of representative points to be calculated.
      :type n_points: int

      :returns:

                A 2D array of the most representative points. If the
                    subset of Pareto efficient points is less than n_points, returns
                    the subset of the Pareto front.
      :rtype: np.ndarray


   .. py:method:: calculate_intermediate_points(preferred_point: numpy.ndarray, zbars: numpy.ndarray, n_iterations_left: int) -> numpy.ndarray

      Calculates the intermediate points between representative points an a preferred point.

      :param preferred_point: The preferred point, 1D array.
      :type preferred_point: np.ndarray
      :param zbars: The representative points, 2D array.
      :type zbars: np.ndarray
      :param n_iterations_left: The number of iterations left.
      :type n_iterations_left: int

      :returns: The intermediate points as a 2D array.
      :rtype: np.ndarray


   .. py:method:: calculate_bounds(pareto_front: numpy.ndarray, intermediate_points: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray]

      Calculate the new bounds of the reachable points on the Pareto
      optimal front from each of the intermediate points.

      :param pareto_front: The Pareto optimal front.
      :type pareto_front: np.ndarray
      :param intermediate_points: The current intermediate points as a 2D array.
      :type intermediate_points: np.ndarray

      :returns: The lower and upper bounds for each of the intermediate points.
      :rtype: Tuple[np.ndarray, np.ndarray]


   .. py:method:: calculate_distances(intermediate_points: numpy.ndarray, zbars: numpy.ndarray, nadir: numpy.ndarray) -> numpy.ndarray


   .. py:method:: calculate_reachable_point_indices(pareto_front: numpy.ndarray, lower_bounds: numpy.ndarray, upper_bounds: numpy.ndarray) -> List[int]

      Calculate the indices of the reachable Pareto optimal solutions
      based on lower and upper bounds.

      :returns: List of the indices of the reachable solutions.
      :rtype: List[int]



.. py:exception:: ENautilusException

   Bases: :py:obj:`Exception`

   Raised when an exception related to ENautilus is encountered.




.. py:class:: ENautilusInitialRequest(ideal: numpy.ndarray, nadir: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the initial preferences.



   .. py:method:: validator(response: Dict) -> None


   .. py:method:: init_with_method(method)
      :classmethod:



.. py:class:: ENautilusRequest(ideal: numpy.ndarray, nadir: numpy.ndarray, points: numpy.ndarray, lower_bounds: numpy.ndarray, upper_bounds: numpy.ndarray, n_iterations_left: int, distances: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the intermediate requests.



   .. py:method:: validator(response: Dict) -> None



.. py:class:: ENautilusStopRequest(preferred_point: numpy.ndarray, solution: Optional[numpy.ndarray] = None)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle termination.




.. py:function:: validate_preferences(n_objectives: int, response: Dict) -> None

   Validate decision maker's preferences.

   :param n_objectives: Number of objectives in problem.
   :type n_objectives: int
   :param response: Decision maker's response containing preference information.
   :type response: Dict

   :raises NautilusException: In case preference info is not valid.


.. py:class:: Nautilus(problem: desdeo_problem.problem.MOProblem, ideal: numpy.ndarray, nadir: numpy.ndarray, epsilon: float = 1e-06, objective_names: Optional[List[str]] = None, minimize: Optional[List[int]] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   Implements the basic NAUTILUS method as presented in |Miettinen_2010|.

   In NAUTILUS, starting from the nadir point,
   a solution is obtained at each iteration which dominates the previous one.
   Although only the last solution will be Pareto optimal, the decision maker never looses sight of the
   Pareto optimal set, and the search is oriented so that (s)he progressively focusses on the preferred part of
   the Pareto optimal set. Each new solution is obtained by minimizing an achievement scalarizing function including
   preferences about desired improvements in objective function values.

   The decision maker has **two possibilities** to provide her/his preferences:

   1. The decision maker can **rank** the objectives according to the **relative** importance of improving each current
   objective value.

   .. note::

      This ranking is not a global preference ranking of the objectives, but represents the local importance of
      improving each of the current objective values **at that moment**.

   2. The decision maker can specify **percentages** reflecting how (s)he would like to improve the current objective
   values, by answering to the following question:

   *"Assuming you have one hundred points available, how would you distribute
   them among the current objective values so that the more points you allocate, the more improvement on the
   corresponding current objective value is desired?"*

   After each iteration round, the decision maker specifies whether (s)he wishes to continue with the previous
   preference information, or define a new one.

   In addition to this, the decision maker can influence the solution finding process by taking a **step back** to
   previous iteration point. This enables the decision maker to provide new preferences and change the direction of
   solution seeking process. Furthermore, the decision maker can also take a **half-step** in case (s)he feels that a
   full step limits the reachable area of Pareto optimal set too much.

   NAUTILUS is specially suitable for avoiding  undesired anchoring effects, for example in negotiation support
   problems, or just as a means of finding an initial Pareto optimal solution for any interactive procedure.

   :param problem: Problem to be solved.
   :type problem: MOProblem
   :param ideal: The ideal objective vector of the problem.
   :type ideal: np.ndarray
   :param nadir: The nadir objective vector of the problem. This may also be the "worst" objective vector
                 provided by the Decision maker if the approximation of Nadir vector is not applicable or if
                 the Decision maker wishes to provide even worse objective vector than what the
                 approximated Nadir vector is.
   :type nadir: np.ndarray
   :param epsilon: A small number used in calculating the utopian point.
   :type epsilon: float
   :param objective_names: Names of the objectives. List must match the number of columns
                           in ideal.
   :type objective_names: Optional[List[str]], optional
   :param minimize: Multipliers for each objective. '-1' indicates maximization
                    and '1' minimization. Defaults to all objective values being
                    minimized.
   :type minimize: Optional[List[int]], optional

   :raises NautilusException: One or more dimension mismatches are encountered among the supplies arguments.

   .. py:method:: start() -> NautilusInitialRequest

      Start the solution process with initializing the first request.

      :returns: Initial request.
      :rtype: NautilusInitialRequest


   .. py:method:: iterate(request: Union[NautilusInitialRequest, NautilusRequest, NautilusStopRequest]) -> Union[NautilusRequest, NautilusStopRequest]

      Perform the next logical iteration step based on the given request type.

      :param request: Either initial or intermediate request.
      :type request: Union[NautilusInitialRequest, NautilusRequest]

      :returns: A new request with content depending on the Decision maker's
                preferences.
      :rtype: Union[NautilusRequest, NautilusStopRequest]


   .. py:method:: handle_initial_request(request: NautilusInitialRequest) -> NautilusRequest

      Handles the initial request by parsing the response appropriately.

      :param request: Initial request including Decision maker's initial preferences.
      :type request: NautilusInitialRequest

      :returns: New request with updated solution process information.
      :rtype: NautilusRequest


   .. py:method:: handle_request(request: NautilusRequest) -> Union[NautilusRequest, NautilusStopRequest]

      Handle Decision maker's requests after the first iteration round, so called **intermediate requests.**

      :param request: Intermediate request including Decision maker's response.
      :type request: NautilusRequest

      :returns: In case last iteration, request to stop the solution process.
                Otherwise, new request with updated solution process information.
      :rtype: Union[NautilusRequest, NautilusStopRequest]


   .. py:method:: calculate_preferential_factors(pref_method: int, pref_info: numpy.ndarray, nadir: numpy.ndarray, utopian: numpy.ndarray) -> numpy.ndarray

      Calculate preferential factors based on the Decision maker's preference information. These preferential
      factors are used as weights for objectives when solving an Achievement scalarizing function. The Decision maker
      (DM) has **two possibilities** to provide her/his preferences:

      1. The DM can rank the objectives according to the **relative** importance of improving each current objective
      value.

      .. note::

         This ranking is not a global preference ranking of the objectives, but represents the local importance of
         improving each of the current objective values **at that moment**.

      2. The DM can specify percentages reflecting how (s)he would like to improve the current objective values,
      by answering to the following question:

      *"Assuming you have one hundred points available, how would you distribute
      them among the current objective values so that the more points you allocate, the more improvement on the
      corresponding current objective value is desired?"*

      :param pref_method: Preference information method (either ranks (1) or percentages (2)).
      :type pref_method: int
      :param pref_info: Preference information on how the DM wishes to improve the values of each objective
                        function.
      :type pref_info: np.ndarray
      :param nadir: Nadir vector.
      :type nadir: np.ndarray
      :param utopian: Utopian vector.
      :type utopian: np.ndarray

      :returns: Weights assigned to each of the objective functions in achievement scalarizing function.
      :rtype: np.ndarray

      .. rubric:: Examples

      >>> pref_method = 1  # ranks
      >>> pref_info = np.array([2, 2, 1, 1])  # first and second objective are the most important to improve
      >>> nadir = np.array([-4.75, -2.87, -0.32, 9.71])
      >>> utopian = np.array([-6.34, -3.44, -7.5, 0.])
      >>> calculate_preferential_factors(pref_method, pref_info, nadir, utopian)
      array([0.31446541, 0.87719298, 0.13927577, 0.10298661])

      >>> pref_method = 2  # percentages
      >>> pref_info = np.array([10, 30, 40, 20])  # DM wishes to improve most the value of objective 3, then 2,4,1
      >>> nadir = np.array([-4.75, -2.87, -0.32, 9.71])
      >>> utopian = np.array([-6.34, -3.44, -7.5, 0.])
      >>> calculate_preferential_factors(pref_method, pref_info, nadir, utopian)
      array([6.28930818, 5.84795322, 0.34818942, 0.51493306])


   .. py:method:: solve_asf(ref_point: numpy.ndarray, x0: numpy.ndarray, preferential_factors: numpy.ndarray, nadir: numpy.ndarray, utopian: numpy.ndarray, objectives: Callable, variable_bounds: Optional[numpy.ndarray], method: Union[desdeo_tools.solver.ScalarSolver.ScalarMethod, str, None]) -> dict

      Solve Achievement scalarizing function.

      :param ref_point: Reference point.
      :type ref_point: np.ndarray
      :param x0: Initial values for decision variables.
      :type x0: np.ndarray
      :param preferential_factors: preferential factors on how much would the decision maker wish to improve
                                   the values of each objective function.
      :type preferential_factors: np.ndarray
      :param nadir: Nadir vector.
      :type nadir: np.ndarray
      :param utopian: Utopian vector.
      :type utopian: np.ndarray
      :param objectives: The objective function values for each input vector.
      :type objectives: np.ndarray
      :param variable_bounds: Lower and upper bounds of each variable
                              as a 2D numpy array. If undefined variables, None instead.
      :type variable_bounds: Optional[np.ndarray
      :param method: The optimization method the scalarizer should be minimized with
      :type method: Union[ScalarMethod, str, None

      :returns: 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.
      :rtype: Dict


   .. py:method:: calculate_iteration_point(itn: int, z_prev: numpy.ndarray, f_current: numpy.ndarray) -> numpy.ndarray

      Calculate next iteration point towards the Pareto optimal solution.

      :param itn: Number of iterations left.
      :type itn: int
      :param z_prev: Previous iteration point.
      :type z_prev: np.ndarray
      :param f_current: Current optimal objective vector.
      :type f_current: np.ndarray

      :returns: Next iteration point.
      :rtype: np.ndarray


   .. py:method:: calculate_bounds(objectives: Callable, n_objectives: int, x0: numpy.ndarray, epsilons: numpy.ndarray, bounds: Union[numpy.ndarray, None], constraints: Optional[Callable], method: Union[desdeo_tools.solver.ScalarSolver.ScalarMethod, str, None]) -> numpy.ndarray

      Calculate the new bounds using Epsilon constraint method.

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

      :returns: New lower bounds for objective functions.
      :rtype: new_lower_bounds (np.ndarray)


   .. py:method:: calculate_distance(z_current: numpy.ndarray, nadir: numpy.ndarray, f_current: numpy.ndarray) -> numpy.ndarray

      Calculates the distance from current iteration point to the Pareto optimal set.

      :param z_current: Current iteration point.
      :type z_current: np.ndarray
      :param nadir: Nadir vector.
      :type nadir: np.ndarray
      :param f_current: Current optimal objective vector.
      :type f_current: np.ndarray

      :returns: Distance to the Pareto optimal set.
      :rtype: np.ndarray



.. py:function:: validate_response(n_objectives: int, z_current: numpy.ndarray, nadir: numpy.ndarray, response: Dict, first_iteration_bool: bool) -> None

   Validate decision maker's response.

   :param n_objectives: Number of objectives.
   :type n_objectives: int
   :param z_current: Current iteration point.
   :type z_current: np.ndarray
   :param nadir: Nadir point.
   :type nadir: np.ndarray
   :param response: Decision maker's response containing preference information.
   :type response: Dict
   :param first_iteration_bool: Indicating whether the iteration round is the first one (True) or not (False).
   :type first_iteration_bool: bool

   :raises NautilusException: In case Decision maker's response is not valid.


.. py:function:: validate_n2_preferences(n_objectives: int, response: Dict) -> None

   Validate decision maker's preferences in NAUTILUS 2.

   :param n_objectives: Number of objectives in problem.
   :type n_objectives: int
   :param response: Decision maker's response containing preference information.
   :type response: Dict

   :raises NautilusException: In case preference info is not valid.


.. py:function:: validate_n_iterations(n_it: int) -> None

   Validate decision maker's preference for number of iterations.

   :param n_it: Number of iterations.
   :type n_it: int

   :raises NautilusException: If number of iterations given is not a positive integer greater than zero.


.. py:class:: NautilusV2(problem: desdeo_problem.problem.MOProblem, starting_point: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray, epsilon: float = 1e-06, objective_names: Optional[List[str]] = None, minimize: Optional[List[int]] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   Implements the NAUTILUS 2 method as presented in |Miettinen_2015|.

   Similarly to NAUTILUS, starting from the nadir point,
   a solution is obtained at each iteration which dominates the previous one.
   Although only the last solution will be Pareto optimal, the Decision Maker (DM) never looses sight of the
   Pareto optimal set, and the search is oriented so that (s)he progressively focusses on the preferred part of
   the Pareto optimal set. Each new solution is obtained by minimizing an achievement scalarizing function including
   preferences about desired improvements in objective function values.

   NAUTILUS 2 introduces a new preference handling technique which is easily understandable for the DM and allows
   the DM to conveniently control the solution process. Preferences are given as direction of improvement for
   objectives. In NAUTILUS 2, the DM has **three ways** to do this:

   1. The DM sets the direction of improvement directly.

   2. The DM defines the **improvement ratio** between two different objectives fi and fj.
      For example, if the DM wishes that the improvement of fi by one unit should be accompanied with the improvement
      of fj by θij units. Here, the DM selects an objective fi (i=1,…,k) and for each of the other objectives fj
      sets the value θij. Then, the direction of improvement is defined by

           ``δi=1 and δj=θij, j≠i.``

   3. As a generalization of the approach 2, the DM sets values of improvement ratios freely for some **selected
      pairs** of objective functions.

   As with NAUTILUS, after each iteration round, the decision maker specifies whether (s)he wishes to continue with the
   previous preference information, or define a new one.

   In addition to this, the decision maker can influence the solution finding process by taking a **step back** to the
   previous iteration point. This enables the decision maker to provide new preferences and change the direction of the
   solution seeking process. Furthermore, the decision maker can also take a **half-step** in case (s)he feels that a
   full step limits the reachable area of the Pareto optimal set too much.


   :param problem: Problem to be solved.
   :type problem: MOProblem
   :param starting_point: Objective vector used as a starting point for method.
   :type starting_point: np.ndarray
   :param ideal: The ideal objective vector of the problem being represented by the Pareto front.
   :type ideal: np.ndarray
   :param nadir: The nadir objective vector of the problem being represented by the Pareto front.
   :type nadir: np.ndarray
   :param epsilon: A small number used in calculating the utopian point. By default 1e-6.
   :type epsilon: float
   :param objective_names: Names of the objectives. The length of the list must match the
                           number of columns in ideal.
   :type objective_names: Optional[List[str]], optional
   :param minimize: Multipliers for each objective. '-1' indicates maximization
                    and '1' minimization. Defaults to all objective values being
                    minimized.
   :type minimize: Optional[List[int]], optional

   :raises NautilusException: One or more dimension mismatches are encountered among the supplies arguments.

   .. py:method:: start() -> NautilusInitialRequest

      Start the solution process with initializing the first request.

      :returns: Initial request.
      :rtype: NautilusInitialRequest


   .. py:method:: iterate(request: Union[NautilusInitialRequest, NautilusRequest, NautilusStopRequest]) -> Union[NautilusRequest, NautilusStopRequest]

      Perform the next logical iteration step based on the given request type.

      :param request: Either initial or intermediate request.
      :type request: Union[NautilusInitialRequest, NautilusRequest]

      :returns:

                A new request with content depending on the Decision maker's
                    preferences.
      :rtype: Union[NautilusRequest, NautilusStopRequest]


   .. py:method:: handle_initial_request(request: NautilusInitialRequest) -> NautilusRequest

      Handles the initial request by parsing the response appropriately.

      :param request: Initial request including Decision maker's initial preferences.
      :type request: NautilusInitialRequest

      :returns: New request with updated solution process information.
      :rtype: NautilusRequest


   .. py:method:: handle_request(request: NautilusRequest) -> Union[NautilusRequest, NautilusStopRequest]

      Handle Decision maker's requests after the first iteration round, so-called **intermediate requests.**

      :param request: Intermediate request including Decision maker's response.
      :type request: NautilusRequest

      :returns:

                In case of last iteration, request to stop the solution process.
                    Otherwise, new request with updated solution process information.
      :rtype: Union[NautilusRequest, NautilusStopRequest]


   .. py:method:: calculate_preferential_factors(n_objectives: int, pref_method: int, pref_info: numpy.ndarray) -> numpy.ndarray

      Calculate preferential factors based on decision maker's preference information.

      :param n_objectives: Number of objectives in problem.
      :type n_objectives: int
      :param pref_method: Preference information method, either: Direction of improvement (1), improvement ratios
                          between a selected objective and rest of the objectives (2), or improvement ratios freely
                          for some selected pairs of objectives (3).
      :type pref_method: int
      :param pref_info: Preference information on how the DM wishes to improve the values of each objective
                        function. **See the examples below**.
      :type pref_info: np.ndarray

      :returns: Direction of improvement. Used as weights assigned to each of the objective functions in the
                achievement scalarizing function.
      :rtype: np.ndarray

      .. rubric:: Examples

      >>> n_objectives = 4
      >>> pref_method = 1  # deltas directly
      >>> pref_info = np.array([1, 2, 1, 2]),  # second and fourth objective are the most important to improve
      >>> calculate_preferential_factors(n_objectives, pref_method, pref_info)
      np.array([1, 2, 1, 2])

      >>> n_objectives = 4
      >>> pref_method = 2  # improvement ratios between one selected objective and each other objective
      >>> pref_info = np.array([1, 1.5, (7/3), 0.5])  # first objective's ratio is set to one
      >>> calculate_preferential_factors(n_objectives, pref_method, pref_info)
      np.array([1, 1.5, (7/3), 0.5])

      >>> n_objectives = 4
      >>> pref_method = 3  # improvement ratios between freely selected pairs of objectives
      # format the tuples like this: (('index of objective', 'index of objective'), 'improvement ratio between the objectives')
      >>> pref_info = np.array([((1, 2), 0.5), ((3, 4), 1), ((2, 3), 1.5)], dtype=object)
      >>> calculate_preferential_factors(n_objectives, pref_method, pref_info)
      np.array([1., 0.5, 0.75, 0.75])

      .. note::

         Remember to specify "dtype=object" in **pref_info** array when using preference
             method 3.


   .. py:method:: calculate_doi(n_objectives: int, pref_info: numpy.ndarray) -> numpy.ndarray

      Calculate direction of improvement based on improvement ratios between pairs of objective functions.

      :param n_objectives: Number of objectives.
      :type n_objectives: int
      :param pref_info: Preference information on how the DM wishes to improve the values of each objective
                        function.
      :type pref_info: np.ndarray

      :returns: Direction of improvement.
      :rtype: np.ndarray


   .. py:method:: solve_asf(ref_point: numpy.ndarray, x0: numpy.ndarray, preferential_factors: numpy.ndarray, nadir: numpy.ndarray, utopian: numpy.ndarray, objectives: Callable, variable_bounds: Optional[numpy.ndarray] = None, method: Union[desdeo_tools.solver.ScalarSolver.ScalarMethod, str, None] = None) -> dict

      Solve achievement scalarizing function.

      :param ref_point: Reference point.
      :type ref_point: np.ndarray
      :param x0: Initial values for decision variables.
      :type x0: np.ndarray
      :param preferential_factors: Preferential factors indicating how much would the decision maker wish to
                                   improve the values of each objective function.
      :type preferential_factors: np.ndarray
      :param nadir: Nadir vector.
      :type nadir: np.ndarray
      :param utopian: Utopian vector.
      :type utopian: np.ndarray
      :param objectives: The objective function values for each input vector.
      :type objectives: np.ndarray
      :param variable_bounds: Lower and upper bounds of each variable
                              as a 2D numpy array. If undefined variables, None instead.
      :type variable_bounds: Optional[np.ndarray]
      :param method: The optimization method the scalarizer should be minimized with.
      :type method: Union[ScalarMethod, str, None]

      :returns: 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.
      :rtype: Dict


   .. py:method:: calculate_iteration_point(itn: int, z_prev: numpy.ndarray, f_current: numpy.ndarray) -> numpy.ndarray

      Calculate next iteration point towards the Pareto optimal solution.

      :param itn: Number of iterations left.
      :type itn: int
      :param z_prev: Previous iteration point.
      :type z_prev: np.ndarray
      :param f_current: Current optimal objective vector.
      :type f_current: np.ndarray

      :returns: Next iteration point.
      :rtype: np.ndarray


   .. py:method:: calculate_bounds(objectives: Callable, n_objectives: int, x0: numpy.ndarray, epsilons: numpy.ndarray, bounds: Union[numpy.ndarray, None], constraints: Optional[Callable], method: Union[desdeo_tools.solver.ScalarSolver.ScalarMethod, str, None]) -> numpy.ndarray

      Calculate the new bounds using Epsilon constraint method.

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

      :returns: New lower bounds for objective functions.
      :rtype: np.ndarray


   .. py:method:: calculate_distance(z_current: numpy.ndarray, starting_point: numpy.ndarray, f_current: numpy.ndarray) -> numpy.ndarray

      Calculates the distance from current iteration point to the Pareto optimal set.

      :param z_current: Current iteration point.
      :type z_current: np.ndarray
      :param starting_point: Starting iteration point.
      :type starting_point: np.ndarray
      :param f_current: Current optimal objective vector.
      :type f_current: np.ndarray

      :returns: Distance to the Pareto optimal set.
      :rtype: np.ndarray



.. py:exception:: NautilusException

   Bases: :py:obj:`Exception`

   Raised when an exception related to Nautilus is encountered.


.. py:class:: NautilusInitialRequest(ideal: numpy.ndarray, nadir: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the Decision maker's initial preferences for the first iteration round.

   :param ideal: Ideal vector.
   :type ideal: np.ndarray
   :param nadir: Nadir vector.
   :type nadir: np.ndarray

   .. py:method:: init_with_method(method: desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod)
      :classmethod:

      Initialize request with given instance of Nautilus method.

      :param method: Instance of Nautilus-class.
      :type method: Nautilus

      :returns: Initial request.
      :rtype: NautilusInitialRequest



.. py:class:: NautilusRequest(z_current: numpy.ndarray, nadir: numpy.ndarray, lower_bounds: numpy.ndarray, upper_bounds: numpy.ndarray, distance: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the Decision maker's preferences after the first iteration round.


.. py:class:: NautilusStopRequest(x_h: numpy.ndarray, f_h: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle termination.

   :param x_h: Solution (decision variables).
   :type x_h: np.ndarray
   :param f_h: Objective vector.
   :type f_h: np.ndarray


.. py:class:: NautilusNavigator(pareto_front: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray, decision_variables: Optional[numpy.ndarray] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   Implementations of the NAUTILUS Navigator algorithm.

   :param pareto_front: A two dimensional numpy array
                        representing a Pareto front with objective vectors on each of its
                        rows.
   :type pareto_front: np.ndarray
   :param ideal: The ideal objective vector of the problem
                 being represented by the Pareto front.
   :type ideal: np.ndarray
   :param nadir: The nadir objective vector of the problem
                 being represented by the Pareto front.
   :type nadir: np.ndarray
   :param decision_variables: Two dimensinoal numpy
                              array of decision variables
                              that can be optionally supplied. The i'th vector in
                              decision_variables should result in the i'th objective
                              vector in pareto_front. Defaults to None.
   :type decision_variables: Optional[np.ndarray]

   :raises NautilusNavigatorException: One or more dimension mismatches are
   :raises encountered among the supplies arguments.:

   .. py:method:: start() -> NautilusNavigatorRequest

      Returns the first Request object to begin iterating.

      :returns: The Request.
      :rtype: NautilusNavigatorRequest


   .. py:method:: iterate(request: NautilusNavigatorRequest) -> NautilusNavigatorRequest

      Perform the next logical step based on the response in the
      Request.


   .. py:method:: handle_request(request: NautilusNavigatorRequest) -> Union[NautilusNavigatorRequest, NautilusNavigatorStopRequest]

      Handle the Request and its contents.

      :param request: A Request with a defined response.
      :type request: NautilusNavigatorRequest

      :returns: Some of the contents of the response are invalid.
      :rtype: NautilusNavigatorRequest


   .. py:method:: update(ref_point: numpy.ndarray, speed: int, go_to_previous: bool, stop: bool, step_number: Optional[int] = None, nav_point: Optional[numpy.ndarray] = None, lower_bounds: Optional[numpy.ndarray] = None, upper_bounds: Optional[numpy.ndarray] = None, user_bounds: Optional[numpy.ndarray] = None, reachable_idx: Optional[List[int]] = None, distance: Optional[float] = None, steps_remaining: Optional[int] = None) -> Optional[NautilusNavigatorRequest]

      Update the internal state of self.

      :param ref_point: A reference point given by a decision maker.
      :type ref_point: np.ndarray
      :param speed: An integer value between 1-5 indicating the navigation speed.
      :type speed: int
      :param go_to_previous: If True, the parameters indicate the state
                             of a previous state, and the request is handled accordingly.
      :type go_to_previous: bool
      :param stop: If the navigation should stop. If True, returns a request with self's current state.
      :type stop: bool
      :param step_number: Current step number, or
                          previous step number if go_to_previous is True. Defaults to None.
      :type step_number: Optional[int], optional
      :param nav_point: The current
                        navigation point. Relevant if go_to_previous is True. Defaults to
                        None.
      :type nav_point: Optional[np.ndarray], optional
      :param lower_bounds: Lower bounds of
                           the reachable objective vector values. Relevant if go_to_previous
                           is True. Defaults to None.
      :type lower_bounds: Optional[np.ndarray], optional
      :param upper_bounds: Upper bounds of
                           the reachable objective vector values. Relevant if go_to_previous
                           is True. Defaults to None.
      :type upper_bounds: Optional[np.ndarray], optional
      :param user_bounds: The user given bounds for each objective.
                          The reachable lower limit with attempt to not exceed the given bounds for each
                          objective value.
      :type user_bounds: Optional[np.ndarray], optional
      :param reachable_idx: Indices of the
                            reachable Pareto optimal solutions. Relevant if go_to_previous is
                            True. Defaults to None.
      :type reachable_idx: Optional[List[int]], optional
      :param distance: Distance to the Pareto
                       optimal front. Relevant if go_to_previous is True. Defaults to
                       None.
      :type distance: Optional[float], optional
      :param steps_remaining: Remaining steps in the
                              navigation. Relevant if go_to_previous is True. Defaults to None.
      :type steps_remaining: Optional[int], optional

      :returns: Some of the given parameters are erroneous.
      :rtype: NautilusNavigatorRequest


   .. py:method:: calculate_reachable_point_indices(pareto_front: numpy.ndarray, lower_bounds: numpy.ndarray, upper_bounds: numpy.ndarray) -> List[int]

      Calculate the indices of the reachable Pareto optimal solutions
      based on lower and upper bounds.

      :returns: List of the indices of the reachable solutions.
      :rtype: List[int]


   .. py:method:: solve_nautilus_asf_problem(pareto_f: numpy.ndarray, subset_indices: List[int], ref_point: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray, user_bounds: numpy.ndarray) -> int
      :staticmethod:

      Forms and solves the achievement scalarizing function to find the
      closest point on the Pareto optimal front to the given reference
      point.

      :param pareto_f: The whole Pareto optimal front.
      :type pareto_f: np.ndarray
      :param subset_indices: Indices of the currently reachable solutions.
      :type subset_indices: [type]
      :param ref_point: The reference point indicating a decision
                        maker's preference.
      :type ref_point: np.ndarray
      :param ideal: Ideal point.
      :type ideal: np.ndarray
      :param nadir: Nadir point.
      :type nadir: np.ndarray
      :param user_bounds: 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.
      :type user_bounds: np.ndarray

      :returns: Index of the closest point according the minimized value of the ASF.
      :rtype: int


   .. py:method:: calculate_navigation_point(projection: numpy.ndarray, nav_point: numpy.ndarray, steps_remaining: int) -> numpy.ndarray

      Calculate a new navigation point based on the projection of the
      preference point to the Pareto optimal front.

      :param projection: The point on the Pareto optimal front
                         closest to the preference point given by a decision maker.
      :type projection: np.ndarray
      :param nav_point: The previous navigation point.
      :type nav_point: np.ndarray
      :param steps_remaining: How many steps are remaining in the navigation.
      :type steps_remaining: int

      :returns: The new navigation point.
      :rtype: np.ndarray


   .. py:method:: calculate_bounds(pareto_front: numpy.ndarray, nav_point: numpy.ndarray, user_bounds: numpy.ndarray, previous_lb: numpy.ndarray, previous_ub: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray]
      :staticmethod:

      Calculate the new bounds of the reachable points on the Pareto
      optimal front from a navigation point.

      :param pareto_front: The Pareto optimal front.
      :type pareto_front: np.ndarray
      :param nav_point: The current navigation point.
      :type nav_point: np.ndarray
      :param user_bounds: 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.
      :type user_bounds: np.ndarray
      :param previous_lb: If no new lower bound can be found for an objective, this value is used.
      :type previous_lb: np.ndarray
      :param previous_ub: If no new upper bound can be found for an objective, this value is used.
      :type previous_ub: np.ndarray

      :returns: The lower and upper bounds.
      :rtype: Tuple[np.ndarray, np.ndarray]


   .. py:method:: calculate_distance(nav_point: numpy.ndarray, projection: numpy.ndarray, nadir: numpy.ndarray) -> float

      Calculate the distance to the Pareto optimal front from a
      navigation point. The distance is calculated to the supplied
      projection which is assumed to lay on the front.

      :param nav_point: The navigation point.
      :type nav_point: np.ndarray
      :param projection: The point of the Pareto optimal front the distance is calculated to.
      :type projection: np.ndarray
      :param nadir: The nadir point of the Pareto optimal set.
      :type nadir: np.ndarray

      :returns: The distance.
      :rtype: float



.. py:exception:: NautilusNavigatorException

   Bases: :py:obj:`Exception`

   Raised when an exception related to NAUTILUS Navigator is encountered.



.. py:class:: NautilusNavigatorRequest(ideal: numpy.ndarray, nadir: numpy.ndarray, reachable_lb: numpy.ndarray, reachable_ub: numpy.ndarray, user_bounds: List[float], reachable_idx: List[int], step_number: int, steps_remaining: int, distance: float, allowed_speeds: List[int], current_speed: int, navigation_point: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   Request to handle interactions with NAUTILUS Navigator. See the
   NautilusNavigator class for further details.

   .. py:method:: init_with_method(method)
      :classmethod:


   .. py:method:: validator(response: Dict) -> None



.. py:class:: NIMBUS(problem: Union[desdeo_problem.problem.MOProblem, desdeo_problem.problem.DiscreteDataProblem], scalar_method: Optional[Union[desdeo_tools.solver.ScalarSolver.ScalarMethod, str]] = 'scipy_de', starting_point: Optional[numpy.ndarray] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   Implements the synchronous NIMBUS algorithm.

   :param problem: The problem to be solved.
   :type problem: MOProblem
   :param scalar_method: The method used to solve
                         the various ASF minimization problems present in the method. Defaults to 'scipy_de' (differential evolution).
   :type scalar_method: Optional[Union[ScalarMethod, str]], optional
   :param starting_point: The initial solution (objectives) to start classification from.
                          If None, a neutral starting point will be computed.
   :type starting_point: Optional[np.ndarray], optional

   .. note::

      When a starting point is supplied, decision variables of that point will be approximated to be the variables of the
      solution closest to the starting point. In other words, the decision variables associated to the initial point may be
      inaccurate!

   .. py:method:: start() -> Tuple[NimbusClassificationRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Return the first request to start iterating NIMBUS.

      :returns: The first request and
                and a plot request to visualize relevant data.
      :rtype: Tuple[NimbusClassificationRequest, SimplePlotRequest]


   .. py:method:: request_classification() -> Tuple[NimbusClassificationRequest, desdeo_tools.interaction.request.SimplePlotRequest]


   .. py:method:: create_plot_request(objectives: numpy.ndarray, msg: str) -> desdeo_tools.interaction.request.SimplePlotRequest

      Used to create a plot request for visualizing objective values.

      :param objectives: A 2D numpy array containing objective vectors to be visualized.
      :type objectives: np.ndarray
      :param msg: A message to be displayed in the context of a visualization.
      :type msg: str

      :returns: A plot request to create a visualization.
      :rtype: SimplePlotRequest


   .. py:method:: handle_classification_request(request: NimbusClassificationRequest) -> Tuple[NimbusSaveRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Handles a classification request.

      :param request: A classification request with the
                      response attribute set.
      :type request: NimbusClassificationRequest

      :returns: A NIMBUS save request and a plot request
                with the solutions the decision maker can choose from to save for alter use.
      :rtype: Tuple[NimbusSaveRequest, SimplePlotRequest]


   .. py:method:: handle_save_request(request: NimbusSaveRequest) -> Tuple[NimbusIntermediateSolutionsRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Handles a save request.

      :param request: A save request with the response attribute set.
      :type request: NimbusSaveRequest

      :returns: Return an
                intermediate solution request where the decision maker can specify whether they
                would like to see intermediate solution between two previously computed solutions.
                The plot request has the available solutions.
      :rtype: Tuple[NimbusIntermediateSolutionsRequest, SimplePlotRequest]


   .. py:method:: handle_intermediate_solutions_request(request: NimbusIntermediateSolutionsRequest) -> Tuple[Union[NimbusSaveRequest, NimbusMostPreferredRequest], desdeo_tools.interaction.request.SimplePlotRequest]

      Handles an intermediate solutions request.

      :param request: A NIMBUS intermediate solutions
                      request with the response attribute set.
      :type request: NimbusIntermediateSolutionsRequest

      :returns: Return either a save request or a preferred solution request. The former is returned if the
                decision maker wishes to see intermediate points, the latter otherwise. Also a plot request is
                returned with the solutions available in it.
      :rtype: Tuple[Union[NimbusSaveRequest, NimbusMostPreferredRequest], SimplePlotRequest,]


   .. py:method:: handle_most_preferred_request(request: NimbusMostPreferredRequest) -> Tuple[Union[NimbusClassificationRequest, NimbusStopRequest], desdeo_tools.interaction.request.SimplePlotRequest]

      Handles a preferred solution request.

      :param request: A NIMBUS preferred solution request with the
                      response attribute set.
      :type request: NimbusMostPreferredRequest

      :returns: Return a classification request if the decision maker wishes to continue. If the
                decision maker wishes to stop, return a stop request. Also return a plot
                request with all the solutions saved so far.
      :rtype: Tuple[Union[NimbusClassificationRequest, NimbusStopRequest], SimplePlotRequest]


   .. py:method:: request_stop() -> Tuple[NimbusStopRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Create a NimbusStopRequest based on self.

      :returns: A stop request and a plot
                request with the final solution chosen in it.
      :rtype: Tuple[NimbusStopRequest, SimplePlotRequest]


   .. py:method:: request_most_preferred_solution(solutions: numpy.ndarray, objectives: numpy.ndarray) -> Tuple[NimbusMostPreferredRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Create a NimbusMostPreferredRequest.

      :param solutions: A 2D numpy array of decision variable vectors.
      :type solutions: np.ndarray
      :param objectives: A 2D numpy array of objective value vectors.
      :type objectives: np.ndarray

      :returns: The requests based on the given arguments.
      :rtype: Tuple[NimbusMostPreferredRequest, SimplePlotRequest]

      .. note::

         The 'i'th decision variable vector in `solutions` should correspond to the 'i'th objective value vector in
         `objectives`.


   .. py:method:: compute_intermediate_solutions(solutions: numpy.ndarray, n_desired: int) -> Tuple[NimbusSaveRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Computes intermediate solution between two solutions computed earlier.

      :param solutions: The solutions between which the intermediate solutions should
                        be computed.
      :type solutions: np.ndarray
      :param n_desired: The number of intermediate solutions desired.
      :type n_desired: int

      :raises NimbusException:

      :returns: A save request with the computed intermediate
                points, and a plot request to visualize said points.
      :rtype: Tuple[NimbusSaveRequest, SimplePlotRequest]


   .. py:method:: save_solutions_to_archive(objectives: numpy.ndarray, decision_variables: numpy.ndarray, indices: List[int]) -> Tuple[NimbusIntermediateSolutionsRequest, None]

      Save solutions to the archive. Saves also the corresponding objective function
      values.

      :param objectives: Available objectives.
      :type objectives: np.ndarray
      :param decision_variables: Available solutions.
      :type decision_variables: np.ndarray
      :param indices: Indices of the solutions to be saved.
      :type indices: List[int]

      :returns: An intermediate solutions request asking the
                decision maker whether they would like to generate intermediata solutions between two existing solutions.
                Also returns a plot request to visualize the available solutions between which the intermediate solutions
                should be computed.
      :rtype: Tuple[NimbusIntermediateSolutionsRequest, None]


   .. py:method:: calculate_new_solutions(number_of_solutions: int, levels: numpy.ndarray, improve_inds: numpy.ndarray, improve_until_inds: numpy.ndarray, acceptable_inds: numpy.ndarray, impaire_until_inds: numpy.ndarray, free_inds: numpy.ndarray) -> Tuple[NimbusSaveRequest, desdeo_tools.interaction.request.SimplePlotRequest]

      Calculates new solutions based on classifications supplied by the decision maker by
          solving ASF problems.

      :param number_of_solutions: Number of solutions, should be between 1 and 4.
      :type number_of_solutions: int
      :param levels: Aspiration and upper bounds relevant to the some of the classifications.
      :type levels: np.ndarray
      :param improve_inds: Indices corresponding to the objectives which should be improved.
      :type improve_inds: np.ndarray
      :param improve_until_inds: Like above, but improved until an aspiration level is reached.
      :type improve_until_inds: np.ndarray
      :param acceptable_inds: Indices of objectives which are acceptable as they are now.
      :type acceptable_inds: np.ndarray
      :param impaire_until_inds: Indices of objectives which may be impaired until an upper limit is
                                 reached.
      :type impaire_until_inds: np.ndarray
      :param free_inds: Indices of objectives which may change freely.
      :type free_inds: np.ndarray

      :returns: A save request with the newly computed solutions, and
                a plot request to visualize said solutions.
      :rtype: Tuple[NimbusSaveRequest, SimplePlotRequest]


   .. py:method:: update_current_solution(solutions: numpy.ndarray, objectives: numpy.ndarray, index: int) -> None

      Update the state of self with a new current solution and the corresponding objective values. This solution is
      used in the classification phase of synchronous NIMBUS.

      :param solutions: A 2D numpy array of decision variable vectors.
      :type solutions: np.ndarray
      :param objectives: A 2D numpy array of objective value vectors.
      :type objectives: np.ndarray
      :param index: The index of the solution in `solutions` and `objectives`.
      :type index: int

      :returns: The requests based on the given arguments.
      :rtype: Tuple[NimbusMostPreferredRequest, SimplePlotRequest]

      .. note::

         The 'i'th decision variable vector in `solutions` should correspond to the 'i'th objective value vector in
         `objectives`.


   .. py:method:: iterate(request: Union[NimbusClassificationRequest, NimbusSaveRequest, NimbusIntermediateSolutionsRequest, NimbusMostPreferredRequest, NimbusStopRequest]) -> Tuple[Union[NimbusClassificationRequest, NimbusSaveRequest, NimbusIntermediateSolutionsRequest], Union[desdeo_tools.interaction.request.SimplePlotRequest, None]]

      Implements a finite state machine to iterate over the different steps defined in Synchronous NIMBUS based on a supplied request.

      :param request: A request based on the next step in the NIMBUS algorithm is taken.
      :type request: Union[NimbusClassificationRequest,NimbusSaveRequest,NimbusIntermediateSolutionsRequest,NimbusMostPreferredRequest,NimbusStopRequest,]

      :raises NimbusException: If a wrong type of request is supplied based on the current state NIMBUS is in.

      :returns: The next logically sound request.
      :rtype: Tuple[Union[NimbusClassificationRequest,NimbusSaveRequest,NimbusIntermediateSolutionsRequest,],Union[SimplePlotRequest, None],]



.. py:class:: NimbusClassificationRequest(method: NIMBUS, ref: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request to handle the classification of objectives in the synchronous NIMBUS method.

   :param method: The instance of the NIMBUS method the request should be initialized for.
   :type method: NIMBUS
   :param ref: Objective values used as a reference the decision maker is classifying the objectives.
   :type ref: np.ndarray

   .. attribute:: self._valid_classifications

      The valid classifications. Defaults is ['<', '<=', '=', '>=', '0']

      :type: List[str]

   .. py:method:: validator(response: Dict) -> None

      Validates a dictionary containing the response of a decision maker. Should contain the keys
      'classifications', 'levels', and 'number_of_solutions'.

      'classifications' should be a list of strings, where the number of
      elements is equal to the number of objectives being classified, and
      the elements are found in `_valid_classifications`. 'levels' should
      have either aspiration levels or bounds for each objective depending
      on that objective's classification. 'number_of_solutions' should be
      an integer between 1 and 4 indicating the number of intermediate solutions to be
      computed.

      :param response: See the documentation for `validator`.
      :type response: Dict

      :raises NimbusException: Some discrepancy is encountered in the parsing of the response.



.. py:exception:: NimbusException

   Bases: :py:obj:`Exception`

   Risen when an error related to NIMBUS is encountered.




.. py:class:: NimbusIntermediateSolutionsRequest(solution_vectors: List[numpy.ndarray], objective_vectors: List[numpy.ndarray])

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request to handle the computation of intermediate points between two previously computed points.

   :param solution_vectors: A list of numpy arrays each representing a decision variable vector.
   :type solution_vectors: List[np.ndarray]
   :param objective_vectors: A list of numpy arrays each representing an objective vector.
   :type objective_vectors: List[np.ndarray]

   .. note::

      The objective vector at position 'i' in `objective_vectors` should correspond to the decision variables at
      position 'i' in `solution_vectors`. Only the two first entries in each of the lists is relevant. The
      rest is ignored.

   .. py:method:: validator(response: Dict)

      Validates a response dictionary. The dictionary should contain the keys 'indices' and 'number_of_solutions'.

      'indices' should be a list of integers representing an index to the
      lists `solutions_vectors` and `objective_vectors`. 'number_of_solutions' should be an integer greater or equal
      to 1.

      :param response: See the documentation for `validator`.
      :type response: Dict

      :raises NimbusException: Some discrepancy is encountered in the parsing of `response`.



.. py:class:: NimbusMostPreferredRequest(solution_vectors: List[numpy.ndarray], objective_vectors: List[numpy.ndarray])

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request to handle the indication of a preferred point.

   :param solution_vectors: A list of numpy arrays each representing a decision variable vector.
   :type solution_vectors: List[np.ndarray]
   :param objective_vectors: A list of numpy arrays each representing an objective vector.
   :type objective_vectors: List[np.ndarray]

   .. note::

      The objective vector at position 'i' in `objective_vectors` should correspond to the decision variables at
      position 'i' in `solution_vectors`. Only the two first entries in each of the lists are relevant. The preferred
      solution will be selected from `objective_vectors`.

   .. py:method:: validator(response: Dict)

      Validates a response dictionary. The dictionary should contain the keys 'index' and 'continue'.

      'index' is an integer and should indicate the index of the preferred solution is `objective_vectors`.
      'continue' is a boolean and indicates whether to stop or continue the iteration of Synchronous NIMBUS.

      :param response: See the documentation for `validator`.
      :type response: Dict

      :raises NimbusException: Some discrepancy is encountered in the parsing of `response`.



.. py:class:: NimbusSaveRequest(solution_vectors: List[numpy.ndarray], objective_vectors: List[numpy.ndarray])

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request to handle archiving of the solutions computed with NIMBUS.

   :param solution_vectors: A list of numpy arrays each representing a decision variable vector.
   :type solution_vectors: List[np.ndarray]
   :param objective_vectors: A list of numpy arrays each representing an objective vector.
   :type objective_vectors: List[np.ndarray]

   .. note::

      The objective vector at position 'i' in `objective_vectors` should correspond to the decision variables at
      position 'i' in `solution_vectors`.

   .. py:method:: validator(response: Dict) -> None

      Validates a response dictionary. The dictionary should contain the keys 'indices'.

      'indices' should be a list of integers representing an index to the
      lists `solutions_vectors` and `objective_vectors`.

      :param response: See the documentation for `validator`.
      :type response: Dict

      :raises NimbusException: Some discrepancy is encountered in the parsing of `response`.



.. py:class:: NimbusStopRequest(solution_final: numpy.ndarray, objective_final: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request to handle the termination of Synchronous NIMBUS.

   :param solutions_final: A numpy array containing the final decision variable values.
   :type solutions_final: np.ndarray
   :param objective_final: A numpy array containing the final objective variables which correspond to
   :type objective_final: np.ndarray
   :param `solution_final`.:

   .. note:: This request expects no response.


.. py:exception:: RPMException

   Bases: :py:obj:`Exception`

   Raised when an exception related to Reference Point Method (RFM) is encountered.


.. py:class:: RPMInitialRequest(ideal: numpy.ndarray, nadir: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the Decision Maker's initial preferences for the first iteration round.

   .. py:method:: init_with_method(method: desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod)
      :classmethod:

      Initialize request with given instance of ReferencePointMethod.

      :param method: Instance of ReferencePointMethod-class.
      :type method: ReferencePointMethod

      :returns: Initial request.
      :rtype: RPMInitialRequest



.. py:class:: RPMRequest(f_current: numpy.ndarray, f_additionals: numpy.ndarray, ideal: numpy.ndarray, nadir: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle the Decision Maker's preferences after the first iteration round.

   :param f_current: Current solution.
   :type f_current: np.ndarray
   :param f_additionals: Additional solutions.
   :type f_additionals: np.ndarray
   :param ideal: Idea vector.
   :type ideal: np.ndarray
   :param nadir: Nadir vector.
   :type nadir: np.ndarray


.. py:class:: RPMStopRequest(x_h: numpy.ndarray, f_h: numpy.ndarray)

   Bases: :py:obj:`desdeo_tools.interaction.request.BaseRequest`

   A request class to handle termination.


.. py:class:: ReferencePointMethod(problem: Union[desdeo_problem.problem.MOProblem, desdeo_problem.problem.DiscreteDataProblem], ideal: numpy.ndarray, nadir: numpy.ndarray, epsilon: float = 1e-06, objective_names: Optional[List[str]] = None, minimize: Optional[List[int]] = None)

   Bases: :py:obj:`desdeo_mcdm.interactive.InteractiveMethod.InteractiveMethod`

   Implements the Reference Point Method as presented in |Wierzbicki_1982|.

   In the Reference Point Method, the Decision Maker (DM) specifies **desirable aspiration levels** for objective
   functions. Vectors formed of these aspiration levels are then used to derive scalarizing functions having minimal
   values at weakly, properly or Pareto optimal solutions. It is important that reference points are intuitive and easy
   for the DM to specify, their consistency is not an essential requirement. Before the solution process starts, some
   information is given to the DM about the problem. If possible, the ideal objective vector and the
   (approximated) nadir objective vector are presented.

   At each iteration, the DM is asked to give desired aspiration levels for the objective functions. Using this
   information to formulate a **reference point**, achievement function is minimized and a (weakly, properly or) Pareto
   optimal solution is obtained. This solution is then presented to the DM. In addition, k other (weakly,
   properly or) Pareto optimal solutions are calculated using **perturbed reference points**, where k is the
   number of objectives in the problem. The alternative solutions are also presented to the DM. If (s)he finds any of
   the k + 1 solutions satisfactory, the solution process is ended. Otherwise, the DM is asked to present a new
   reference point and the iteration described above is repeated.

   The idea in perturbed reference points is that the DM gets **better understanding** of the possible solutions around
   the current solution. If the reference point is far from the Pareto optimal set, the DM gets a **wider** description
   of the Pareto optimal set and if the reference point is near the Pareto optimal set, then a **finer** description of
   the Pareto optimal set is given.

   In this method, the DM has to specify aspiration levels and compare objective vectors. The DM is **free to change**
   her/his mind during the process and can direct the solution process without being forced to understand complicated
   concepts and their meaning. On the other hand, the method does not necessarily help the DM to find more satisfactory
   solutions.

   :param problem: Problem to be solved.
   :type problem: MOProblem
   :param ideal: The ideal objective vector of the problem.
   :type ideal: np.ndarray
   :param nadir: The nadir objective vector of the problem. This may also be the "worst" objective vector
                 provided by the Decision Maker if the approximation of Nadir vector is not applicable or if
                 the Decision Maker wishes to provide even worse objective vector than what the
                 approximated Nadir vector is.
   :type nadir: np.ndarray
   :param epsilon: A small number used in calculating the utopian point.
   :type epsilon: float
   :param epsilon: A small number used in calculating the utopian point. Default value is 1e-6.
   :type epsilon: float
   :param objective_names: Names of the objectives. The length of the list must match the
                           number of elements in ideal vector.
   :type objective_names: Optional[List[str]], optional
   :param minimize: Multipliers for each objective. '-1' indicates maximization
                    and '1' minimization. Defaults to all objective values being
                    minimized.
   :type minimize: Optional[List[int]], optional

   :raises RPMException: Dimensions of ideal, nadir, objective_names, and minimize-list do not match.

   .. py:method:: start() -> RPMInitialRequest

      Start the solution process with initializing the first request.

      :returns: Initial request.
      :rtype: RPMInitialRequest


   .. py:method:: iterate(request: Union[RPMInitialRequest, RPMRequest, RPMStopRequest]) -> Union[RPMRequest, RPMStopRequest]

      Perform the next logical iteration step based on the given request type.

      :param request: Either initial or intermediate request.
      :type request: Union[RPMInitialRequest, RPMRequest]

      :returns: A new request with content depending on the Decision Maker's
                preferences.
      :rtype: Union[RPMRequest, RPMStopRequest]


   .. py:method:: handle_initial_request(request: RPMInitialRequest) -> RPMRequest

      Handles the initial request by parsing the response appropriately.

      :param request: Initial request including the Decision Maker's initial preferences.
      :type request: RPMInitialRequest

      :returns: New request with updated solution process information.
      :rtype: RPMRequest


   .. py:method:: handle_request(request: RPMRequest) -> Union[RPMRequest, RPMStopRequest]

      Handle the Decision Maker's requests after the first iteration round, so-called **intermediate requests.**

      :param request: Intermediate request including the Decision Maker's response.
      :type request: RPMRequest

      :returns: In case last iteration, request to stop the solution process.
                Otherwise, new request with updated solution process information.
      :rtype: Union[RPMRequest, RPMStopRequest]


   .. py:method:: calculate_prp(ref_point: numpy.ndarray, f_current: numpy.ndarray) -> numpy.ndarray

      Calculate perturbed reference points.

      :param ref_point: Current reference point.
      :type ref_point: np.ndarray
      :param f_current: Current solution.
      :type f_current: np.ndarray

      :returns: Perturbed reference points.
      :rtype: np.ndarray


   .. py:method:: solve_asf(ref_point: numpy.ndarray, x0: numpy.ndarray, preferential_factors: numpy.ndarray, nadir: numpy.ndarray, utopian: numpy.ndarray, objectives: Callable, variable_vectors: Optional[numpy.ndarray] = None, variable_bounds: Optional[numpy.ndarray] = None, method: Union[desdeo_tools.solver.ScalarSolver.ScalarMethod, str, None] = None) -> dict

      Solve Achievement scalarizing function.

      :param ref_point: Reference point.
      :type ref_point: np.ndarray
      :param x0: Initial values for decision variables.
      :type x0: np.ndarray
      :param preferential_factors: Preferential factors on how much would the Decision Maker wish to improve
                                   the values of each objective function.
      :type preferential_factors: np.ndarray
      :param nadir: Nadir vector.
      :type nadir: np.ndarray
      :param utopian: Utopian vector.
      :type utopian: np.ndarray
      :param objectives: The objective function values for each input vector.
      :type objectives: np.ndarray
      :param variable_bounds: Lower and upper bounds of each variable
                              as a 2D numpy array. If undefined variables, None instead.
      :type variable_bounds: Optional[np.ndarray
      :param method: The optimization method the scalarizer should be minimized with.
      :type method: Union[ScalarMethod, str, None]

      :returns: 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.
      :rtype: dict



