CMA-ES / pycma

Python implementation of CMA-ES

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Passing arguments + constrained optimization

martinmatak opened this issue · comments

Hi,

I'm not sure how to pass arguments to objective function and use constrained optimization?

Here's a minimal example that reproduces error:

import cma
import numpy as np

def obj_f(x, y):
    return x[0]*x[1] + y

# I've tried def constraint(x,y) as well, same thing
def constraint(x): 
    return [x[0] - 1]

x, es = cma.fmin2(obj_f, np.zeros(2), 1, args=(1,))
print("unconstrained done")
cfun = cma.ConstrainedFitnessAL(obj_f, constraint)
x, es = cma.fmin2(cfun, np.zeros(2), 1, args=(1,))
print("constrained done")

and this is what I get:

(3_w,6)-aCMA-ES (mu_w=2.0,w_1=63%) in dimension 2 (seed=138888, Thu Jul 28 12:35:57 2022)
Iterat #Fevals   function value  axis ratio  sigma  min&max std  t[m:s]
    1      6 -1.099857607348775e+00 1.0e+00 1.37e+00  1e+00  1e+00 0:00.0
    2     12 -8.982446135934190e+00 1.2e+00 2.09e+00  2e+00  2e+00 0:00.0
    3     18 -3.057948317212121e+01 1.4e+00 3.84e+00  4e+00  4e+00 0:00.0
   20    120 -4.894950332294568e+06 6.3e+00 5.10e+02  8e+02  1e+03 0:00.0
termination on tolfacupx=1000.0 (Thu Jul 28 12:35:57 2022)
final/bestever f-value = -3.719290e+06 -4.894950e+06
incumbent solution: [-1572.98613330058, 2364.4776399492775]
std deviation: [762.7205778976415, 1136.3374715313475]
unconstrained done
(3_w,6)-aCMA-ES (mu_w=2.0,w_1=63%) in dimension 2 (seed=63645, Thu Jul 28 12:35:57 2022)
Traceback (most recent call last):
  File "/home/mmatak/cma_min_example.py", line 13, in <module>
    x, es = cma.fmin2(cfun, np.zeros(2), 1, args=(1,))
  File "/home/mmatak/pkgs/pycma/cma/evolution_strategy.py", line 4047, in fmin2
    res = fmin(objective_function, x0, sigma0,
  File "/home/mmatak/pkgs/pycma/cma/evolution_strategy.py", line 4465, in fmin
    X, fit = es.ask_and_eval(parallel_objective or objective_function,
  File "/home/mmatak/pkgs/pycma/cma/evolution_strategy.py", line 2455, in ask_and_eval
    f = func(x, *args) if kappa == 1 else \
TypeError: __call__() takes 2 positional arguments but 3 were given

One way around it is to have global variables that objective funciton and constraints function can see, but that's not a very clean solution.

A generic and clean solution seems to be

from functools import partial

cfun = cma.ConstrainedFitnessAL(partial(obj_f, y=1), constraint)

That's the reason why args is not implemented in the ConstrainedFitnessAL interface.