将最优值绘制为目标中参数的函数

计算科学 优化 约束优化 scipy
2021-12-21 18:22:50

我正在尝试使用 scipy.optimize 最小化 2d 函数。具体来说,我想将函数fun的最小值绘制为参数wjk的函数。问题是我不能将wjk作为函数参数传递,因为我没有对其进行优化。如何获得作为目标函数中参数函数的优化值?

import numpy as np
import matplotlib.pyplot as mp
from scipy.stats import lognorm
from scipy.optimize import minimize
from numdifftools import Jacobian, Hessian

def fun(y):
    li = 1e4
    wj = 0.1
    wk = 0.4
    wjk = 0.2
    pji = 1 - lognorm.cdf(y[0], 10)
    pki = 1 - lognorm.cdf(y[1], 10)
    return (li*(wj * pji + wk * pki - wjk * pji * pki ) + y[0] + y[1])

def fun_der(x):
    return Jacobian(lambda x: fun(x))(x).ravel()

def fun_hess(x):
    return Hessian(lambda x: fun(x))(x)

def main():

    y0 = [100.0, 100.0]
    b = (0, np.inf)
    bounds = (b, b)
    y=minimize(fun, y0, bounds=bounds, method='SLSQP', jac=fun_der, hess=fun_hess).__getitem__('x')
    print(y, fun(y))


main()```

1个回答

有几种方法可以做到这一点。例如,您可以定义一个新函数 fun_wjk(y) = fun(y, wjk) 每次您想要使用不同的 wjk 值进行最小化。


import numpy as np
import matplotlib.pyplot as mp
from scipy.stats import lognorm
from scipy.optimize import minimize
from numdifftools import Jacobian, Hessian

def fun(y, wjk_value):
    li = 1e4
    wj = 0.1
    wk = 0.4
    wjk = wjk_value
    pji = 1 - lognorm.cdf(y[0], 10)
    pki = 1 - lognorm.cdf(y[1], 10)
    return (li*(wj * pji + wk * pki - wjk * pji * pki ) + y[0] + y[1])

def fun_der(x, wjk_value):
    return Jacobian(lambda x: fun(x, wjk_value))(x).ravel()

def fun_hess(x, wjk_value):
    return Hessian(lambda x: fun(x, wjk_value))(x)

def main(wjk):

    y0 = [100.0, 100.0]
    b = (0, np.inf)
    bounds = (b, b)
    fun_wjk = lambda y : fun(y, wjk_value=wjk)
    fun_der_wjk = lambda y : fun_der(y, wjk_value=wjk)
    fun_hess_wjk = lambda y : fun_hess(y, wjk_value=wjk)
    y=minimize(fun_wjk, y0, bounds=bounds, method='SLSQP', jac=fun_der_wjk, hess=fun_hess_wjk).__getitem__('x')
    print(y, fun_wjk(y))


main(wjk=0.15)
main(wjk=0.2)
main(wjk=0.25)

您还可以将 wjk 作为参数传递给 fun,如scipy.optimize.minimize 文档中所述。它还将参数传递给 Jacobian 和 Hessian。

import numpy as np
import matplotlib.pyplot as mp
from scipy.stats import lognorm
from scipy.optimize import minimize
from numdifftools import Jacobian, Hessian

def fun(y, *args):
    li = 1e4
    wj = 0.1
    wk = 0.4
    try:
        wjk = args[0]
    except Exception:
        wjk = 0.2
    pji = 1 - lognorm.cdf(y[0], 10)
    pki = 1 - lognorm.cdf(y[1], 10)
    return (li*(wj * pji + wk * pki - wjk * pji * pki ) + y[0] + y[1])

def fun_der(x, *args):
    return Jacobian(lambda x: fun(x, *args))(x).ravel()

def fun_hess(x, *args):
    return Hessian(lambda x: fun(x, *args))(x)

def main(wjk):

    y0 = [100.0, 100.0]
    b = (0, np.inf)
    bounds = (b, b)
    y=minimize(fun, y0, bounds=bounds, args=(wjk,), method='SLSQP', jac=fun_der, hess=fun_hess).__getitem__('x')
    print(y, fun(y))


main(wjk=0.15)
main(wjk=0.2)
main(wjk=0.25)