:py:mod:`desdeo_emo.EAs.PPGA`
=============================

.. py:module:: desdeo_emo.EAs.PPGA


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

Classes
~~~~~~~

.. autoapisummary::

   desdeo_emo.EAs.PPGA.PPGA
   desdeo_emo.EAs.PPGA.Lattice




.. py:class:: PPGA(problem, population_size: int = 100, population_params=None, initial_population=None, n_iterations: int = 10, n_gen_per_iter: int = 10, predator_pop_size: int = 50, prey_max_moves: int = 10, prob_prey_move: float = 0.3, offspring_place_attempts: int = 10, kill_interval: int = 7, max_rank: int = 20, neighbourhood_radius: int = 3)

   Bases: :py:obj:`desdeo_emo.EAs.BaseEA.BaseEA`

   Predatory-Prey genetic algorithm.

   A population of prey signify the various models or solutions to the problem at hand.
   Weaker prey, i.e. bad models or solutions, are killed by predators.
   The predators and prey are placed in a lattice, in which they are free to roam.

   In each generation, each predator gets a certain number of turns to move about and
   hunt in its neighbourhood, killing the weaker prey, according to a fitness criteria.
   After this, each prey gets a certain number of moves to pursue a random walk and to
   reproduce with other prey. Each reproduction step generates two new prey from two
   parents, by crossing over their attributes and adding random mutations. After each
   prey has completed its move, the whole process starts again.

   As the weaker individuals get eliminated in each generation, the population as a
   whole becomes more fit, i.e. the individuals get closer to the true pareto-optimal
   solutions.

   If you have any questions about the code, please contact:

   Bhupinder Saini: bhupinder.s.saini@jyu.fi
   Project researcher at University of Jyväskylä.

   :param population: The population object
   :type population: object

   .. rubric:: Notes

   The algorithm has been created earlier in MATLAB, and this Python implementation
   has been using that code as a basis. See references [4] for the study during which
   the original MATLAB version was created.
   Python code has been written by Niko Rissanen under the supervision of professor
   Nirupam Chakraborti.

   For the MATLAB implementation, see:
   N. Chakraborti. Data-Driven Bi-Objective Genetic Algorithms EvoNN and BioGP and
   Their Applications in Metallurgical and Materials Domain. In Datta, Shubhabrata,
   Davim, J. Paulo (eds.), Computational Approaches to Materials Design: Theoretical
   and Practical Aspects, pp. 346-369, 2016.

   .. rubric:: References

   [1] Laumanns, M., Rudolph, G., & Schwefel, H. P. (1998). A spatial predator-prey
   approach to multi-objective
   optimization: A preliminary study.
   In International Conference on Parallel Problem Solving from Nature (pp. 241-249).
   Springer, Berlin, Heidelberg.

   [2] Li, X. (2003). A real-coded predator-prey genetic algorithm for multiobjective
   optimization. In International
   Conference on Evolutionary Multi-Criterion Optimization (pp. 207-221). Springer,
   Berlin, Heidelberg.

   [3] Chakraborti, N. (2014). Strategies for evolutionary data driven modeling in
   chemical and metallurgical Systems.
   In Applications of Metaheuristics in Process Engineering (pp. 89-122). Springer,
   Cham.

   [4] Pettersson, F., Chakraborti, N., & Saxén, H. (2007). A genetic algorithms based
   multi-objective neural net
   applied to noisy blast furnace data. Applied Soft Computing, 7(1), 387-397.

   .. py:method:: _next_gen()

      Run one generation of PPGA.

      Intended to be used by next_iteration.

      :param population: Population object
      :type population: "Population"


   .. py:method:: select(population, max_rank=20) -> list

      Of the population, individuals lower than max_rank are selected.
      Return indices of selected individuals.

      :param population: Contains the current population and problem
                         information.
      :type population: Population
      :param max_rank: Select only individuals lower than max_rank
      :type max_rank: int

      :returns: List of indices of individuals to be selected.
      :rtype: list


   .. py:method:: manage_preferences(preference=None)

      Forward the preference to the correct preference handling method.

      :param preference: _description_. Defaults to None.
      :type preference: _type_, optional

      :raises eaError: Preference handling not implemented.



.. py:class:: Lattice(size_x, size_y, population, predator_pop_size, target_pop_size, prob_prey_move, prey_max_moves, offspring_place_attempts, neighbourhood_radius)

   The 2-dimensional toroidal lattice in which the predators and prey are placed.

   .. attribute:: size_x

      Width of the lattice.

      :type: int

   .. attribute:: size_y

      Height of the lattice.

      :type: int

   .. attribute:: lattice

      2d array for the lattice.

      :type: ndarray

   .. attribute:: predator_pop

      The predator population.

      :type: ndarray

   .. attribute:: predators_loc

      Location (x, y) of predators on the lattice.

      :type: list

   .. attribute:: preys_loc

      Location (x, y) of preys on the lattice.

      :type: list

   .. py:method:: init_predators()

      Initialize the predator population, linearly distributed in [0,1]
      and place them in the lattice randomly.


   .. py:method:: init_prey()

      Find an empty position in the lattice and place the prey.


   .. py:method:: move_prey()

      Find an empty position in prey neighbourhood for the prey to move in,
      and choose a mate for breeding if any available.

      :returns: **mating_pop** -- List of parent indices to use for mating
      :rtype: list


   .. py:method:: place_offspring(offspring)

      Try to place the offsprings to the lattice. If no empty spot found within
      number of max attempts, do not place.

      :param offspring: number of offsprings
      :type offspring: int

      :returns: Successfully placed offspring indices.
      :rtype: list


   .. py:method:: move_predator()

      Find an empty position in the predator neighbourhood for the predators to move in,
      move the predator and kill the weakest prey in its neighbourhood, if any.
      Repeat until > predator_max_moves.


   .. py:method:: update_lattice(selected=None)

      Update prey positions in the lattice.

      :param selected: Indices of preys to be removed from the lattice.
      :type selected: list


   .. py:method:: lattice_wrap_idx(index, lattice_shape)
      :staticmethod:

      Returns periodic lattice index
      for a given iterable index.

      :param index: one integer for each axis
      :type index: tuple
      :param lattice_shape: the shape of the lattice to index to
      :type lattice_shape: tuple


   .. py:method:: neighbours(arr, x, y, n=3)
      :staticmethod:

      Given a 2D-array, returns an n*n array whose "center" element is arr[x,y]

      :param arr: A 2D-array where to get the neighbouring cells
      :type arr: ndarray
      :param x: X coordinate for the center element
      :type x: int
      :param y: Y coordinate for the center element
      :type y: int
      :param n: Radius of the neighbourhood
      :type n: int

      :returns: * *The neighbouring cells of x, y in radius n*n.*
                * *Defaults to Moore neighbourhood (n=3).*



