Python线性编程 - 如何将变量约束为整数

时间:2017-11-17 03:19:50

标签: python constraints pulp

我想通过购买一定数量的门票来最大化赢得抽奖的可能性。为此,我写了以下代码

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.我可以通过手动调用目标函数并检查来完成此操作。

1 个答案:

答案 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))

现在是线性的。

无论如何,离开代码并在数学中写下问题总是一个好主意。这可以帮助您以不同的方式思考问题。