<p>虽然您要求使用库<code>mystic</code>,但在开始非线性优化时,您可能不需要这种细粒度的控制。模块<code>scipy</code>应该足够了。以下是一个或多或少完整的解决方案,纠正了我认为原始白皮书中有关定价界限的错误:</p>
<pre><code>import numpy as np
from scipy.optimize import minimize
P_nom = 89
P_max = None
price_elasticity = 2
number_of_days = 7
demand = lambda a, L: 1./L
total_rooms = [5]*number_of_days
def objective(P, *args):
return -np.dot(P, O(P, *args))
def worst_leftover(P, C, *args):
return min(np.subtract(C, O(P, *args)))
def X(P, a, L, d, e, P_nom):
return d(a, L)*(sum(P[a:a+L])/P_nom/L)**e
def d(a, L):
return 1.
def O_l(P, l, l_max, *args):
return sum([X(P, a, L, *args)
for a in xrange(0, l)
for L in xrange(l-a+1, l_max+1)])
def O(P, *args):
return [O_l(P, l, *args) for l in xrange(len(P))]
result = minimize(
objective,
[P_nom]*number_of_days,
args=(number_of_days-1, demand, price_elasticity, P_nom),
method='SLSQP',
bounds=[(0, P_max)]*number_of_days,
constraints={
'type': 'ineq',
'fun': worst_leftover,
'args': (total_rooms, number_of_days-1, demand, price_elasticity, P_nom)
},
tol=1e-1,
options={'maxiter': 10**3}
)
print result.x
</code></pre>
<p>有几点值得一提:</p>
<ol>
<li><p>与原始白皮书中引用的最大化相比,目标函数有一个附加的减号,用于scipy的<code>minimize()</code>例程。这将导致<code>result.fun</code>为负数,而不是显示总收入。</p></li>
<li><p>这个公式似乎对参数有点敏感。最小化是正确的(至少,当它说它正确地执行check<code>result.success</code>)时是正确的,但是如果输入值与实际值相差太远,那么您可能会发现价格远高于预期。您可能还希望使用比下面示例中更多的天数。你的白皮书似乎引发了周期性的影响。</p></li>
<li><p>我不是白皮书的命名方案的真正粉丝,因为它与可读代码有关。我改变了一些东西,但是有些东西确实很糟糕,应该被替换,比如小写字母l,它很容易被数字1混淆。</p></li>
<li><p>我确实设定了界限,所以价格是正的而不是负的。根据您的领域专业知识,您应该验证这是正确的决定。</p></li>
<li><p>你可能更喜欢比我指定的更严格的公差。这在某种程度上取决于您希望运行时是什么。请随意使用<code>tol</code>参数。另外,对于更严格的公差,您可能会发现<code>options</code>参数中的<code>'maxiter'</code>必须增加,才能使<code>minimize()</code>正确收敛。</p></li>
<li><p>我很确定<code>total_rooms</code>应该是酒店中尚未预订的房间数,因为白皮书的索引是字母l,而不是像原来代码中那样的常量。为了测试的目的,我将它设置为一个常量列表。</p></li>
<li><p>方法必须是“SLSQP”,以处理价格和房间数量的界限。注意不要换这个。</p></li>
<li><p>如何计算<code>O_l()</code>存在着巨大的低效。如果运行时是个问题,那么我要做的第一步是找出如何缓存/记忆对<code>X()</code>的调用。所有这些实际上只是第一次通过,概念证明。它应该是合理的无缺陷和正确的,但是它几乎是直接从白皮书中提取出来的,并且可以进行一些重新分解。</p></li>
</ol>
<p>任何人,玩得开心,并随时评论/下午/等任何进一步的问题。在</p>