-2

I'm trying to write a pyomo optimization that takes a non convex set of prices and solves to determine the best time to purchase and sell within that list of prices. However, I'm unable to get the model to converge and finding difficulty with the pyomo syntax to formulate my problem correctly. Specifically, everytime I try to construct a way to compare that the problem only buys and sells once, I get either the error that it resolves to a trivial false, or that such a constraint is not valid.

my decision variables are as follows:

model.buy = pyo.Var(model.time, within=pyo.Binary)
model.sell = pyo.Var(model.time, within= pyo.Binary)

the constraint I'm attempting to write is:

def buy_sell_constraint(model):
    exp = sum(model.buy) == 1 and sum(model.sell) == 1
    return exp

model.buy_sell_constraint = pyo.Constraint(buy_sell_constraint)

Any direction that can help me figure this out is appreciated.

Jibel
  • 127
  • 2
  • 2
  • 15
Luemas91
  • 1
  • 1
  • there are a lot of syntax issues in just a few lines of code. Do you have a math model for what you are trying to do? You cannot use `and` in formulation. Your variables are indexed (presumably) by `model.time`, but you omit handling that in the constraint? – AirSquid May 15 '23 at 13:28
  • There are other contraints that contain the time index, but the point of this constraint is that there is one single buy and one single sell, but they should be at separate points in time. That's why I sum the model.buy and model.sell variables. – Luemas91 May 15 '23 at 13:45

1 Answers1

1

You should be doing something like this below if you wish to sum. Also note, you cannot use and logic in constraints. There are other (slightly more complicated) ways of formulating logic in integer programs that can be found in several tutorials/texts/other examples on this site.

The below makes 2 separate constraints that basically state that during one (and only one) of the time periods there must be 1 sale. Same for buy.

If you are just getting going, refer to the dox for examples, and after each thing you add to your model, pprint() the model as I've shown below and check the math.

Use tiny data sets (like 3 time periods as I show) to start to ensure it is working.

Code:

import pyomo.environ as pyo

m = pyo.ConcreteModel()

m.T    = pyo.Set(initialize=range(3), doc='times')

m.buy  = pyo.Var(m.T, domain=pyo.Binary)
m.sell = pyo.Var(m.T, domain=pyo.Binary)

m.C1 = pyo.Constraint(expr=sum( m.buy[t] for t in m.T) == 1, doc='must buy')
m.C2 = pyo.Constraint(expr=sum(m.sell[t] for t in m.T) == 1, doc='must sell')

m.pprint()

Output:

1 Set Declarations
    T : times
        Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    3 : {0, 1, 2}

2 Var Declarations
    buy : Size=3, Index=T
        Key : Lower : Value : Upper : Fixed : Stale : Domain
          0 :     0 :  None :     1 : False :  True : Binary
          1 :     0 :  None :     1 : False :  True : Binary
          2 :     0 :  None :     1 : False :  True : Binary
    sell : Size=3, Index=T
        Key : Lower : Value : Upper : Fixed : Stale : Domain
          0 :     0 :  None :     1 : False :  True : Binary
          1 :     0 :  None :     1 : False :  True : Binary
          2 :     0 :  None :     1 : False :  True : Binary

2 Constraint Declarations
    C1 : must buy
        Size=1, Index=None, Active=True
        Key  : Lower : Body                     : Upper : Active
        None :   1.0 : buy[0] + buy[1] + buy[2] :   1.0 :   True
    C2 : must sell
        Size=1, Index=None, Active=True
        Key  : Lower : Body                        : Upper : Active
        None :   1.0 : sell[0] + sell[1] + sell[2] :   1.0 :   True

5 Declarations: T buy sell C1 C2
AirSquid
  • 10,214
  • 2
  • 7
  • 31