Foad S. Farimani
Foad S. Farimani

Reputation: 14016

passing a function with multiple independent variables and multiple arguments to scipy optimize minimize

Following this question, I want to make my question as specific as possible focusing on the part that I can not solve. Consider a very simple function of:

def foo(x, y, a, b, c):
    return a * x**4 + b * y**2 + c

now I want to use the scipy.optimize.minimize or any of other existing functions to find the x and y (i.e., parameters) to minimize foo given the constants a, b, and c (i.e., args). If I had only one parameter and multiples arguments then from this page I could do:

def foo(x, *args):
    a, b, c = args
    return a * x**4 + b * x**2 + c

# X0 = to some scalar
# ARGS = a tuple of scalars (A, B, C) 

x_min = scipy.optimize.minimize(foo, x0=X0, args=ARGS)

and if I had only independent variables, with no constant args, then from this page I could do:

def foo(*params):
    x, y = params
    return 4 * x**4 + 2 * y**2 + 1

# P0 = to a list of scalars [X0, Y0] 

x_min = scipy.optimize.minimize(foo, x0=P0)

However, I can not use any of the above syntaxes. I believe I have to define my function as something like:

def foo(*args, **kwargs):
    x, y = args
    a, b, c = tuple(kwargs.values())
    return a * x**4 + b * y**2 + c

but then I don't know how to pass args and kwargs to the scipy.optimize functions. I would appreciate if you could help me understand what is the best way to define the foo function with multiple independent parameters and constant arguments to scipy.optimize functions. Thanks for your support in advance.

Upvotes: 2

Views: 1773

Answers (2)

Foad S. Farimani
Foad S. Farimani

Reputation: 14016

We want to define a function foo that takes multiple independent variables (x and y) and also has constant arguments (a, b, and c), and then use the scipy.optimize.minimize function to find the values of x and y that minimize the function while keeping the constants fixed.

import scipy.optimize

def foo(params, *args):
    x, y = params
    a, b, c = args
    return a * x**4 + b * y**2 + c

x0 = [1, 2]  # initial guess
args = (1, 2, 3)  # constant arguments a, b, c
result = scipy.optimize.minimize(foo, x0, args=args)

x_min = result.x[0]
y_min = result.x[1]

print("Optimized x:", x_min)
print("Optimized y:", y_min)
print("Minimum value of foo:", result.fun)

the foo function takes params as the list of independent variables x and y, and also takes the constant arguments a, b, and c as separate tuple of parameters using the *args syntax. We then pass the initial guess x0 for x and y, and the constant arguments a, b, and c using the args parameter of the scipy.optimize.minimize function.

Upvotes: 0

shx2
shx2

Reputation: 64318

Instead of passing foo and making scipy pass the constant arguments, you can bind them yourself, either using lambda or functools.partial:

A, B, C = some_const_values
foo1 = lambda x, y: foo(x, y, A, B, C)

Or:

import functools
foo1 = functools.partial(foo, a=A, b=B, c=C)

Then:

x_min = scipy.optimize.minimize(foo1, ...)

Upvotes: 2

Related Questions