Search code examples
optimizationconstraintspyomo

How to set up simple two domain constraint on a variable in Pyomo?


I am working on a supply chain optimisation problem using Pyomo and I need to set up a constraint on specific variables in the model. The constraint is that the variable should be within the set (0,1) or (200, to infinity). However, when I try to set up that constraint I am getting a TypeError, here is my code:

def rail_rule(model):
        for route in routes:
            if "rail" in route[0].lower():
                dest = route[0]
                dg = route[1]
                sg = route[2]
                site = route[3]
                return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1

model.railconst = Constraint(rule = rail_rule)

I get this error when I run it :

TypeError: Relational expression used in an unexpected Boolean context.

        The inequality expression:
            200.0  <=  x[RAIL - KENSINGTON,8,8,BROCKLESBY]
        contains non-constant terms (variables) that were evaluated in an
        unexpected Boolean context at
          File '<ipython-input-168-901363ebc86f>', line 8:
    return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1

        Evaluating Pyomo variables in a Boolean context, e.g.
            if expression <= 5:
        is generally invalid.  If you want to obtain the Boolean value of the
        expression based on the current variable values, explicitly evaluate the
        expression using the value() function:
            if value(expression) <= 5:
        or
            if value(expression <= 5):

So my understanding is that I cant give Pyomo a boolean expression as a constraint, but I am quite new to Pyomo and not too sure if that's what my issue is or if I am doing it correctly.

This constraint could also be implemented in the variable intialisation as boundaries, but I cant find a way to set up two boundaries on a single variable in Pyomo.

Thanks !


Solution

  • There are different ways to handle this:

    (1) Use binary variables. Assume you have a good upper bound on x, i.e., x ∈ [0, U]. Then formulate the constraints

      x ≤ 1 + (U-1) δ
      x ≥ 200 δ
      δ ∈ {0,1}  (binary variable)
    

    This is the easiest way.

    (2) If you don't have a good upper bound on x, you can use a SOS1 set. (SOS1 means Special Ordered Set of type 1). Assume x,s1,s2 ≥ 0.

      x ≤ 1 + s1
      x ≥ 200 - s2
      s1,s2 ∈ SOS1   (s1,s2 form a SOS1 set)
    

    (3) Use disjunctive programming.