项目作者: krzysztofarendt

项目描述 :
Optimized and benchmarked parallel Genetic Algorithm with inequality constraints, and a scipy-like interface
高级语言: Jupyter Notebook
项目地址: git://github.com/krzysztofarendt/modestga.git
创建时间: 2018-05-24T13:50:18Z
项目社区:https://github.com/krzysztofarendt/modestga

开源协议:BSD 2-Clause "Simplified" License

下载


modestga

Python package Downloads

Genetic Algorithm with a SciPy-like interface:

  1. # Minimization with box constraints
  2. minimize(fun, bounds, x0=None, args=(), callback=None, options={}, workers=None)
  3. # Minimization with box and inequality constraints
  4. con_minimize(fun, bounds, constr, x0=None, args=(), callback=None, options={}, workers=None)

Main features:

  • single-CPU and parallel modes,
  • rectangular bounds and inequality constraints,
  • adaptive mutation,
  • suitable for large-scale non-convex problems,
  • pure Python,
  • continuous testing on latest Ubuntu and Python 3.7-3.10 but should work also on other distros and on Windows.

Two functions are available:

  • modestga.minimize() for minimization with simple rectangular bounds on parameters,
  • modestga.con_minimize() for full constrained minimization (possibly nonlinear, noncontinuous).

The function con_minimize() is a wrapper over minimize() and has only one
extra argument constr with a list of constraint functions. The algorithm
tries to keep the constraint functions outputs above zero. The constraint
functions can be nonlinear and noncontinuous (actually any Python code is fine).

By default modestga.minimize() and modestga.con_minimize() run on all CPUs
and divides the population into smaller subpopulations (1 per CPU)
which exchange genes among one another after each generation.

To use multiple CPUs the cost function (and constraints) must be serializable.
If you want to minimize some function which cannot be serialized with
cloudpickle, run
the minimization on a single CPU (workers=1).

Installation

  1. pip install modestga

To get the latest version, clone the repository and install using setup.py:

  1. git clone https://github.com/krzysztofarendt/modestga
  2. cd modestga
  3. pip install -e .

Test

Clone the repository and run:

  1. pip install -e .
  2. pip install pytest
  3. pytest

You can also run some examples, e.g. optimization of the 50-dimensional Rastrigin function:

  1. python modestga/examples/min_rastrigin_fun.py

…or run all examples at once:

  1. bin/run_examples.sh

Example

Minimal:

  1. import random
  2. import numpy as np
  3. from modestga import minimize
  4. # Define function to be minimized (can be noisy and non-convex)
  5. def fun(x, *args):
  6. return np.sum(x ** 2) + random.random()
  7. # Specify parameter bounds (here: 100 parameters allowed to vary from 0 to 10)
  8. bounds = [(0, 10) for i in range(100)]
  9. # Overwrite default evolution options
  10. options = {
  11. 'generations': 1000, # Max. number of generations
  12. 'pop_size': 500 # Population size
  13. }
  14. # Minimize
  15. # (it uses all available CPUs by default)
  16. res = minimize(fun, bounds, options=options)
  17. # Print optimization result
  18. print(res)

Extended:

  1. import logging
  2. import random
  3. import numpy as np
  4. from modestga import minimize
  5. # Set up logging if needed
  6. logging.basicConfig(filename='ga.log', level='INFO', filemode='w')
  7. # Define function to be minimized (can be noisy and non-convex)
  8. def fun(x, *args):
  9. return np.sum(x ** 2) + random.random()
  10. # Specify parameter bounds (here: 100 parameters allowed to vary from 0 to 10)
  11. bounds = [(0, 10) for i in range(100)]
  12. # Overwrite default evolution options
  13. options = {
  14. 'generations': 1000, # Max. number of generations
  15. 'pop_size': 500, # Population size
  16. 'mut_rate': 0.01, # Initial mutation rate (adaptive mutation)
  17. 'trm_size': 20, # Tournament size
  18. 'tol': 1e-3 # Solution tolerance
  19. }
  20. def callback(x, fx, ng, *args):
  21. """Callback function called after each generation"""
  22. print(f"\nx={x}\nf(x)={fx}\n")
  23. # Minimize using 3 CPUs
  24. res = minimize(fun, bounds, callback=callback, options=options, workers=3)
  25. # Print optimization result
  26. print(res)
  27. # Final parameters
  28. x = res.x
  29. # Final function value
  30. fx = res.fx
  31. # Number of function evaluations
  32. nfev = res.nfev

For constrained optimization examples check out the following scripts:

  • modestga/examples/con_min_mishra_fun.py
  • modestga/examples/con_min_rosenbrock_fun.py
  • modestga/examples/con_min_rastrigin_fun.py

Benchmarks

modestga vs. Differential Evolution (Scipy) vs. Monte Carlo

The algorithm has been benchmarked against Differential Evolution (SciPy) and naive Monte Carlo (modestga.benchmark.methods.monte_carlo) using the Rastrigin function. Fig. 2 shows mean results from five runs for each case. The main parameters were as follows:

  • population = 100,
  • maximum number of generations = 1000,
  • tolerance = 1e-3,
  • mutation rate - three scenarios for GA and DE,
  • workers (CPUs) = 1.

The Monte Carlo method did not take into account the tolerance and was simply stopped at 1000 iteration.

Note that unlike in modestga, in Differentian Evolution the population size is multiplied by the number of parameters. For exact meaning of the mutation parameter in Differential Evolution please refer to the SciPy documention.



Figure 2: Comparison to other methods

Summary:

  • in almost all considered mutation cases modestga achieves similar or better result in significantly shorter time for large-scale problems (N > 32),
  • modestga is slower for small-scale problems, especially when the cost function evaluation is fast, as in this case,
  • the increasing time in Differential Evolution is due to the increasing size of population (it’s multiplied by the number of parameters), but larger population seems to be inefective in solving the minimization problem.

Number of CPUs vs. computing time

The performance of the parallel optimization was evaluated on a 64-dimensional Rastrigin function. Since the evaluation of this function is very fast, multiprocessing is beneficial only up to around 3 CPUs. Beyond that point considerable time is spend on inter-process communication. Thus, the optimum number of CPUs depends mainly on the function evaluation time.



Figure 3: Parallel minimization performance