如您所知,要最小化的函数会根据参数而变化
给出。所以我们需要编写一些动态定义函数的代码。
一种方法是定义一个模板字符串,进行一些字符串格式化
根据给定的参数修改模板,然后使用exec
到
定义函数。这有一些优先级——标准库使用它定义命名元组的技术 https://github.com/python/cpython/blob/master/Lib/collections/__init__.py#L421.
因此,例如,如果我们希望最小化的表达式是
4*(b-a)**2 + 5*(c-d)**2
那么你可以使用
import textwrap
import scipy.optimize as optimize
def make_model(*fixed):
template = textwrap.dedent("""
def func(variable, {fixed}):
{variable} = variable
return 4*(b-a)**2 + 5*(c-d)**2
""")
variable = set(('a', 'b', 'c', 'd')).difference(fixed)
ns = dict()
funcstr = template.format(variable=', '.join(variable), fixed=', '.join(fixed))
print(funcstr) # comment out if you don't want to see the function
exec funcstr in ns
return ns['func']
def solve(initial_guess, **givens):
fixed = tuple(givens.keys())
vals = tuple(givens.values())
sol = optimize.minimize(make_model(*fixed), initial_guess, args=vals)
return sol
print(solve(initial_guess=1, a=1, c=1.1, d=-1.2))
这产生
def func(variable, a, c, d):
b = variable
return 4*(b-a)**2 + 5*(c-d)**2
status: 0
success: True
njev: 1
nfev: 3
hess_inv: array([[1]])
fun: array([ 26.45])
x: array([ 1.])
message: 'Optimization terminated successfully.'
jac: array([ 0.])
nit: 0
print(solve(initial_guess=(1, 1), a=1, c=1.1))
yields
def func(variable, a, c):
b, d = variable
return 4*(b-a)**2 + 5*(c-d)**2
status: 0
success: True
njev: 3
nfev: 12
hess_inv: array([[1, 0],
[0, 1]])
fun: 2.4611848645596973e-16
x: array([ 0.99999999, 1.1 ])
message: 'Optimization terminated successfully.'
jac: array([ 1.19209279e-08, 2.88966118e-08])
nit: 1