我想通过购买一定数量的门票来最大化赢得抽奖的可能性。为此,我写了以下代码
import numpy as np
import math as mt
from scipy.optimize import minimize
from pulp import *
def objective(tickets, winners = 500, losers = 2500, cost_of_ticket = 40, winning_amt = 1000):
Pwin = 1 - mt.factorial(losers)//mt.factorial(losers - tickets)*mt.factorial(winners+losers-tickets)/mt.factorial(winners+losers)
Ewin = Pwin*(winning_amt - cost_of_ticket*tickets)
return Ewin
# declare your variables
tickets = LpVariable("tickets", range(0, 10)) # 0<= tickets <= 10
prob = LpProblem("problem", LpMaximize)
#define the objective
prob += objective(tickets)
# solve the problem
status = prob.solve(GLPK(msg=0))
LpStatus[status]
# print the results
value(tickets)
问题似乎是传递给目标函数的票证数量不是整数(并且因子函数失败)。任何人都可以建议我应该如何确保票证限制为正整数值?
检查的答案应该是8.我可以通过手动调用目标函数并检查来完成此操作。
答案 0 :(得分:1)
你的目标确实是
ExpWin(t) = choose(N,t)*(A-C*t)
其中t是整数变量,N,A,C是常数。这是一个非线性函数,因此线性MIP求解器将无法处理此问题。
对于这个问题,它很愚蠢,但一般来说我们可以将其线性化。用以下内容引入二进制变量x(i):
x(i) = 1 if tickets=i
0 otherwise
这可以通过
强制执行sum(i,x(i)) = 1
sum(i,i*x(i)) = tickets
只有在变量票据的范围很小(在您的情况下为10)时才有意义。现在我们可以预先计算一个常数数组w(i),如果票数是i,这是预期的胜利。现在目标看起来像:
max sum(i, w(i)*x(i))
现在是线性的。
无论如何,离开代码并在数学中写下问题总是一个好主意。这可以帮助您以不同的方式思考问题。