如何使用python在短时间内获得具有两个变量积分表达式的成本函数的最小值? [英] How to get the minimum value of a cost function, having two variable integration expression, in short time using 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
中,如果将r
和Q
设置为某些值,则不会更改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屋!