I am trying to solve an optimization problem. I use PuLP to solve it. However, the optimal solution given by the solver does not respect the constraints I impose in the code. This is absurd and I don't understand.
Description of the problem : I want to solve the problem given in picture
"sc" means "under constraints" and : f(p, e) = 20 sum_{i=0}^12 s_i + 50 \sum_{i=0}^{11}e[i] {p[i+1]-p[i]}
with s_m = s_0 + sum_{i=1}^m (p_m - d_m)
The sequence u just checks u[i]=sign(p[i+1]-p[i])
d is a sequence of elements that is given.
def q(e, X, p0):
# Constantes et données de l'énoncé
mois = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
mois0 = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
e = {'1': e[0],
'2': e[1],
'3': e[2],
'4': e[3],
'5': e[4],
'6': e[5],
'7': e[6],
'8': e[7],
'9': e[8],
'10': e[9],
'11': e[10],
'12': e[11]}
# Définition du problème
prob = LpProblem("Planification de la production", LpMinimize)
# Définition des variables
p = LpVariable.dicts("mois", mois0, 0)
# Fonction objectif
def lst_mois(m):
L=[]
for i in range(1, m+1):
L.append(str(i))
return L
prob += lpSum([20 * (s0 + lpSum([p[i] - d[i] for i in lst_mois(int(m))])) for m in mois0]) + lpSum([50 * e[i] * (p[i] - p[str(int(i)-1)]) for i in mois]), "Coût à constante près"
# Contraintes
for m in mois:
prob += (s0 + lpSum([p[i] - d[i] for i in lst_mois(int(m))])) >= 0, m
for i in mois:
prob += e[i] * (p[i] - p[str(int(i)-1)]) >= 0, "Contrainte de signe "+i
if X < np.inf:
for i in mois:
prob += p[i] <= X, "Coût maximal "+i
prob += p['0'] == p0
# Résolution
prob.solve()
# On renvoie le résultat sous forme d'un tableau (indices = mois, valeur = volume à produire)
production = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
for v in prob.variables():
production[int(v.name[5])] = v.varValue
print(prob.status)
return production
Then when I try to use this function with :
d = {'0': 0., '1': 120, '2': 220, '3': 120, '4': 620, '5': 650, '6': 650, '7': 650, '8': 100, '9': 150, '10': 520, '11': 510, '12': 500}
p0=600
s0=100
a = q([1,1,1,-1,-1,1,-1,1,1,1,1,1], np.inf, p0)
The result is not the good one because the second constraint is not respected. Indeed, the result is :
[600.0, 466.25, 600.0, 600.0, 282.5, 282.5, 282.5, 282.5, 282.5, 282.5, 0.0, 0.0, 0.0]
and it turns out that the second constraint is never respected.
How to solve this ? Thanks
I think you have a typo when you assign the variables to production
list. It should be:
for v in prob.variables():
production[int(v.name.split("_")[-1])] = v.varValue
Then the result will be:
[600.0, 600.0, 600.0, 600.0, 282.5, 282.5, 282.5, 282.5, 282.5, 282.5, 282.5, 466.25, 466.25]