简体   繁体   中英

How to cap a variable in Pulp optimization?

I am trying to optimize the overall sales of a product(for a period of 3 months) using forecasted cost and sales. my current data looks like below

>     Month |    sales quantity  | discount % | Total inventory
      1     |         12         |    5       |      45
      1     |         23         |    9       |      45
      1     |         40         |    15      |      45
      2     |         23         |    5       |      45

each month has a few discounts based on that sales are predicted. Total inventory is the sum of inventory across all months. I am trying to maximize overall sales using pulp but, the optimized result always chooses the highest sales quantity in each month, which most of the time exceeds Total inventory .

I need to cap sales quantity values(to zero) when overall sales exceed Total inventory .

keeping constraints like lpSum(x[i]*sales_quantity[i] for i in unique_months) < total_inventory results in an infeasible solution. A small snippet of my code:

import pulp as lp 

# `data` is a DataFrame contains above data
x = LpVariable.dicts("x", range(0, len(data)), 0, 1, LpBinary) 

prob = lp.LpProblem("test problem", lp.LpMaximize)

# obj function
prob += lpSum(x[i] * data.loc[i, 'sales quantity'] for i in range(0, len(data)))

# constraints
prob += lpSum(x[i] * data.loc[i, 'sales quantity'] for i in range(0, len(data))) >= threshold_inventory_to_clear

# constraints to select each month(without missing any)
for j in list(data['Month'].unique()):
    if j == data['Month'].max():
       break
    sub_idx_current = data[data['Month'] == j].index
    sub_idx_next = data[data['Month'] == j + 1].index
    prob += lpSum(x[idx_current] * data.loc[idx_current, 'Month'] for idx_current in sub_idx_current) \
                        <= lpSum(x[idx_next] * data.loc[idx_next, 'Month'] for idx_next in sub_idx_next)

# Need to replace this constraints with some calling logic
prob += lpSum(x[i]*data.loc[i, 'sales quantity'] for i in range(0, len(data)) < total_inventory

If I understand your problem correctly you have the option to sell or not sell in every month? And you want to maximize your revenue such that you do not sell more than what you have in you inventory. I am not sure though whether you are dealing with multiple products.

If I understood your problem correctly the following should do the trick for a single product over 4 different time periods.

import pulp
import pandas as pd

max_quantity = 45
df = pd.DataFrame({
    "sales_quantity": [12,23,40,23],
    "discount": [5,9,15,5]
})

prob = pulp.LpProblem("MaxSales", pulp.LpMaximize)

X = [pulp.LpVariable('var_'+str(i), 0, 1, pulp.LpBinary) for i, sq in enumerate(df['sales_quantity'])]
prob += pulp.LpAffineExpression({X[i]: (100-df['discount'][i])*df['sales_quantity'][i] 
                                 for i in range(0,len(df))}, name='Objective')
prob += pulp.LpAffineExpression({X[i]: df['sales_quantity'][i] for i in range(0,len(df))})<=max_quantity, "Max Inventory"
prob.solve()
print(prob)
print("Revenue: " + str(pulp.value(prob.objective)))
print([pulp.value(x) for x in X])

Output:

MaxSales:
MAXIMIZE
1140*var_0 + 2093*var_1 + 3400*var_2 + 2185*var_3 + 0
SUBJECT TO
Max_Inventory: 12 var_0 + 23 var_1 + 40 var_2 + 23 var_3 <= 45

VARIABLES
0 <= var_0 <= 1 Integer
0 <= var_1 <= 1 Integer
0 <= var_2 <= 1 Integer
0 <= var_3 <= 1 Integer

Revenue: 3400.0
[0.0, 0.0, 1.0, 0.0]

If I misunderstood anything let me know. I have no right to comment so I couldn't ask for clarification beforehand.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM