Reputation: 858
I would like to maximize the probability of winning a raffle by buying a certain number of tickets. For this, I wrote the following code
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)
The issue seems to be that the number of tickets that get passed into the objective function is not an integer (and the factorial function then fails). Can anyone suggest how I should ensure that the ticket is restricted to positive integer values?
The answer, for checking, should be 8. I can do this by manually calling the objective function and checking.
Upvotes: 0
Views: 2988
Reputation: 106
You can restrict a variable to integers when you define it:
tickets = LpVariable("tickets", range(0, 10), cat='Integer') # 0<= tickets <= 10
As per sascha's comment, this is explained here
Upvotes: 0
Reputation: 16782
Your objective is really
ExpWin(t) = choose(N,t)*(A-C*t)
where t is an integer variable and N,A,C are constants. This is a nonlinear function so a linear MIP solver will not be able to handle this.
For this problem it is silly, but in general we can linearize this. Introduce binary variables x(i) with:
x(i) = 1 if tickets=i
0 otherwise
This can be enforced by
sum(i,x(i)) = 1
sum(i,i*x(i)) = tickets
This only makes sense if the range of variable tickets is small (in your case 10). Now we can precalculate a constant array w(i) which is the expected win if the number of tickets is i. Now the objective can look like:
max sum(i, w(i)*x(i))
which is now linear.
Anyway it is always a good idea to step away from code and write down the problem in math. This can help you think about the problem in a different way.
Upvotes: 1