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

.. py:module:: desdeo_mcdm.interactive.Nautilus

.. autoapi-nested-parse::

   NAUTILUS 1



Module Contents
---------------

Classes
~~~~~~~

.. autoapisummary::

   desdeo_mcdm.interactive.Nautilus.NautilusInitialRequest
   desdeo_mcdm.interactive.Nautilus.NautilusRequest
   desdeo_mcdm.interactive.Nautilus.NautilusStopRequest
   desdeo_mcdm.interactive.Nautilus.Nautilus



Functions
~~~~~~~~~

.. autoapisummary::

   desdeo_mcdm.interactive.Nautilus.validate_response
   desdeo_mcdm.interactive.Nautilus.validate_preferences
   desdeo_mcdm.interactive.Nautilus.validate_n_iterations
   desdeo_mcdm.interactive.Nautilus.f1



.. 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_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: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 an positive integer greater than zero.


.. 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.

   .. 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.

   :param z_current: Current iteration point.
   :type z_current: np.ndarray
   :param nadir: Nadir point.
   :type nadir: np.ndarray
   :param lower_bounds: Lower bounds for objective functions for next iteration.
   :type lower_bounds: np.ndarray
   :param upper_bounds: Upper bounds for objective functions for next iteration.
   :type upper_bounds: np.ndarray
   :param distance: Closeness to Pareto optimal front.
   :type distance: np.ndarray


.. 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.


.. 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:: f1(xs)


