Reputation: 1070
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
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
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
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