Add more constraint features

master
Alinson S. Xavier 5 years ago
parent b5e602cdc1
commit 5e1f26e4b0
No known key found for this signature in database
GPG Key ID: DCA0DAD4D2F58624

@ -4,8 +4,6 @@
import logging
import re
import sys
from dataclasses import dataclass
from enum import Enum
from io import StringIO
from random import randint
from typing import List, Any, Dict, Optional, Hashable
@ -444,6 +442,14 @@ class GurobiSolver(InternalSolver):
)
if self._has_lp_solution:
constr.dual_value = gp_constr.pi
constr.sa_rhs_up = gp_constr.sarhsup
constr.sa_rhs_low = gp_constr.sarhslow
if gp_constr.cbasis == 0:
constr.basis_status = "b"
elif gp_constr.cbasis == -1:
constr.basis_status = "n"
else:
raise Exception(f"unknown cbasis: {gp_constr.cbasis}")
if self._has_lp_solution or self._has_mip_solution:
constr.slack = gp_constr.slack
return constr
@ -452,6 +458,22 @@ class GurobiSolver(InternalSolver):
def are_callbacks_supported(self) -> bool:
return True
@overrides
def get_constraint_attrs(self) -> List[str]:
return [
"basis_status",
"category",
"dual_value",
"lazy",
"lhs",
"rhs",
"sa_rhs_down",
"sa_rhs_up",
"sense",
"slack",
"user_features",
]
class GurobiTestInstanceInfeasible(Instance):
@overrides

@ -246,3 +246,10 @@ class InternalSolver(ABC, EnforceOverrides):
callback or user cuts callback.
"""
return False
@abstractmethod
def get_constraint_attrs(self) -> List[str]:
"""
Returns a list of constraint attributes supported by this solver.
"""
pass

@ -435,6 +435,19 @@ class BasePyomoSolver(InternalSolver):
def are_callbacks_supported(self) -> bool:
return False
@overrides
def get_constraint_attrs(self) -> List[str]:
return [
"category",
"dual_value",
"lazy",
"lhs",
"rhs",
"sense",
"slack",
"user_features",
]
class PyomoTestInstanceInfeasible(Instance):
@overrides

@ -2,7 +2,7 @@
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
from typing import Any
from typing import Any, Dict
from miplearn.features import Constraint
from miplearn.solvers.internal import InternalSolver
@ -12,7 +12,7 @@ from miplearn.solvers.internal import InternalSolver
# This file is in the main source folder, so that it can be called from Julia.
def _round_constraints(constraints):
def _round_constraints(constraints: Dict[str, Constraint]) -> Dict[str, Constraint]:
for (cname, c) in constraints.items():
for attr in ["slack", "dual_value"]:
if getattr(c, attr) is not None:
@ -20,6 +20,20 @@ def _round_constraints(constraints):
return constraints
def _remove_unsupported_constr_attrs(
solver: InternalSolver,
constraints: Dict[str, Constraint],
):
for (cname, c) in constraints.items():
to_remove = []
for k in c.__dict__.keys():
if k not in solver.get_constraint_attrs():
to_remove.append(k)
for k in to_remove:
setattr(c, k, None)
return constraints
def run_internal_solver_tests(solver: InternalSolver) -> None:
run_basic_usage_tests(solver.clone())
run_warm_start_tests(solver.clone())
@ -76,16 +90,22 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
# Fetch constraints (after-lp)
assert_equals(
_round_constraints(solver.get_constraints()),
{
"eq_capacity": Constraint(
lazy=False,
lhs={"x[0]": 23.0, "x[1]": 26.0, "x[2]": 20.0, "x[3]": 18.0},
rhs=67.0,
sense="<",
slack=0.0,
dual_value=13.538462,
)
},
_remove_unsupported_constr_attrs(
solver,
{
"eq_capacity": Constraint(
lazy=False,
lhs={"x[0]": 23.0, "x[1]": 26.0, "x[2]": 20.0, "x[3]": 18.0},
rhs=67.0,
sense="<",
slack=0.0,
dual_value=13.538462,
sa_rhs_down=None,
sa_rhs_up=69.0,
basis_status="n",
)
},
),
)
# Solve MIP

Loading…
Cancel
Save