24

Currently I have the following code that defines the function f.

a = #something
b = #something
c = #something
def f(x):
    """Evaluates some function that depends on parameters a, b, and c"""
    someNumber = #some calculation
    return someNumber

Ideally I would do def f(x, a, b, c), BUT I am minimizing f with respect to x and SciPy's optimization toolbox doesn't allow for one to minimize functions with parameters in the arguments. That said I would like to run my minimization code for multiple values of a, b and c. Is there a way I can do this?

Nate Stemen
  • 1,235
  • 3
  • 15
  • 27
  • 3
    "Freeze" the function with particular `a, b, c` values using `functools.partial` ? – PM 2Ring Mar 25 '17 at 14:54
  • @PM2Ring this would work, and I'm glad I know about this tool now, but as @Liteye pointed out `minimize` actually allows me to pass it parameters. Thanks! – Nate Stemen Mar 25 '17 at 16:17
  • 1
    No worries. `partial` is great when you need it, but I don't know SciPy, so it was only a suggestion. Obviously, Liteye's answer is the proper way to do this. :) – PM 2Ring Mar 25 '17 at 16:34

2 Answers2

36

You can specify additional arguments in args

from scipy.optimize import minimize 
minimize(f, x0, args=(a, b, c))
Evgeny
  • 4,173
  • 2
  • 19
  • 39
Liteye
  • 2,761
  • 1
  • 16
  • 16
  • 3
    Do parameters in `args` need to be called in the same way they are called in the body of the function `f`? Does also `f` remain `f(x)` or does it become `f(x,a,b,c)`? – Robb1 Aug 25 '20 at 18:03
17

This is a straightforward question and answer about using minimize. In case other users need something more concrete, here's a simple example.

A generalized quadratic equation:

In [282]: def fun(x, a,b,c):
     ...:     return a*x**2 + b*x + c

In [283]: optimize.minimize(fun, 10, args=(1,0,0))
Out[283]: 
      fun: 1.7161984122524196e-15
 hess_inv: array([[ 0.50000001]])
      jac: array([ -6.79528891e-08])
  message: 'Optimization terminated successfully.'
     nfev: 15
      nit: 4
     njev: 5
   status: 0
  success: True
        x: array([ -4.14270251e-08])

In [284]: optimize.minimize(fun, 10, args=(1,1,1))
Out[284]: 
      fun: 0.7500000000000221
 hess_inv: array([[ 0.49999999]])
      jac: array([  3.12924385e-07])
  message: 'Optimization terminated successfully.'
     nfev: 12
      nit: 2
     njev: 4
   status: 0
  success: True
        x: array([-0.49999985])

The function could take arrays as input as well, but still needs to return a single (scalar) value:

In [289]: optimize.minimize(fun, [10,10,10], args=(np.array([1,2,3]), 1, 1))
Out[289]: 
      fun: 2.541666666667115
 hess_inv: array([[ 0.50021475, -0.00126004,  0.00061239],
       [-0.00126004,  0.25822101, -0.00259327],
       [ 0.00061239, -0.00259327,  0.16946887]])
      jac: array([ -8.94069672e-08,   4.47034836e-07,  -2.20537186e-06])
  message: 'Optimization terminated successfully.'
     nfev: 55
      nit: 9
     njev: 11
   status: 0
  success: True
        x: array([-0.50000006, -0.2499999 , -0.16666704])

In [286]: def fun(x, a,b,c):
 ...:     return (a*x**2 + b*x + c).sum()

It's a good idea to make sure the function runs with the proposed x0 and args, e.g.

In [291]: fun(np.array([10,10,10]), np.array([1,2,3]), 1, 1)
Out[291]: 633

If you can't call the objective function, or are confused as to how its arguments work, minimize isn't a magic bullet. This minimization is only as good as your understanding of the objective function.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Sorry to dig up an old answer but I think another question is probably a duplicate. How would you add a constraint that depends on both the minimization variable, x, and one of the arguments, say a. I have a similar problem with the additional constraint that x + a < 1. – user1936752 Feb 09 '19 at 22:57
  • @user1936752, I think the constraints are called with the same arguments as the objective function, i.e. `(x,) + args` (tuple join). So they have to have the same signature, or at least a compatible one. – hpaulj Feb 09 '19 at 23:10
  • thanks for the comment. Maybe I was unable to express my question properly so I've asked a separate question here: https://stackoverflow.com/questions/54611746/scipy-minimize-how-to-pass-args-to-both-the-objective-and-the-constraint. If you have time to look at it, I'd be most grateful! – user1936752 Feb 09 '19 at 23:14