1
$\begingroup$

I am new to modeling LP with Pulp in Python and I need some help with defining a constraint with multiple variables with different indexes. Please see below.

  1. The constraint is defined on A, B, C indexes.
  2. Start_Inv and End_Inv variables are again defined on A, B, C indexes.
  3. Production variable is defined on A, B, C, D indexes.

I want Production variable to be summed by A, B, C and enter the constraint.

Below is what I wrote and of course it doesn't work.

for A, B, C in Start_Inv_DF.index:

    model += Start_Inv[(A, B, C)] + Production[(A, B, C, D)] == End_Inv[(A, B, C)]

Is there an easy way to model this? Probably, I need a coefficient to do "SUM Production group by A, B, C", can you please advise how to create one?

Adding more details. 1/13/2022

I have tried lpSUM and it works for two indexes but not for three or more. Can you please see what I am doing wrong?

  1. This 2 indexes case works.
import pandas as pd 
import pulp as plp

tuples1 = [('DE', 'Apple'),
          ('DE', 'Orange'),
          ('PA', 'Apple'),
          ('PA', 'Orange')]

index1 = pd.MultiIndex.from_tuples(tuples1, names=["Location", "Product"])
DF1 = pd.DataFrame({'Count A': [12., 70., 30., 20.], 'Count B': [12., 70., 30., 20.]}, index=index1)

Production1 = plp.LpVariable.dicts("Production1",
                              ((Location, Product) for Location, Product in DF1.index),
                              lowBound=0,
                              cat='Continuous')

Products = ['Apple', 'Orange']

for Location, Product in DF1.index:
    print(plp.lpSum(Production1[(Location, Product)] for Product in Products))
  1. This 3 indexes case errors out.
import pandas as pd 
import pulp as plp

tuples1 = [('DE', 'Apple'),
          ('DE', 'Orange'),
          ('PA', 'Apple'),
          ('PA', 'Orange')]

index1 = pd.MultiIndex.from_tuples(tuples1, names=["Location", "Product"])
DF1 = pd.DataFrame({'Count A': [12., 70., 30., 20.], 'Count B': [12., 70., 30., 20.]}, index=index1)

tuples2 = [('DE', 'Apple', 'Truck'),
           ('DE', 'Orange', 'Rail'),
           ('DE', 'Apple', 'Rail'),
           ('DE', 'Orange', 'Truck'),
           ('PA', 'Apple', 'Truck'),
           ('PA', 'Orange', 'Rail')]

index2 = pd.MultiIndex.from_tuples(tuples2, names=["Location", "Product", "Mode"])
DF2 = pd.DataFrame({'Count A': [12., 70., 30., 20., 20., 40], 'Count B': [12., 70., 30., 20., 80., 30.]}, index=index2)

Production2 = plp.LpVariable.dicts("Production2",
                              ((Location, Product, Mode) for Location, Product, Mode in DF2.index),
                              lowBound=0,
                              cat='Continuous')

Modes = ['Truck', 'Rail']

for Location, Product in DF1.index:
    print(plp.lpSum(Production2[(Location, Product, Mode)] for Mode in Modes))
$\endgroup$
5
  • $\begingroup$ Assuming you have import pulp at the beginning, what you need is pulp.lpSum() method for summing over variable D. So, replace your Production[(A,B,C,D)] with pulp.lpSum(Production[(A,B,C,D] for all D in your_d_index) $\endgroup$
    – EhsanK
    Jan 12 at 14:04
  • $\begingroup$ Thank you. I have already tried this but it does not seem to work. See below. If I do the below it works fine. print(plp.lpSum( [Unmet_Demand[Month, Product, Customer] for Month, Product, Customer in Demand_DF1.index] )) However, if i do this, it fails with a KeyError. print(plp.lpSum( [Unmet_Demand[Month, Product, Customer] for Customer in Demand_DF1.index] )) $\endgroup$
    – Korean_OR
    Jan 12 at 15:51
  • $\begingroup$ without knowing anything, I see that in both of those cases you loop over the same thing (Demand_DF1.index). If that index is comprised of 3 values of (Month, Product, Customer), then you can't use that to only iterate over Customer. In fact, Customer in for Customer in Demand_DF1.index is a tuple of (Month, Product, Customer). If you only want Customer you should use something else. For example, customers = Demand_DF1['Customer'].unique() and then use for customer in customers for your sum. $\endgroup$
    – EhsanK
    Jan 12 at 16:20
  • $\begingroup$ Thank you very much for your prompt responses. I confirmed it works when there are two indexes but it does not seem to work for 3 or more indexes. Not sure what is going wrong at this point. I will continue to look into this and provide an update later. $\endgroup$
    – Korean_OR
    Jan 12 at 22:32
  • $\begingroup$ I have provided more details about my testing with lpSum. Can one of you please try the codes and see what I am doing wrong? $\endgroup$
    – Korean_OR
    Jan 13 at 14:00
1
$\begingroup$

I assume when you say "it doesn't work" you're getting a KeyError which is expected in your 3-index model. Because you have 2 locations, 2 products, and 2 modes. Your 2-index tuple with product and location has all 4 indexes, but your 3-index tuple has 6, missing ('PA', 'Apple', 'Rail') and ('PA, 'Orange', 'Truck').

If this was a mistake, correct your 3-index tuple and your KeyError will be fixed. If not a mistake, then one way to fix this is to change your last line of code to the following, which checks if the key exists in Production2 and if it's not, replaces it with 0:

print(plp.lpSum(Production2.get((Location, Product, Mode), 0) for Mode in Modes))
$\endgroup$
1
  • $\begingroup$ Thank you very much! Your advice solved my issue. $\endgroup$
    – Korean_OR
    Jan 13 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.