anyoptimization / pymoo

NSGA2, NSGA3, R-NSGA3, MOEAD, Genetic Algorithms (GA), Differential Evolution (DE), CMAES, PSO
https://pymoo.org
Apache License 2.0
2.21k stars 381 forks source link

Provide "warm start" population #44

Closed hyumo closed 4 years ago

hyumo commented 4 years ago

I am curious if there's a way to provide initial input values to the algorithm so that the search would be quicker?

I am not quite familiar with those genetic algorithms, correct me if I am wrong in this.

blankjul commented 4 years ago

Yes, you can pre-define the initial population (this is how it would be called in evolutionary computation).

If you just know the design values:

import numpy as np

from pymoo.algorithms.so_genetic_algorithm import GA
from pymoo.factory import get_problem
from pymoo.optimize import minimize

problem = get_problem("sphere")

X = np.random.random((500, problem.n_var))

algorithm = GA(sampling=X)

res = minimize(problem,
               algorithm,
               seed=1,
               verbose=False)

print("Best solution found: \nX = %s\nF = %s" % (res.X, res.F))

If you like to provide pre-evaluated solutions:

import numpy as np

from pymoo.algorithms.so_genetic_algorithm import GA
from pymoo.factory import get_problem
from pymoo.model.evaluator import Evaluator
from pymoo.model.population import Population
from pymoo.optimize import minimize

problem = get_problem("sphere")

X = np.random.random((500, problem.n_var))

pop = Population(len(X))
pop.set("X", X)
Evaluator().eval(problem, pop)

algorithm = GA(sampling=pop)

res = minimize(problem,
               algorithm,
               seed=1,
               verbose=False)

print("Best solution found: \nX = %s\nF = %s" % (res.X, res.F))

Hope this answers your question.

hyumo commented 4 years ago

Yes! Thanks for your quick respond. And thanks for this awesome library.

hyumo commented 4 years ago

Sorry to reopen this issue, I am having some issues trying to set an initial x value. I am curious what would the "500" (population) be in the MOEA/D algo. I am using elementwise evaluation and I got the following error. I was able to run NSGA3 by setting it to the same as the population size. Thanks for your help.

Traceback (most recent call last):
  File "test.py", line 216, in <module>
    res = minimize(problem,
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\optimize.py", line 76, in minimize
    res = algorithm.solve()
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\algorithm.py", line 208, in solve
    self._solve(self.problem)
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\algorithm.py", line 289, in _solve
    self.next()
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\algorithm.py", line 260, in next
    self._next()
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\algorithms\moead.py", line 102, in _next
    off = crossover.do(self.problem, pop, parents[None, :])
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\crossover.py", line 50, in do
    X = pop.get("X")[parents.T].copy()
IndexError: index 3 is out of bounds for axis 0 with size 1
blankjul commented 4 years ago

The 500 was just randomly picked. However, for MOEAD the Population object or NumPy array must be equal to the number of reference directions.

import numpy as np

from pymoo.algorithms.moead import MOEAD
from pymoo.factory import get_reference_directions, DTLZ1
from pymoo.model.evaluator import Evaluator
from pymoo.model.population import Population
from pymoo.optimize import minimize
from pymoo.visualization.scatter import Scatter

problem = DTLZ1()

ref_dirs = get_reference_directions("das-dennis", 3, n_partitions=12)
X = np.random.random((len(ref_dirs), problem.n_var))

pop = Population(len(X))
pop.set("X", X)
Evaluator().eval(problem, pop)

algorithm = MOEAD(ref_dirs, sampling=pop)

res = minimize(problem,
               algorithm,
               seed=1,
               verbose=True)

Scatter().add(res.F).show()

Does this work for you? Elementwise evaluation shall not make any difference.

hyumo commented 4 years ago

Thanks for your help!

I switched to using len(ref_dirs), however, I am still getting similar errors.

I can try to reference a default problem and see if I implemented my own problem correctly, but it seems to be working fine if I remove the sampling argument.

My own problem has:

Here's what I am doing:

    # Reference direction
    ref_dirs = get_reference_directions("das-dennis", 2, n_partitions=12)
    # Generate initial condition
    x = np.full((len(ref_dirs), problem.n_var), 20)

    pop = Population(len(x))
    pop.set("X", x)
    Evaluator().eval(problem, pop)

    algorithm = MOEAD(
        ref_dirs,
        decomposition="pbi",
        prob_neighbor_mating=0.95,
        sampling=pop
    )

    termination = get_termination("n_gen", 20)   

    res = minimize(problem,
               algorithm,
               termination,
               save_history=True,
               verbose=True)
Setting number of neighbours to population size: 13
====================================================================================================
n_gen |  n_eval |   cv (min)   |   cv (avg)   |  n_nds  | delta_ideal  | delta_nadir  |   delta_f
====================================================================================================
    1 |       0 |  0.146588718 |  0.146588718 |       1 |            - |            - |            -
Traceback (most recent call last):
  File "limerock2.py", line 239, in <module>
    res = minimize(problem,
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\optimize.py", line 76, in minimize
    res = algorithm.solve()
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\algorithm.py", line 208, in solve
    self._solve(self.problem)
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\algorithm.py", line 289, in _solve
    self.next()
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\algorithm.py", line 260, in next
    self._next()
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\algorithms\moead.py", line 102, in _next
    off = crossover.do(self.problem, pop, parents[None, :])
  File "d:\Anaconda3\envs\pymoo\lib\site-packages\pymoo\model\crossover.py", line 50, in do
    X = pop.get("X")[parents.T].copy()
IndexError: index 6 is out of bounds for axis 0 with size 1
blankjul commented 4 years ago

I just debugged it. And your initial population is NOT supposed to have duplicates. Because a duplicate elimination happens the population becomes a single individual which fails. If you pass instead of X equals to 20 random values it should work.

import numpy as np

from pymoo.algorithms.moead import MOEAD
from pymoo.factory import get_reference_directions, DTLZ1, get_termination
from pymoo.model.evaluator import Evaluator
from pymoo.model.population import Population
from pymoo.optimize import minimize

problem = DTLZ1(n_obj=2)

# Reference direction
ref_dirs = get_reference_directions("das-dennis", 2, n_partitions=12)
x = np.random.random((len(ref_dirs), problem.n_var))

pop = Population(len(x))
pop.set("X", x)
Evaluator().eval(problem, pop)

algorithm = MOEAD(
    ref_dirs,
    decomposition="pbi",
    prob_neighbor_mating=0.95,
    sampling=pop
)

termination = get_termination("n_gen", 20)

res = minimize(problem,
           algorithm,
           termination,
           save_history=True,
           verbose=True)
hyumo commented 4 years ago

hmm, ok, that's good to know. Thanks a lot for your help, I've added some randomness to 20 and it seems to be working fine now.