0

Does anyone know what is a good way to indicate whether a model variable is bounded between certain values? For example, indicator1 = 1 when 0<= variable x <=200 else 0, indicator2 = 1 when 200<= variable x <= 300.

One use case of this is to calculate weight dependent shipping cost, e.g. if the shipment weighs less than 200 lbs then it costs $z/lb; if the shipment weighs more than 200lb and less than 300 lbs then it costs $y/lb.

Minimize W1*z + W2*y

Weight = W1 + W2

0 <= W1 <= 200*X1

200*X2 <= W2 <= 300*X2

X1+ X2 = 1

X1, X2 binary

Weight, W1, W2 >= 0

Above is the formulation I came up with for this situation. However, now I have more than 200 buckets of values to check, so this formulation does not seem efficient enough. I am wondering whether there are better ways to model this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

1 Answers1

0

This problem can also be modeled as a Generalized Disjunctive Program (GDP). It's more verbose, but more descriptive.

from pyomo.environ import *
from pyomo.gdp import *
m = ConcreteModel()
m.total_weight_cost = Var(domain=NonNegativeReals)
m.weight = Var(domain=NonNegativeReals)
m.weight_buckets = RangeSet(2)
m.weight_bucket_lb = Param(m.weight_buckets, initialize={1: 0, 2: 200})
m.weight_bucket_ub = Param(m.weight_buckets, initialize={1: 200, 2: 300})
m.weight_bucket_cost = Param(m.weight_buckets, initialize={1: z, 2: y})
m.weight_bucket_disjunction = Disjunction(expr=[
    [m.total_weight_cost == m.weight_bucket_cost[bucket] * m.weight,
     m.weight_bucket_lb[bucket] <= m.weight,
     m.weight <= m.weight_bucket_ub[bucket]
    for bucket in m.weight_buckets]
])
TransformationFactory('gdp.bigm').apply_to(m)
SolverFactory('gurobi').solve(m, tee=True)
m.display()
Qi Chen
  • 1,648
  • 1
  • 10
  • 19