Re: How to update LP variable limit constaints in Schedule problem

639 views
Skip to first unread message

Stuart Mitchell

unread,
Apr 21, 2015, 7:31:06 AM4/21/15
to pulp-or...@googlegroups.com

You need to use binary variables to model this in your problem. How you do this is up to you but maybe this reference will help

http://mat.gsia.cmu.edu/orclass/integer/integer.html

Hi all,

I’m trying to solve an storage optimization problem using PULP in Python, where given daily prices I want to maximize the profit, say for the next year (365 days). I have defined a list of 365 variables “net_withdrawals” (positive number for withdrawals and negative if injections), and set an initial lower and upper limits in the declaration.

 

However, and I also have constraints defined that, the storage stock/inventory level at any time must be between 0 and maximum capacity, and so far so good. I’m having issue with adding another constraints to “futher“ limit the “net_withdrawals” variables for each day between a narrower range, based on the current stock level: e.g, withdrawal rate is halved and injection rate is doubled if the stock goes below 50% of the total capacity, and vice versa.

 

I can work out the current stock level, however as it is an Affine Expressions, I cannot seem to use if-else conditional statement to check his value and define the new limits for “net_withdrawals” variables. E.g.: total capacity is 1000, and I tried:

 

 

Optimization_model = pulp.LpProblem(Model - LP', pulp.LpMaximize)

periods = range(0, NUMBER_OF_DAYS)

net_withdrawals = [pulp.LpVariable("net_withdrawals_%s" % i, lowBound=-50, upBound=50) for i in periods]

 

For day in periods:

Stock_level -= net_withdrawals[i]

 

If stock_level < 500:

Optimization_model += net_withdrawals[i] < -25

Optimization_model += net_withdrawals[i] > 50

                        Else:

Optimization_model += net_withdrawals[i] < -50

Optimization_model += net_withdrawals[i] > 25

 

           

I’d like to add different constraints for boundary limits based on different stock levels, e.g. 25%, 50%, 75% etc…

But I could not seem to get this basic logic working.

 

Would you be able to suggest/advice?

I really appreciate it and thanks in advance.

--
You received this message because you are subscribed to the Google Groups "pulp-or-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pulp-or-discu...@googlegroups.com.
To post to this group, send email to pulp-or...@googlegroups.com.
Visit this group at http://groups.google.com/group/pulp-or-discuss.
For more options, visit https://groups.google.com/d/optout.

Alex Tian

unread,
Apr 21, 2015, 8:52:34 AM4/21/15
to pulp-or...@googlegroups.com
Hi Stuart,

Thanks for the reply!

I've defined 4 list of variables in total now, with 2 new lists of interger/binary variable, and for any period, I wanted to the program to use either of 2 "netInj_vars_" variables, and I'll have a corresponding "netInj_flags_" to indicate which to use. However I got the below errors in both objectives and constraints, I'm a newbie here :( could you please advise how to fix it? 

Or should I use change to use a different way to translate the problem in Pulp?

Error:
    raise TypeError("Non-constant expressions cannot be multiplied")
    TypeError: Non-constant expressions cannot be multiplied

netInj_flags_1 = [pulp.LpVariable("NW_%s" % i, lowBound=0, upBound=1, cat=pulp.LpInteger) for i in periods]
netInj_vars_1 = [pulp.LpVariable("NW_%s" % i, lowBound=MAX_WITHDRAWAL_RATE/2, upBound=MAX_INJECTION_RATE, cat=pulp.LpInteger) for i in periods]

netInj_flags_2 = [pulp.LpVariable("NW_%s" % i, lowBound=0, upBound=1, cat=pulp.LpInteger) for i in periods]
netInj_vars_2 = [pulp.LpVariable("NW_%s" % i, lowBound=MAX_WITHDRAWAL_RATE, upBound=MAX_INJECTION_RATE/2, cat=pulp.LpInteger) for i in periods]

# ERROR on next line for objectives
gas_model += (
pulp.lpSum(
[netInj_flags_1[i]*netInj_vars_1[i]*-prices[i] + netInj_flags_2[i]*netInj_vars_2[i]*-prices[i] for i in periods]
), "profit")


# ERROR on next line for constraints
gas_model += [netInj_flags_1[i] + netInj_flags_2[i] == 1 for i in periods] 

stockLevel = INITIAL_STOCK_LEVEL
for i in periods:
stockLevel += netInj_flags_1[i]*netInj_vars_1[i] + netInj_flags_2[i]*netInj_vars_2[i]

gas_model += stockLevel >= 0
gas_model += stockLevel <= 1000

gas_model.solve()

Stuart Mitchell

unread,
Apr 21, 2015, 5:41:08 PM4/21/15
to pulp-or...@googlegroups.com
You cannot model the problem like this as that will be come a non linear problem.

So in general you may not multiply two variables together 

you may want to model it which variables that indicate when your stock level reaches a certain point.

StockLevel[i] <= X[i] * 500 + Y[i] * 1000

X[i] + Y[i] = 1

Then model your other constraints using Y and X.

Read this

for more help.

Stu
--
Stuart Mitchell
PhD Engineering Science
Extraordinary Freelance Programmer and Optimisation Guru

Alex Tian

unread,
Apr 22, 2015, 4:32:05 AM4/22/15
to pulp-or...@googlegroups.com
Thanks Stuart, I cracked last night!
BUT the previous link you sent was very useful, I used Piecewise linear formulations!

Thanks again for your help!
Alex
Reply all
Reply to author
Forward
0 new messages