zdt_example.rst 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. ===============================
  2. Zdt optimisation problem
  3. ===============================
  4. In applied mathematics, test functions, known as artificial landscapes, are useful to evaluate characteristics of continuous optimization algorithms, such as:
  5. - Convergence rate.
  6. - Precision.
  7. - Robustness.
  8. - General performance.
  9. .. note::
  10. The full code for what will be proposed in this example is available: ZdtExample.py_.
  11. Rosenbrock's function
  12. ======================
  13. In mathematical optimization, the Rosenbrock function is a non-convex function, introduced by Howard H. Rosenbrock in 1960, which is used as a performance test problem for optimization algorithms.
  14. Mathematical definition
  15. ~~~~~~~~~~~~~~~~~~~~~~~
  16. The function is defined by: :math:`f(x, y) = (a − x)^2 + b(y − x^2)^2`
  17. It has a global minimum at :math:`(x, y) = (a, a^2)`, where :math:`f(x, y) = 0`. Usually these parameters are set such that :math:`a = 1` and :math:`b = 100`. Only in the trivial case where :math:`a = 0` the function is symmetric and the minimum is at the origin.
  18. Below is a 3D representation of the function with the same parameters :math:`a = 1` and :math:`b = 100`.
  19. .. image:: _static/examples/zdt/rosenbrock_function.jpg
  20. :width: 50 %
  21. :align: center
  22. :alt: 3D representation of Rosenbrock's function
  23. The search space is defined by: :math:`-\infty \leq x_i \leq \infty, 1 \leq i \leq n`
  24. Optimal solution is defined by: :math:`f(1, ..., 1)=0` when :math:`n > 3`
  25. Specific instance used
  26. ~~~~~~~~~~~~~~~~~~~~~~
  27. Using :math:`a = 1` and :math:`b = 100`, the function can be re-written:
  28. - :math:`f(x)=\sum_{i=1}^{n-1}{[(x_{i + 1} − x_i^2)^2 + (1 − x_i)^2]}`
  29. For the current implementation example, the search space will be reduced to :math:`-10 \leq x_i \leq 10` and the instance size will be set to :math:`n = 10`.
  30. Macop implementation
  31. ========================
  32. Let's see how it is possible with the use of the **Macop** package to implement and deal with this Rosenbrock's function instance problem.
  33. Solution structure definition
  34. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35. Firstly, we are going to use a type of solution that will allow us to define the structure of our solutions.
  36. The available macop.solutions.continuous.ContinuousSolution_ type of solution within the Macop package represents exactly what one would wish for.
  37. I.e. a solution that stores a float array with respect to the size of the problem.
  38. Let's see an example of its use:
  39. .. code:: python
  40. from macop.solutions.continuous import ContinuousSolution
  41. problem_interval = -10, 10
  42. solution = ContinuousSolution.random(10, interval=problem_interval)
  43. print(solution)
  44. The ``problem_interval`` variable is required in order to generate our continuous solution with respect to the search space.
  45. The resulting solution obtained should be something like:
  46. .. code:: bash
  47. Continuous solution [-3.31048093 -8.69195762 ... -2.84790964 -1.08397853]
  48. Zdt Evaluator
  49. ~~~~~~~~~~~~~
  50. Now that we have the structure of our solutions, and the means to generate them, we will seek to evaluate them.
  51. To do this, we need to create a new evaluator specific to our problem and the relative evaluation function:
  52. - :math:`f(x)=\sum_{i=1}^{n-1}{[(x_{i + 1} − x_i^2)^2 + (1 − x_i)^2]}`
  53. So we are going to create a class that will inherit from the abstract class macop.evaluators.base.Evaluator_:
  54. .. code:: python
  55. from macop.evaluators.base import Evaluator
  56. class ZdtEvaluator(Evaluator):
  57. """Generic Zdt evaluator class which enables to compute custom Zdt function for continuous problem
  58. - stores into its `_data` dictionary attritute required measures when computing a continuous solution
  59. - `_data['f']` stores lambda Zdt function
  60. - `compute` method enables to compute and associate a score to a given continuous solution
  61. """
  62. def compute(self, solution):
  63. """Apply the computation of fitness from solution
  64. Args:
  65. solution: {:class:`~macop.solutions.base.Solution`} -- Solution instance
  66. Returns:
  67. {float}: fitness score of solution
  68. """
  69. return self._data['f'](solution)
  70. The cost function for the zdt continuous problem is now well defined but we still need to define the lambda function.
  71. .. code:: python
  72. from macop.evaluators.continuous.mono import ZdtEvaluator
  73. # Rosenbrock function definition
  74. Rosenbrock_function = lambda s: sum([ 100 * math.pow(s.data[i + 1] - (math.pow(s.data[i], 2)), 2) + math.pow((1 - s.data[i]), 2) for i in range(len(s.data) - 1) ])
  75. evaluator = ZdtEvaluator(data={'f': Rosenbrock_function})
  76. .. tip::
  77. The class proposed here, is available in the Macop package macop.evaluators.continuous.mono.ZdtEvaluator_.
  78. Running algorithm
  79. ~~~~~~~~~~~~~~~~~
  80. Now that the necessary tools are available, we will be able to deal with our problem and look for solutions in the search space of our Zdt Rosenbrock instance.
  81. Here we will use local search algorithms already implemented in **Macop**.
  82. If you are uncomfortable with some of the elements in the code that will follow, you can refer to the more complete **Macop** documentation_ that focuses more on the concepts and tools of the package.
  83. .. code:: python
  84. # main imports
  85. import numpy as np
  86. # module imports
  87. from macop.solutions.continuous import ContinuousSolution
  88. from macop.evaluators.continuous.mono import ZdtEvaluator
  89. from macop.operators.continuous.mutators import PolynomialMutation
  90. from macop.policies.classicals import RandomPolicy
  91. from macop.algorithms.mono import IteratedLocalSearch as ILS
  92. from macop.algorithms.mono import HillClimberFirstImprovment
  93. # usefull instance data
  94. n = 10
  95. problem_interval = -10, 10
  96. qap_instance_file = 'zdt_instance.txt'
  97. # default validator (check the consistency of our data, i.e. x_i element in search space)
  98. def validator(solution):
  99. mini, maxi = problem_interval
  100. for x in solution.data:
  101. if x < mini or x > maxi:
  102. return False
  103. return True
  104. # define init random solution with search space bounds
  105. def init():
  106. return ContinuousSolution.random(n, interval=problem_interval, validator)
  107. # only one operator here
  108. operators = [PolynomialMutation()]
  109. # random policy even if list of solution has only one element
  110. policy = RandomPolicy(operators)
  111. # Rosenbrock function definition
  112. Rosenbrock_function = lambda s: sum([ 100 * math.pow(s.data[i + 1] - (math.pow(s.data[i], 2)), 2) + math.pow((1 - s.data[i]), 2) for i in range(len(s.data) - 1) ])
  113. evaluator = ZdtEvaluator(data={'f': Rosenbrock_function})
  114. # passing global evaluation param from ILS
  115. hcfi = HillClimberFirstImprovment(init, evaluator, operators, policy, validator, maximise=False, verbose=True)
  116. algo = ILS(init, evaluator, operators, policy, validator, localSearch=hcfi, maximise=False, verbose=True)
  117. # run the algorithm
  118. bestSol = algo.run(10000, ls_evaluations=100)
  119. print('Solution for zdt Rosenbrock instance score is {}'.format(evaluator.compute(bestSol)))
  120. Continuous Rosenbrock's function problem is now possible with **Macop**. As a reminder, the complete code is available in the ZdtExample.py_ file.
  121. .. _ZdtExample.py: https://github.com/jbuisine/macop/blob/master/examples/ZdtExample.py
  122. .. _documentation: https://jbuisine.github.io/macop/_build/html/documentations
  123. .. _macop.solutions.continuous.ContinuousSolution: macop/macop.solutions.continuous.html#macop.solutions.continuous.ContinuousSolution
  124. .. _macop.evaluators.base.Evaluator: macop/macop.evaluators.base.html#macop.evaluators.base.Evaluator
  125. .. _macop.evaluators.continuous.mono.ZdtEvaluator: macop/macop.evaluators.continuous.mono.html#macop.evaluators.continuous.mono.ZdtEvaluator