1

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.

Foad S. Farimani
  • 12,396
  • 15
  • 78
  • 193

2 Answers2

1

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, ...)
shx2
  • 61,779
  • 13
  • 130
  • 153
  • aha, cool workarounds. thank you. so there is no way to pass a function with `*args, **kwargs` directly to the `scipy.optimize` functions without defining a lambda or intermediary function? – Foad S. Farimani Feb 25 '20 at 13:59
  • I will test this in a couple o fhours and will come back to approve the answer. – Foad S. Farimani Feb 25 '20 at 14:07
  • I tried your code. I'm not sure if it will work as it is. I this the `x, y` parameters need to be smashed into one like `foo_ = lambda P: foo(P[0], P[1], A, B, C)` and then `minimize(foo_, x0=[X0, Y0])`. I'm not gonna apply this edit on your post you will not get any notifications. better you look at it your self. – Foad S. Farimani Feb 25 '20 at 19:58
  • see [this](https://stackoverflow.com/a/27682638/4999991) as an example – Foad S. Farimani Feb 25 '20 at 20:02
0

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.

Foad S. Farimani
  • 12,396
  • 15
  • 78
  • 193