The Pyomo optimization modeling framework for formulating, analyzing, and solving mathematical optimization problems
—
Components for modeling logical relationships and disjunctive constraints in optimization problems. GDP enables the formulation of problems with logical decision-making and alternative process paths through disjuncts and disjunctions.
Components for defining disjunctive blocks containing variables, constraints, and logical relationships.
class Disjunct:
"""
Disjunct component for GDP modeling.
A disjunct represents a logical block that is either active or inactive.
When active, all constraints within the disjunct must be satisfied.
"""
def __init__(self, *args, **kwargs): ...
def activate(self):
"""Activate this disjunct."""
def deactivate(self):
"""Deactivate this disjunct."""
def is_active(self):
"""Check if disjunct is active."""
@property
def indicator_var(self):
"""Get the binary indicator variable for this disjunct."""
class DisjunctData:
"""
Data container for disjunct components.
Stores the actual constraint and variable data associated with
a specific disjunct instance.
"""
def __init__(self, component=None): ...
def activate(self): ...
def deactivate(self): ...
def is_active(self): ...Components for defining logical disjunctions (OR relationships) between disjuncts.
class Disjunction:
"""
Disjunction component representing logical OR relationships.
A disjunction requires that exactly one of its constituent
disjuncts must be active (true).
"""
def __init__(self, *args, **kwargs): ...
def activate(self):
"""Activate this disjunction."""
def deactivate(self):
"""Deactivate this disjunction."""
def is_active(self):
"""Check if disjunction is active."""
class DisjunctionData:
"""
Data container for disjunction components.
Stores the disjunct references and logical relationships
for a specific disjunction instance.
"""
def __init__(self, component=None): ...
def activate(self): ...
def deactivate(self): ...
def is_active(self): ...Exception class for GDP-specific errors and validation issues.
class GDP_Error(Exception):
"""GDP-specific error class for logical modeling issues."""
def __init__(self, message): ...from pyomo.environ import *
from pyomo.gdp import Disjunct, Disjunction
model = ConcreteModel()
# Decision variables
model.x = Var(bounds=(0, 10))
model.y = Var(bounds=(0, 10))
# Create disjuncts for alternative process paths
model.path1 = Disjunct()
model.path2 = Disjunct()
# Path 1: High-temperature, low-pressure process
model.path1.temp_constraint = Constraint(expr=model.x >= 8)
model.path1.pressure_constraint = Constraint(expr=model.y <= 3)
model.path1.cost = Var(bounds=(0, 100))
model.path1.cost_def = Constraint(expr=model.path1.cost == 2*model.x + model.y)
# Path 2: Low-temperature, high-pressure process
model.path2.temp_constraint = Constraint(expr=model.x <= 5)
model.path2.pressure_constraint = Constraint(expr=model.y >= 6)
model.path2.cost = Var(bounds=(0, 100))
model.path2.cost_def = Constraint(expr=model.path2.cost == model.x + 3*model.y)
# Disjunction: exactly one path must be chosen
model.path_choice = Disjunction(expr=[model.path1, model.path2])
# Objective: minimize total cost
model.obj = Objective(
expr=model.path1.cost + model.path2.cost,
sense=minimize
)from pyomo.environ import *
from pyomo.gdp import Disjunct, Disjunction
model = ConcreteModel()
# Sets for indexing
model.UNITS = Set(initialize=[1, 2, 3])
model.MODES = Set(initialize=['low', 'med', 'high'])
# Variables
model.flow = Var(model.UNITS, bounds=(0, 100))
model.operating = Var(model.UNITS, domain=Binary)
# Indexed disjuncts for operating modes
model.mode_disjunct = Disjunct(model.UNITS, model.MODES)
# Define constraints for each mode
for unit in model.UNITS:
# Low mode: 0-30% capacity
model.mode_disjunct[unit, 'low'].flow_lower = Constraint(
expr=model.flow[unit] >= 0
)
model.mode_disjunct[unit, 'low'].flow_upper = Constraint(
expr=model.flow[unit] <= 30
)
# Medium mode: 30-70% capacity
model.mode_disjunct[unit, 'med'].flow_lower = Constraint(
expr=model.flow[unit] >= 30
)
model.mode_disjunct[unit, 'med'].flow_upper = Constraint(
expr=model.flow[unit] <= 70
)
# High mode: 70-100% capacity
model.mode_disjunct[unit, 'high'].flow_lower = Constraint(
expr=model.flow[unit] >= 70
)
model.mode_disjunct[unit, 'high'].flow_upper = Constraint(
expr=model.flow[unit] <= 100
)
# Each unit must operate in exactly one mode
def mode_disjunction_rule(model, unit):
return [model.mode_disjunct[unit, mode] for mode in model.MODES]
model.mode_choice = Disjunction(model.UNITS, rule=mode_disjunction_rule)from pyomo.environ import *
from pyomo.gdp import Disjunct, Disjunction
model = ConcreteModel()
# Variables
model.x = Var(bounds=(0, 20))
model.y = Var(bounds=(0, 20))
# Top-level choice: Process A or Process B
model.process_A = Disjunct()
model.process_B = Disjunct()
# Within Process A: two sub-options
model.process_A.option_A1 = Disjunct()
model.process_A.option_A2 = Disjunct()
# Process A, Option 1
model.process_A.option_A1.con1 = Constraint(expr=model.x <= 8)
model.process_A.option_A1.con2 = Constraint(expr=model.y >= 5)
# Process A, Option 2
model.process_A.option_A2.con1 = Constraint(expr=model.x >= 12)
model.process_A.option_A2.con2 = Constraint(expr=model.y <= 10)
# Process A must choose one sub-option
model.process_A.sub_choice = Disjunction(
expr=[model.process_A.option_A1, model.process_A.option_A2]
)
# Process B (single option)
model.process_B.con1 = Constraint(expr=model.x + model.y <= 15)
model.process_B.con2 = Constraint(expr=model.x - model.y >= 2)
# Top-level disjunction
model.main_choice = Disjunction(expr=[model.process_A, model.process_B])
# Objective
model.obj = Objective(expr=model.x + model.y, sense=maximize)from pyomo.environ import *
from pyomo.gdp import Disjunct, Disjunction
import pyomo.contrib.gdpopt as gdpopt
# Create GDP model (using previous example)
model = create_gdp_model() # Your GDP model creation function
# Method 1: Use GDP-specific solver
solver = SolverFactory('gdpopt')
results = solver.solve(model, tee=True)
# Method 2: Transform to MILP and solve
from pyomo.gdp import TransformationFactory
# Big-M transformation
bigm = TransformationFactory('gdp.bigm')
bigm.apply_to(model)
# Solve transformed model
milp_solver = SolverFactory('gurobi') # or 'cplex', 'glpk', etc.
results = milp_solver.solve(model, tee=True)
# Method 3: Hull reformulation
model_hull = model.clone()
hull = TransformationFactory('gdp.hull')
hull.apply_to(model_hull)
results = milp_solver.solve(model_hull, tee=True)from pyomo.environ import *
from pyomo.gdp import Disjunct, Disjunction
# After solving GDP model
if results.solver.termination_condition == TerminationCondition.optimal:
print("Solution found!")
# Check which disjuncts are active
for disjunct in [model.path1, model.path2]:
if disjunct.indicator_var.value >= 0.5: # Binary variable ≈ 1
print(f"{disjunct.name} is active")
# Access variables within active disjunct
if hasattr(disjunct, 'cost'):
print(f" Cost: {value(disjunct.cost)}")
# Access main variables
print(f"x = {value(model.x)}")
print(f"y = {value(model.y)}")
print(f"Objective = {value(model.obj)}")from pyomo.environ import *
from pyomo.gdp import Disjunct, Disjunction
model = ConcreteModel()
# Variables
model.x = Var(bounds=(0, 100))
model.setup_cost = Var(bounds=(0, 1000))
model.operating_cost = Var(bounds=(0, 500))
# Disjunct for "facility not built"
model.not_built = Disjunct()
model.not_built.no_production = Constraint(expr=model.x == 0)
model.not_built.no_setup = Constraint(expr=model.setup_cost == 0)
model.not_built.no_operating = Constraint(expr=model.operating_cost == 0)
# Disjunct for "facility built"
model.built = Disjunct()
model.built.min_production = Constraint(expr=model.x >= 20) # Minimum viable scale
model.built.setup_cost_def = Constraint(expr=model.setup_cost == 200)
model.built.operating_cost_def = Constraint(expr=model.operating_cost == 5 * model.x)
# Either build or don't build
model.build_decision = Disjunction(expr=[model.not_built, model.built])
# Objective: maximize profit (revenue - costs)
model.revenue = Expression(expr=10 * model.x)
model.total_cost = Expression(expr=model.setup_cost + model.operating_cost)
model.obj = Objective(expr=model.revenue - model.total_cost, sense=maximize)Install with Tessl CLI
npx tessl i tessl/pypi-pyomo