Create ConstraintFeatures

This commit is contained in:
2021-04-15 11:49:58 -05:00
parent 0e9c8b0a49
commit 230d13a5c0
5 changed files with 167 additions and 42 deletions

View File

@@ -19,7 +19,7 @@ from pyomo.core.expr.numeric_expr import SumExpression, MonomialTermExpression
from pyomo.opt import TerminationCondition
from pyomo.opt.base.solvers import SolverFactory
from miplearn.features import VariableFeatures
from miplearn.features import VariableFeatures, ConstraintFeatures
from miplearn.instance.base import Instance
from miplearn.solvers import _RedirectOutput
from miplearn.solvers.internal import (
@@ -128,7 +128,77 @@ class BasePyomoSolver(InternalSolver):
self._pyomo_solver.update_var(var)
@overrides
def get_constraints(self, with_static: bool = True) -> Dict[str, Constraint]:
def get_constraints(self, with_static: bool = True) -> ConstraintFeatures:
assert self.model is not None
names: List[str] = []
rhs: List[float] = []
lhs: List[Tuple[Tuple[str, float], ...]] = []
senses: List[str] = []
def _parse_constraint(c: pe.Constraint) -> None:
if with_static:
# Extract RHS and sense
has_ub = c.has_ub()
has_lb = c.has_lb()
assert (
(not has_lb) or (not has_ub) or c.upper() == c.lower()
), "range constraints not supported"
if not has_ub:
senses.append(">")
rhs.append(float(c.lower()))
elif not has_lb:
senses.append("<")
rhs.append(float(c.upper()))
else:
senses.append("=")
rhs.append(float(c.upper()))
# Extract LHS
lhsc = []
expr = c.body
if isinstance(expr, SumExpression):
for term in expr._args_:
if isinstance(term, MonomialTermExpression):
lhsc.append((term._args_[1].name, float(term._args_[0])))
elif isinstance(term, _GeneralVarData):
lhsc.append((term.name, 1.0))
else:
raise Exception(
f"Unknown term type: {term.__class__.__name__}"
)
elif isinstance(expr, _GeneralVarData):
lhsc.append((expr.name, 1.0))
else:
raise Exception(
f"Unknown expression type: {expr.__class__.__name__}"
)
lhs.append(tuple(lhsc))
for constr in self.model.component_objects(pyomo.core.Constraint):
if isinstance(constr, pe.ConstraintList):
for idx in constr:
names.append(f"{constr.name}[{idx}]")
_parse_constraint(constr[idx])
else:
names.append(constr.name)
_parse_constraint(constr)
rhs_t, lhs_t, senses_t = None, None, None
if with_static:
rhs_t = tuple(rhs)
lhs_t = tuple(lhs)
senses_t = tuple(senses)
return ConstraintFeatures(
names=tuple(names),
rhs=rhs_t,
senses=senses_t,
lhs=lhs_t,
)
@overrides
def get_constraints_old(self, with_static: bool = True) -> Dict[str, Constraint]:
assert self.model is not None
constraints = {}
@@ -267,20 +337,6 @@ class BasePyomoSolver(InternalSolver):
@overrides
def get_variable_attrs(self) -> List[str]:
return [
# "basis_status",
"lower_bound",
"obj_coeff",
"reduced_cost",
# "sa_lb_down",
# "sa_lb_up",
# "sa_obj_down",
# "sa_obj_up",
# "sa_ub_down",
# "sa_ub_up",
"type",
"upper_bound",
"value",
# new attributes
"names",
# "basis_status",
"categories",