Search code examples
pythonpandasoptimizationmathematical-optimizationpulp

python pulp: How do I create LpMaximize and LpMinimize problem?


How do I go about creating an optimization that LpMaximize profits and LpMinimize the variance?

I tried making var negative than using LpMaximize. The code below just the max of var and not the min of var and the max of profit.

  prob += lpSum([profits[i]*x[i] for i in N] and [var[v]*x[v] for v in N]) #tried this

  my full code is below 


 from pulp import *
 # PROBLEM DATA:
 costs = [15, 25, 35, 40, 45, 55]
 profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
 var=[24, 12, 24, 32, 52, 62]
 city = ["NYC","SF","LA","SF","NYC","LA"] 
 max_cost = 2500
 max_to_pick = 4

 # DECLARE PROBLEM OBJECT:
 prob = LpProblem("Mixed Problem", LpMaximize)
 # VARIABLES
 n = len(costs)
 N = range(n)
 x = LpVariable.dicts('x', N, cat="Binary")

 # OBJECTIVE
 prob += lpSum([profits[i]*x[i] for i in N] and [var[v]*x[v] for v in N])



 # CONSTRAINTS
 prob += lpSum([x[i] for i in N]) == max_to_pick   # to include
 prob += lpSum([x[i]*costs[i] for i in N]) <= max_cost  # Limit max.

# NEW CONSTRAINT
for c in set(city):
  index_list = [i for i in N if city[i] == c] 
  prob += lpSum([x[i] for i in index_list]) <= 1

# SOLVE & PRINT RESULTS
prob.solve()
print(LpStatus[prob.status])
print('Profit = ' + str(value(prob.objective)))
print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))

for v in prob.variables ():
   print (v.name, "=", v.varValue)

Many thanks!

I think this is the final answer

   from pulp import *
   # PROBLEM DATA:
   costs = [15, 25, 35, 40, 45, 55]
   profits = [1.7, 2, 2.4, 3.2, 5.6, 6.2]
   var=[24, 12, 24, 32, 52, 62]
   city = ["NYC","SF","LA","SF","NYC","LA"] 
   max_cost = 2500
   max_to_pick = 4

   # DECLARE PROBLEM OBJECT:
   prob = LpProblem("Mixed Problem", LpMaximize)
   # VARIABLES
   n = len(costs)
   N = range(n)
   x = LpVariable.dicts('x', N, cat="Binary")

    # OBJECTIVE
   prob += lpSum([profits[i]*x[i] for i in N])



   # CONSTRAINTS
  prob += lpSum([x[i] for i in N]) == max_to_pick    #Limit number 
  prob += lpSum([x[i]*costs[i] for i in N]) <= max_cost  #max cost


  # NEW CONSTRAINT
 for c in set(city):
   index_list = [i for i in N if city[i] == c] 
   prob += lpSum([x[i] for i in index_list]) <= 1





  # SOLVE & PRINT RESULTS
  prob.solve()

  obj = value(prob.objective)
  print(LpStatus[prob.status])
  print('obj = ' + str(value(prob.objective)))

 # MODIFY PROBLEM FOR 2ND PROBLEM
  prob.sense = LpMinimize # change sense to LpMinimize
  prob += lpSum([var[v]*x[v] for v in N]) # Reset the objective
  prob += lpSum([profits[i]*x[i] for i in N]) == obj #Add constraint 
  fixes profits

  # SOLVE 2ND PROBLEM
 prob.solve()
 print(LpStatus[prob.status])
 print('obj = ' + str(value(prob.objective)))
 print('Profits ='+str(sum([x[i].varValue*profits[i] for i in N])))
 print('Variance = ' + str(sum([x[i].varValue*var[i] for i in N])))
 print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))

I using the combined solution of Magnus Åhlander. Of maxing the profit and min the var.


Solution

  • Two possible approaches:

    1. Maximize for one objective (profit), then add it as a constraint and solve for the other objective (variance).
    2. Make the objective a weighted sum (like you are doing, just negate the variance part).

    EDIT:

    Details to Approach 1:

    Initially, solve the 1st problem (maximize profits):

    ...
    # DECLARE PROBLEM OBJECT:
    prob = LpProblem("Mixed Problem", LpMaximize)
    
    # OBJECTIVE
    prob += lpSum([profits[i]*x[i] for i in N])
    ...
    

    Then, solve 2nd problem (mimimize variance), thereby fixing profits through an extra constraint (using the obj value from the first solution):

    ...    
    # DECLARE PROBLEM OBJECT:
    prob = LpProblem("Mixed Problem", LpMinimize)
    
    # OBJECTIVE
    prob += lpSum([var[v]*x[v] for v in N])
    
    # Extra constraint that fixes profits     
    prob += lpSum([profits[i]*x[i] for i in N]) == <<obj from solving first problem>>
    ...
    

    EDIT 2:

    How to modify the model for the second problem (will raise a warning since objective is modified):

    ...
    prob.solve()
    obj = value(prob.objective)
    print(LpStatus[prob.status])
    print('obj = ' + str(value(prob.objective)))
    
    # MODIFY PROBLEM FOR 2ND PROBLEM
    prob.sense = LpMinimize # change sense to LpMinimize
    prob += lpSum([var[v]*x[v] for v in N]) # Reset the objective
    prob += lpSum([profits[i]*x[i] for i in N]) == obj # Add constraint that fixes profits
    
    # SOLVE 2ND PROBLEM
    prob.solve()
    print(LpStatus[prob.status])
    print('obj = ' + str(value(prob.objective)))
    print('Profits = ' + str(sum([x[i].varValue*profits[i] for i in N])))
    print('Variance = ' + str(sum([x[i].varValue*var[i] for i in N])))
    print('Cost = ' + str(sum([x[i].varValue*costs[i] for i in N])))
    ...