如何使用python在短时间内获得具有两个变量积分表达式的成本函数的最小值? [英] How to get the minimum value of a cost function, having two variable integration expression, in short time using python?

查看:96
本文介绍了如何使用python在短时间内获得具有两个变量积分表达式的成本函数的最小值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到成本函数T 的最小值.成本函数 T 具有两个变量( Q和r )的表达式.我还需要找到成本函数 T 达到全局最小值的 Q和r 值. (如果有多个全局最小值-那么全部)Q和r的边界是: 0< Q < 15000; 0 < & 5000 这是方程式

I want to find the minimum value of the cost function T. The cost function T has an expression in two variables (Q and r). I also need to find values of Q and r at which the cost function T reaches the global minimum. (if multiple global minimum values - then all) The bounds of Q and r are : 0 < Q < 15000 ; 0 < r < 5000 Here are the equations

我正在使用 Sympy库来生成方程式.并使用 scipy.optimize.minimize 来找到最小值.这些功能的代码为:

I am using Sympy library to generate the equations. and using the minimize function of scipy.optimize.minimize to find the minimum value. The code for the functions are:

from sympy import *
from scipy.optimize import root_scalar
mean, std = 291, 253
l = 7 #
m = 30
#Q = mean*(lead_time + shelf_life)
p = 5
w = 2
K = 100
c = 5
h = 0.001 #per unit per  day
x = symbols("x")
t = symbols("t")
r = symbols("r")
Q = symbols("Q")
#defining Cumulative distribution function
def cdf():
  cdf_eqn = (1/(std*sqrt(2*pi)))*exp(-(((t-mean)**2)/(2*std**2)))
  cdf = Integral(cdf_eqn, (t,-oo,x)).doit()
  return cdf
#defining Probability density function
def pdf():
  pdf = (1/(std*sqrt(2*pi)))*exp(-((( (x - mean)**2)/(2*std**2)))).doit()
  return pdf
pdf = pdf()
cdf = cdf()
#getting the equation in place
G = K + c*Q + w*(Integral(cdf , (x, 0, Q)) + Integral(cdf.subs(x, (r + Q - x))*cdf , (x, 0, r)))\
     + p*(mean*l - r + Integral(cdf , (x, 0, r)))
CL = (Q - r + mean*l - Integral(cdf , (x, 0, Q)) - Integral(cdf.subs(x, (r + Q - x))*cdf , (x, 0, r)) + Integral(cdf , (x, 0, r)))/mean  
I = h*(Q + r - mean*l - Integral(cdf , (x, 0, Q)) - Integral(cdf.subs(x, (r + Q - x))*cdf , (x, 0, r)) + Integral(cdf , (x, 0, r)))/2
#TC.free_symbols
#optimising the cost function
from  scipy import optimize
def f(params):
    r, Q = params 
    TC = G/CL + I
    return TC
initial_guess = [2500., 10000.]
result = optimize.minimize(f, initial_guess, tol=1e-6 )
if result.success:
    fitted_params = result.x
    print(fitted_params)
else:
    raise ValueError(result.message)

但是会引发如下错误.

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/scipy/optimize/optimize.py in _approx_fprime_helper(xk, f, epsilon, args, f0)
    699             try:
--> 700                 df = df.item()
    701             except (ValueError, AttributeError):
AttributeError: 'Zero' object has no attribute 'item'
During handling of the above exception, another exception occurred:
ValueError                                Traceback (most recent call last)
5 frames
<ipython-input-6-e9bb4190fef5> in <module>()
     39     return TC
     40 initial_guess = [2500., 10000.]
---> 41 result = optimize.minimize(f, initial_guess, tol=1e-6 )
     42 if result.success:
     43     fitted_params = result.x
/usr/local/lib/python3.6/dist-packages/scipy/optimize/_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    602         return _minimize_cg(fun, x0, args, jac, callback, **options)
    603     elif meth == 'bfgs':
--> 604         return _minimize_bfgs(fun, x0, args, jac, callback, **options)
    605     elif meth == 'newton-cg':
    606         return _minimize_newtoncg(fun, x0, args, jac, hess, hessp, callback,
/usr/local/lib/python3.6/dist-packages/scipy/optimize/optimize.py in _minimize_bfgs(fun, x0, args, jac, callback, gtol, norm, eps, maxiter, disp, return_all, **unknown_options)
   1007     else:
   1008         grad_calls, myfprime = wrap_function(fprime, args)
-> 1009     gfk = myfprime(x0)
   1010     k = 0
   1011     N = len(x0)
/usr/local/lib/python3.6/dist-packages/scipy/optimize/optimize.py in function_wrapper(*wrapper_args)
    325     def function_wrapper(*wrapper_args):
    326         ncalls[0] += 1
--> 327         return function(*(wrapper_args + args))
    328 
    329     return ncalls, function_wrapper
/usr/local/lib/python3.6/dist-packages/scipy/optimize/optimize.py in approx_fprime(xk, f, epsilon, *args)
    763 
    764     """
--> 765     return _approx_fprime_helper(xk, f, epsilon, args=args)
    766 
    767 
/usr/local/lib/python3.6/dist-packages/scipy/optimize/optimize.py in _approx_fprime_helper(xk, f, epsilon, args, f0)
    700                 df = df.item()
    701             except (ValueError, AttributeError):
--> 702                 raise ValueError("The user-provided "
    703                                  "objective function must "
    704                                  "return a scalar value.")
ValueError: The user-provided objective function must return a scalar value.

另外,使用其他方法,需要花费很长时间才能运行,超过30分钟左右,最终会引发错误. 如何在很短的时间内找到全局最小值以及Q和r的值.最好是1-5分钟左右.

Additionally, with other methods, it takes a long time to run, more than 30 minutes or so and ends up throwing an error. How can I find the global minima and also the values of Q and r in a very short time. Preferably 1-5 minutes or so.

代表我的朋友发帖

Posting on behalf of my Friend

推荐答案

只是将来的注意事项:在函数f中,如果将rQ设置为某些值,则不会更改SymPy您以后使用的表达式,因为它们先前已为符号变量定义.

Just a note for the future: in your function f, if you set r and Q to something, it does not change the SymPy expressions that you use afterwards since they were already previously defined for symbolic variables.

您的工作似乎非常数值化,实际上,由于您的答案不需要符号,因此您最好进行非符号集成. SymPy是纯Python,特别是对于集成而言,它可能会很慢,而SciPy则被设计为快速.这就是为什么我将所有内容都转换为SciPy的原因:

Your work seems heavily numerical and in fact, since your answers don't need symbols, you're probably better doing non-symbolic integration. SymPy is pure Python which can be slow especially for integration while SciPy is designed to be fast. That's why I converted everything to SciPy things:

我知道我对r=0收敛的第一个回答是可疑的. @VishalAnand对从-inf开始的cdf积分的校正后,我尝试再次运行该程序. T的一次迭代花了大约15秒,却没有找到解决方案.可能是由于现在存在非常复杂的表面.

I knew that my first answer with the r=0 convergence was fishy. After @VishalAnand's correction for the integral of the cdf starting from -inf, I tried running the program again. It took ~15 seconds for a single iteration of T and it was not finding a solution; probably due to a now very complex surface that now exists.

cdf也产生了错误的值;例如,quad(pdf, -np.inf, 50000)[0]产生了一个非常接近0的数字,而它本来应该接近1.这破坏了最小化,因此我尝试了类似quad(pdf, -1000000, 50000)[0]的方法,结果产生的值与sympy.N(sympy.erf((x-mean)/(sqrt(2)*std)))/2 + 1/2相似,结果更快地进行计算.

The cdf was also producing wrong values; for example, quad(pdf, -np.inf, 50000)[0] produced a number very close to 0 when instead it should have been close to 1. This ruined the minimization and so I tried something like quad(pdf, -1000000, 50000)[0] which turned out to produce similar values to sympy.N(sympy.erf((x-mean)/(sqrt(2)*std)))/2 + 1/2 which turned out to be faster to compute.

问题是SciPy最小化函数无法收敛,而是生成了ABNORMAL_TERMINATION_IN_LNSRCH.因此,我给了它一种特定的使用方法:Nelder-Mead.这汇合了.但是最终值非常令人担忧,因为它们在inf-1.793193606659277e+19之间跳转. Python不知道溢出错误(至少据我所知),因此我能想到的唯一可能的解释是函数C的根导致T在r和Q的某些值上具有渐近线.

The problem is that the SciPy minimize function could not converge but rather produced ABNORMAL_TERMINATION_IN_LNSRCH. So I gave it a specific method to use: the Nelder-Mead. This converged. But the final values were very concerning since they were jumping between inf and -1.793193606659277e+19. Python is not known for overflow errors (at least to my knowledge) so the only possible explanation I can think of is that the function C has a root that causes T to have an asymptote at some values of r and Q.

这远远超出了我的范围,所以我将在这里留下最新的努力

This is far beyond me so I'll just leave my updated efforts here:

from numpy import sqrt, pi, exp, inf
from sympy import erf, N
from scipy import optimize
from scipy.integrate import quad

mean, std = 291, 253
l = 7
m = 30
# Q = mean*(lead_time + shelf_life)
p = 5
w = 2
K = 100
c = 5
h = 0.001  # per unit per  day


# defining Probability density function
def pdf(x):
    return (1 / (std * sqrt(2 * pi))) * exp(-(((x - mean) ** 2) / (2 * std ** 2)))


# defining Cumulative distribution function
def cdf(x):
    # cdf1 = quad(pdf, -1000000, x)[0]  # slow
    # cdf2 = quad(pdf, -inf, x)[0]  # slow and produces wrong values at hugh positive x
    cdf3 = N(erf((x-mean)/(sqrt(2)*std)))/2 + 1/2
    return cdf3


# getting the equation in place
def G(r, Q):
    return K + c * Q \
           + w * (quad(cdf, 0, Q)[0] + quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]) \
           + p * (mean * l - r + quad(cdf, 0, r)[0])


def CL(r, Q):
    return (Q - r + mean * l - quad(cdf, 0, Q)[0]
            - quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]
            + quad(cdf, 0, r)[0]) / mean


def I(r, Q):
    return h * (Q + r - mean * l - quad(cdf, 0, Q)[0]
                - quad(lambda x: cdf(r + Q - x) * cdf(x), 0, r)[0]
                + quad(cdf, 0, r)[0]) / 2


def f(params):
    r, Q = params
    TC = G(r, Q)/CL(r, Q) + I(r, Q)
    return TC


initial_guess = [2343.70601496,  239.89137499]
result = optimize.minimize(f, initial_guess, bounds=[(0, 5000), (0, 15000)], method="Nelder-Mead")
# result = f(initial_guess)  # single check
print(result)


在约15秒内产生以下输出:

Resulting in the following output in ~15 seconds:

 final_simplex: (array([[2343.70594323,  257.01581672],
       [2343.70594323,  257.01581672],
       [2343.70594323,  257.01581672]]), array([-1.79319361e+19, -1.79319361e+19, -1.79319361e+19]))
           fun: -1.793193606659277e+19
       message: 'Optimization terminated successfully.'
          nfev: 360
           nit: 155
        status: 0
       success: True
             x: array([2343.70594323,  257.01581672])

希望更有资格的人可以解释这一点.对于给自己带来的任何不便或错误结论,我们深表歉意.

Hopefully someone more qualified can explain this. Apologies for any inconvenience or false conclusions from myself.

这篇关于如何使用python在短时间内获得具有两个变量积分表达式的成本函数的最小值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆