CMA-ES / pycma

Python implementation of CMA-ES
Other
1.11k stars 178 forks source link

cmaes does not seem to take into account `x0` #199

Closed salomonl closed 2 years ago

salomonl commented 2 years ago

I thank you for the development of this open-source solver.

I had a problem, for which the decision space is quite small. To guide the search, I gave a feasible point x0 to the solver, but it does not seem to take it into account.

Here is a following example, taken from the notebook:

import cma

print("Version of cma is : ", cma.__version__)

fun = cma.ff.elli
def constraints(x):
    print(x)
    return [x[1] - -1, x[1] - -0.9]
cfun = cma.ConstrainedFitnessAL(fun, constraints)

x0 = 4 * [2]  # initial solution
sigma0 = 1    # initial standard deviation to sample new solutions

x, es = cma.fmin2(cfun, x0, sigma0, {'tolstagnation': 0, 'maxfevals' : 30}, callback=cfun.update)

On my machine (mac os), I obtain the following:

Version of cma is: 3.2.2
(4_w,8)-aCMA-ES (mu_w=2.6,w_1=52%) in dimension 4 (seed=1, ...)
[3.62434536 1.38823594 1.47181504 0.92699114]
[ 2.86540763 -0.30156747  3.74485539  1.23876455]
[ 2.3190391   1.75062651  3.46214449 -0.06021797]
[1.6775828  1.61594084 3.13379779 0.90006749]
[1.82757179 1.12213061 2.0422148  2.58283707]
[0.89938082 3.14473802 2.90161326 2.50251318]
[2.90085595 1.31626359 1.8771067  1.06419547]
[1.73211192 2.5303621  1.30832196 1.60323159]
Iterat #Fevals   function value  axis ratio  sigma  min&max std  t[m:s]
    1      8 1.238024954254167e+05 1.0e+00 1.14e+00  1e+00  1e+00 0:00.0
[2.2477901  2.7489099  4.27852718 1.96261131]
[ 1.51785958  1.3807828   2.68242534 -0.54502305]
[3.1511377  2.10688359 2.69441187 2.05427505]
[1.20828367 2.37975453 2.72557127 2.00529616]
[3.16683111 2.03036799 2.42994018 0.1318756 ]
[ 5.19778411  3.21557617  4.83863349 -0.5568654 ]
[2.70051093 0.47656508 1.98746376 1.82022889]
[2.21293786 1.32129136 0.27141135 0.41962931]
    2     16 6.576740407898615e+06 1.5e+00 1.15e+00  1e+00  1e+00 0:00.0
[ 3.25458862  0.56432406 -0.16485919  0.03587124]
[1.52614343 1.36815061 0.84938289 0.35924636]
[2.35760857 1.78056082 0.97240973 1.74335642]
[ 3.45250188  1.43499948 -0.00808246  0.85802367]
[ 2.49515877  1.67334124  1.32357009 -1.18537436]
[2.53744483 1.89497312 1.96769959 1.88867309]
[ 1.48274307  0.01381512  2.46077445 -0.70011359]
[0.29826562 0.93871198 0.20095187 0.34169896]
    3     24 2.787927422412443e+06 1.5e+00 1.24e+00  1e+00  1e+00 0:00.0
[ 0.69376142  1.04153967  1.55836136 -1.75430223]
[ 2.14939593 -0.95428145  0.36109498 -0.89564954]
[ 1.13760214  0.23413803 -0.11418116 -0.15461377]
[1.60960546 0.10186673 0.78359057 0.61645475]
[ 1.6211851  -0.06907105  4.67079116 -2.14392209]
[-0.4367175   0.13491975  2.59368404  0.85456721]
[ 1.9693676   0.10474844  2.48743451 -1.54837683]
[ 2.49095042  0.17117021  0.8678723  -1.42659562]
    4     32 7.997121716899037e+05 1.5e+00 1.35e+00  1e+00  1e+00 0:00.0
[ 1.67587953 -0.41865462  0.37830715 -0.39527897]
termination on maxfevals=30 (Wed Mar 30 11:44:38 2022)
final/bestever f-value = 4.590448e+06 1.238025e+05
incumbent solution: [1.675879529182522, -0.4186546209393176, 0.37830715227822675, -0.3952789654356743]
std deviation: [1.2948466611346958, 1.3295307930530997, 1.4612841118361448, 1.311458600293812]

Note that the problem is not related to constrained optimization, I get the same behavior when using cma on an unconstrained problem. Here is the following example, taken from a notebook.

import cma

print("Version of cma is : ", cma.__version__)

def f(x):
    print(x)
    return cma.ff.elli(x)

x0 = 4 * [2]  # initial solution
sigma0 = 1    # initial standard deviation to sample new solutions

x, es = cma.fmin2(f, x0, sigma0, {'maxfevals': 20, 'seed' : 1})

Here is what I get (mac os):

❯ python test_cmaes.py
Version of cma is :  3.2.2
(4_w,8)-aCMA-ES (mu_w=2.6,w_1=52%) in dimension 4 (seed=1, ...)
[3.62434536 1.38823594 1.47181504 0.92699114]
[ 2.86540763 -0.30156747  3.74485539  1.23876455]
[ 2.3190391   1.75062651  3.46214449 -0.06021797]
[1.6775828  1.61594084 3.13379779 0.90006749]
[1.82757179 1.12213061 2.0422148  2.58283707]
[0.89938082 3.14473802 2.90161326 2.50251318]
[2.90085595 1.31626359 1.8771067  1.06419547]
[1.73211192 2.5303621  1.30832196 1.60323159]
Iterat #Fevals   function value  axis ratio  sigma  min&max std  t[m:s]
    1      8 1.238024954254167e+05 1.0e+00 1.14e+00  1e+00  1e+00 0:00.0
[2.2477901  2.7489099  4.27852718 1.96261131]
[ 1.51785958  1.3807828   2.68242534 -0.54502305]
[3.1511377  2.10688359 2.69441187 2.05427505]
[1.20828367 2.37975453 2.72557127 2.00529616]
[3.16683111 2.03036799 2.42994018 0.1318756 ]
[ 5.19778411  3.21557617  4.83863349 -0.5568654 ]
[2.70051093 0.47656508 1.98746376 1.82022889]
[2.21293786 1.32129136 0.27141135 0.41962931]
    2     16 7.685953589113269e+04 1.5e+00 1.12e+00  9e-01  1e+00 0:00.0
[ 1.08558953  1.32461271  1.84308421 -0.37189977]
[2.70844534 1.52058481 2.49621606 0.73483336]
[3.03687226 1.70460952 0.94637427 0.71522373]
[ 1.70081331  1.04925704  0.94627513 -0.04487636]
[ 2.73439478  0.50085117  3.06826547 -0.64986942]
[3.85777293 1.9228469  0.83665206 0.2327016 ]
[ 3.19198426  2.50784897  3.81437665 -0.69907932]
[2.2821455  1.91984601 3.21120733 1.76800949]
    3     24 1.108124081482620e+04 1.5e+00 1.11e+00  9e-01  1e+00 0:00.0
[ 2.27209034  1.31543271  1.13112901 -0.03739224]
termination on maxfevals=20 (Wed Mar 30 11:49:08 2022)
final/bestever f-value = 1.437091e+04 1.108124e+04
incumbent solution: [2.2720903382394786, 1.3154327071893366, 1.1311290124925557, -0.037392238516864656]
std deviation: [1.1271338861306948, 0.9451616053892312, 1.1206323758331647, 1.1262900220764098]

Do you know how to force the use of the point x0 ?

nikohansen commented 2 years ago

The initial solution is used to set the initial mean of the sample distribution. It is not evaluated (often/usually the real-world user already has evaluated this solution anyways, hence to evaluate it first seems a little strange) and its f-value is anyway not used to proceed. The default way to emphasize the importance of the initial solution is to choose a smaller value for the initial sigma.

In the above example already in the third iteration, all new solutions are better than the initial solution.

A rather non-standard way to "respect" the initial solution would be to set the 'CMA_elitist' option to "initial":

cma.CMAOptions('elit')
{'CMA_elitist': 'False  #v or "initial" or True, elitism likely impairs global search performance'}
salomonl commented 2 years ago

Ok I did not understand the meaning of x0. Thank you for your quick answer.