mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 01:18:52 -06:00
Add more constraint features
This commit is contained in:
@@ -4,8 +4,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from dataclasses import dataclass
|
|
||||||
from enum import Enum
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from random import randint
|
from random import randint
|
||||||
from typing import List, Any, Dict, Optional, Hashable
|
from typing import List, Any, Dict, Optional, Hashable
|
||||||
@@ -444,6 +442,14 @@ class GurobiSolver(InternalSolver):
|
|||||||
)
|
)
|
||||||
if self._has_lp_solution:
|
if self._has_lp_solution:
|
||||||
constr.dual_value = gp_constr.pi
|
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:
|
if self._has_lp_solution or self._has_mip_solution:
|
||||||
constr.slack = gp_constr.slack
|
constr.slack = gp_constr.slack
|
||||||
return constr
|
return constr
|
||||||
@@ -452,6 +458,22 @@ class GurobiSolver(InternalSolver):
|
|||||||
def are_callbacks_supported(self) -> bool:
|
def are_callbacks_supported(self) -> bool:
|
||||||
return True
|
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):
|
class GurobiTestInstanceInfeasible(Instance):
|
||||||
@overrides
|
@overrides
|
||||||
|
|||||||
@@ -246,3 +246,10 @@ class InternalSolver(ABC, EnforceOverrides):
|
|||||||
callback or user cuts callback.
|
callback or user cuts callback.
|
||||||
"""
|
"""
|
||||||
return False
|
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:
|
def are_callbacks_supported(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@overrides
|
||||||
|
def get_constraint_attrs(self) -> List[str]:
|
||||||
|
return [
|
||||||
|
"category",
|
||||||
|
"dual_value",
|
||||||
|
"lazy",
|
||||||
|
"lhs",
|
||||||
|
"rhs",
|
||||||
|
"sense",
|
||||||
|
"slack",
|
||||||
|
"user_features",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class PyomoTestInstanceInfeasible(Instance):
|
class PyomoTestInstanceInfeasible(Instance):
|
||||||
@overrides
|
@overrides
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
|
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
|
||||||
# Released under the modified BSD license. See COPYING.md for more details.
|
# 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.features import Constraint
|
||||||
from miplearn.solvers.internal import InternalSolver
|
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.
|
# 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 (cname, c) in constraints.items():
|
||||||
for attr in ["slack", "dual_value"]:
|
for attr in ["slack", "dual_value"]:
|
||||||
if getattr(c, attr) is not None:
|
if getattr(c, attr) is not None:
|
||||||
@@ -20,6 +20,20 @@ def _round_constraints(constraints):
|
|||||||
return 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:
|
def run_internal_solver_tests(solver: InternalSolver) -> None:
|
||||||
run_basic_usage_tests(solver.clone())
|
run_basic_usage_tests(solver.clone())
|
||||||
run_warm_start_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)
|
# Fetch constraints (after-lp)
|
||||||
assert_equals(
|
assert_equals(
|
||||||
_round_constraints(solver.get_constraints()),
|
_round_constraints(solver.get_constraints()),
|
||||||
{
|
_remove_unsupported_constr_attrs(
|
||||||
"eq_capacity": Constraint(
|
solver,
|
||||||
lazy=False,
|
{
|
||||||
lhs={"x[0]": 23.0, "x[1]": 26.0, "x[2]": 20.0, "x[3]": 18.0},
|
"eq_capacity": Constraint(
|
||||||
rhs=67.0,
|
lazy=False,
|
||||||
sense="<",
|
lhs={"x[0]": 23.0, "x[1]": 26.0, "x[2]": 20.0, "x[3]": 18.0},
|
||||||
slack=0.0,
|
rhs=67.0,
|
||||||
dual_value=13.538462,
|
sense="<",
|
||||||
)
|
slack=0.0,
|
||||||
},
|
dual_value=13.538462,
|
||||||
|
sa_rhs_down=None,
|
||||||
|
sa_rhs_up=69.0,
|
||||||
|
basis_status="n",
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Solve MIP
|
# Solve MIP
|
||||||
|
|||||||
Reference in New Issue
Block a user