# ____________________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2026 National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and Engineering
# Solutions of Sandia, LLC, the U.S. Government retains certain rights in this
# software. This software is distributed under the 3-clause BSD License.
# ____________________________________________________________________________________
"""Provides functions for retrieving disjunctive variable bound information stored on a model."""
from pyomo.common.collections import ComponentMap
from pyomo.core import value
inf = float('inf')
[docs]
def disjunctive_bounds(scope):
"""Return all of the variable bounds defined at a disjunctive scope."""
possible_disjunct = scope
while possible_disjunct is not None:
try:
return possible_disjunct._disj_var_bounds
except AttributeError:
# possible disjunct does not have attribute '_disj_var_bounds'.
# Try again with the scope's parent block.
possible_disjunct = possible_disjunct.parent_block()
# Unable to find '_disj_var_bounds' attribute within search scope.
return ComponentMap()
[docs]
def disjunctive_bound(var, scope):
"""Compute the disjunctive bounds for a variable in a given scope.
Args:
var (VarData): Variable for which to compute bound
scope (Component): The scope in which to compute the bound. If not a
DisjunctData, it will walk up the tree and use the scope of the
most immediate enclosing DisjunctData.
Returns:
numeric: the tighter of either the disjunctive lower bound, the
variable lower bound, or (-inf, inf) if neither exist.
"""
# Initialize to the global variable bound
var_bnd = (
value(var.lb) if var.has_lb() else -inf,
value(var.ub) if var.has_ub() else inf,
)
possible_disjunct = scope
while possible_disjunct is not None:
try:
disj_bnd = possible_disjunct._disj_var_bounds.get(var, (-inf, inf))
disj_bnd = (max(var_bnd[0], disj_bnd[0]), min(var_bnd[1], disj_bnd[1]))
return disj_bnd
except AttributeError:
# possible disjunct does not have attribute '_disj_var_bounds'.
# Try again with the scope's parent block.
possible_disjunct = possible_disjunct.parent_block()
# Unable to find '_disj_var_bounds' attribute within search scope.
return var_bnd
[docs]
def disjunctive_lb(var, scope):
"""Compute the disjunctive lower bound for a variable in a given scope."""
return disjunctive_bound(var, scope)[0]
[docs]
def disjunctive_ub(var, scope):
"""Compute the disjunctive upper bound for a variable in a given scope."""
return disjunctive_bound(var, scope)[1]