Monica
Monica

Reputation: 1070

minimazing function , how to pass arguments into a function scipy

I've written a code for minimizing a certain function with respect to r and alpha using scipy . However I encountered a problem with passing an argument to a function.

#!/usr/bin/env python
import numpy as np
from scipy.integrate import quad
import scipy.optimize as opt

def integrand(t, alpha, r):
    return np.exp(-alpha*(t-r))**2

def my_function(parameters, rho):
    alpha = parameters[0]
    r = parameters[1]
    return quad(integrand, 0, rho, args=(alpha, r))[0]

alpha_0 = 1
r_0 = 1
rho = 5.0

vec_expint = np.vectorize(my_function)

res = opt.minimize(my_function(rho), np.asarray([alpha_0, r_0]), method='CG', tol=1.e-2, options={'gtol': 0.01, 'maxiter': 5})
print(res)

I want to put integration bounds as variables. I added a variable rho and I'm getting the following error message:

 res = opt.minimize(my_function(rho), np.asarray([alpha_0, r_0]), method='CG', tol=1.e-2, options={'gtol': 0.01, 'maxiter': 5})
    TypeError: my_function() takes exactly 2 arguments (1 given)

Could anybody explain me how to pass arguments in the right way, please?

Upvotes: 2

Views: 987

Answers (3)

David Z
David Z

Reputation: 131550

First, let me point out one thing that might be confusing you: you have a global (actually, module-level) variable named rho and a local variable named rho inside my_function. These are not the same. It might help clear things up to rename the global variable to rho_0, i.e. replace the last few lines of your code with this:

alpha_0 = 1
r_0 = 1
rho_0 = 5.0

vec_expint = np.vectorize(my_function)

res = opt.minimize(my_function(rho_0), np.asarray([alpha_0, r_0]), method='CG', tol=1.e-2, options={'gtol': 0.01, 'maxiter': 5})
print(res)

Now, the problem you are experiencing comes from writing my_function(rho) inside your call to opt.minimize. When you write my_function(rho), it means you are calling my_function with one argument, and that argument is the value of 5.0 which you are storing under the name rho_0. But my_function requires two arguments: parameters and rho. You can't call it with one argument. That's why Python gives the error you're encountering.

In order to do what you want, you have to be aware that opt.minimize requires a function as its first argument. For example, you could call

opt.minimize(my_function, ...)

What you were giving it is the result of calling a function,

opt.minimize(my_function(...), ...)

which is not the same thing.

As you know, the function you pass to opt.minimize needs to have a signature like

def my_function(parameters, arg0, arg1, ...):
    ...

When you want to pass specific values to arg0, arg1, etc., you use the args argument of opt.minimize.

opt.minimize(my_function, parameters_0, args=(arg0_value, arg1_value, ...)

Inside opt.minimize, at each evaluation step it will choose values for the parameters, pack them up into a tuple, and pass that as the first argument to my_function, while it does the reverse with whatever you pass to args: it unpacks that tuple into individual arguments and passes them to my_function after the parameters.

Upvotes: 1

hpaulj
hpaulj

Reputation: 231355

You have defined:

def my_function(parameters, rho):

Now try

my_function(1)

What's the error? The obvious Python one, right? When you run

 res = opt.minimize(**my_function(rho)**, np.asarray([alpha_0, r_0]), method='CG', tol=1.e-2, options={'gtol': 0.01, 'maxiter': 5})

it doesn't even get past that expression I highlighted.

There are a couple of solutions:

  • define a new function that takes just one parameter, parameters, and defines rho before hand. That can be done with a def, a lambda or partial.

  • give optimize an args parameter. You are already using the args feature when calling quad.

Upvotes: 1

eyllanesc
eyllanesc

Reputation: 243897

use args parameter.

My Code:

#!/usr/bin/env python
import numpy as np
from scipy.integrate import quad
import scipy.optimize as opt

def integrand(t, alpha, r):
    return np.exp(-alpha*(t-r))**2

def my_function(parameters, rho):
    alpha = parameters[0]
    r = parameters[1]
    return quad(integrand, 0, rho, args=(alpha, r))[0]

alpha_0 = 1
r_0 = 1
rho = 5.0

vec_expint = np.vectorize(my_function)

res = opt.minimize(my_function, np.asarray([alpha_0, r_0]), method='CG', tol=1.e-2, args=(rho),options={'gtol': 0.01, 'maxiter': 5})
print(res)

Output:

     fun: 0.0018415003336983448
     jac: array([-0.00523077,  0.00762011])
 message: 'Optimization terminated successfully.'
    nfev: 12
     nit: 2
    njev: 3
  status: 0
 success: True
       x: array([ 2.06899361, -1.1785839 ])

Upvotes: 1

Related Questions