Use np.array for Variables.names

master
Alinson S. Xavier 4 years ago
parent f69067aafd
commit 7d55d6f34c
No known key found for this signature in database
GPG Key ID: DCA0DAD4D2F58624

@ -2,7 +2,7 @@ PYTHON := python3
PYTEST := pytest PYTEST := pytest
PIP := $(PYTHON) -m pip PIP := $(PYTHON) -m pip
MYPY := $(PYTHON) -m mypy MYPY := $(PYTHON) -m mypy
PYTEST_ARGS := -W ignore::DeprecationWarning -vv -x --log-level=DEBUG PYTEST_ARGS := -W ignore::DeprecationWarning -vv --log-level=DEBUG
VERSION := 0.2 VERSION := 0.2
all: docs test all: docs test

@ -95,7 +95,7 @@ class PrimalSolutionComponent(Component):
) )
def sample_predict(self, sample: Sample) -> Solution: def sample_predict(self, sample: Sample) -> Solution:
var_names = sample.get_vector("static_var_names") var_names = sample.get_array("static_var_names")
var_categories = sample.get_vector("static_var_categories") var_categories = sample.get_vector("static_var_categories")
assert var_names is not None assert var_names is not None
assert var_categories is not None assert var_categories is not None
@ -145,7 +145,7 @@ class PrimalSolutionComponent(Component):
instance_features = sample.get_vector("static_instance_features") instance_features = sample.get_vector("static_instance_features")
mip_var_values = sample.get_vector("mip_var_values") mip_var_values = sample.get_vector("mip_var_values")
var_features = sample.get_vector_list("lp_var_features") var_features = sample.get_vector_list("lp_var_features")
var_names = sample.get_vector("static_var_names") var_names = sample.get_array("static_var_names")
var_categories = sample.get_vector("static_var_categories") var_categories = sample.get_vector("static_var_categories")
if var_features is None: if var_features is None:
var_features = sample.get_vector_list("static_var_features") var_features = sample.get_vector_list("static_var_features")
@ -187,8 +187,8 @@ class PrimalSolutionComponent(Component):
_: Optional[Instance], _: Optional[Instance],
sample: Sample, sample: Sample,
) -> Dict[str, Dict[str, float]]: ) -> Dict[str, Dict[str, float]]:
mip_var_values = sample.get_vector("mip_var_values") mip_var_values = sample.get_array("mip_var_values")
var_names = sample.get_vector("static_var_names") var_names = sample.get_array("static_var_names")
assert mip_var_values is not None assert mip_var_values is not None
assert var_names is not None assert var_names is not None

@ -5,7 +5,7 @@
import collections import collections
import numbers import numbers
from math import log, isfinite from math import log, isfinite
from typing import TYPE_CHECKING, Dict, Optional, List, Any, Tuple from typing import TYPE_CHECKING, Dict, Optional, List, Any, Tuple, KeysView, cast
import numpy as np import numpy as np
@ -34,7 +34,7 @@ class FeaturesExtractor:
variables = solver.get_variables(with_static=True) variables = solver.get_variables(with_static=True)
constraints = solver.get_constraints(with_static=True, with_lhs=self.with_lhs) constraints = solver.get_constraints(with_static=True, with_lhs=self.with_lhs)
sample.put_array("static_var_lower_bounds", variables.lower_bounds) sample.put_array("static_var_lower_bounds", variables.lower_bounds)
sample.put_vector("static_var_names", variables.names) sample.put_array("static_var_names", variables.names)
sample.put_array("static_var_obj_coeffs", variables.obj_coeffs) sample.put_array("static_var_obj_coeffs", variables.obj_coeffs)
sample.put_vector("static_var_types", variables.types) sample.put_vector("static_var_types", variables.types)
sample.put_array("static_var_upper_bounds", variables.upper_bounds) sample.put_array("static_var_upper_bounds", variables.upper_bounds)
@ -139,12 +139,29 @@ class FeaturesExtractor:
instance: "Instance", instance: "Instance",
sample: Sample, sample: Sample,
) -> Tuple[List, List]: ) -> Tuple[List, List]:
categories: List[Optional[str]] = [] # Query variable names
user_features: List[Optional[List[float]]] = [] var_names = sample.get_array("static_var_names")
var_features_dict = instance.get_variable_features()
var_categories_dict = instance.get_variable_categories()
var_names = sample.get_vector("static_var_names")
assert var_names is not None assert var_names is not None
# Query variable features and categories
var_features_dict = {
v.encode(): f for (v, f) in instance.get_variable_features().items()
}
var_categories_dict = {
v.encode(): f for (v, f) in instance.get_variable_categories().items()
}
# Assert that variables in user-provided dicts actually exist
var_names_set = set(var_names)
for keys in [var_features_dict.keys(), var_categories_dict.keys()]:
for vn in cast(KeysView, keys):
assert (
vn in var_names_set
), f"Variable {vn!r} not found in the problem; {var_names_set}"
# Assemble into compact lists
user_features: List[Optional[List[float]]] = []
categories: List[Optional[str]] = []
for (i, var_name) in enumerate(var_names): for (i, var_name) in enumerate(var_names):
if var_name not in var_categories_dict: if var_name not in var_categories_dict:
user_features.append(None) user_features.append(None)

@ -73,11 +73,11 @@ class GurobiSolver(InternalSolver):
self._has_lp_solution = False self._has_lp_solution = False
self._has_mip_solution = False self._has_mip_solution = False
self._varname_to_var: Dict[str, "gurobipy.Var"] = {} self._varname_to_var: Dict[bytes, "gurobipy.Var"] = {}
self._cname_to_constr: Dict[str, "gurobipy.Constr"] = {} self._cname_to_constr: Dict[str, "gurobipy.Constr"] = {}
self._gp_vars: List["gurobipy.Var"] = [] self._gp_vars: List["gurobipy.Var"] = []
self._gp_constrs: List["gurobipy.Constr"] = [] self._gp_constrs: List["gurobipy.Constr"] = []
self._var_names: List[str] = [] self._var_names: np.ndarray = np.empty(0)
self._constr_names: List[str] = [] self._constr_names: List[str] = []
self._var_types: List[str] = [] self._var_types: List[str] = []
self._var_lbs: np.ndarray = np.empty(0) self._var_lbs: np.ndarray = np.empty(0)
@ -263,11 +263,13 @@ class GurobiSolver(InternalSolver):
if self.cb_where is not None: if self.cb_where is not None:
if self.cb_where == self.gp.GRB.Callback.MIPNODE: if self.cb_where == self.gp.GRB.Callback.MIPNODE:
return { return {
v.varName: self.model.cbGetNodeRel(v) for v in self.model.getVars() v.varName.encode(): self.model.cbGetNodeRel(v)
for v in self.model.getVars()
} }
elif self.cb_where == self.gp.GRB.Callback.MIPSOL: elif self.cb_where == self.gp.GRB.Callback.MIPSOL:
return { return {
v.varName: self.model.cbGetSolution(v) for v in self.model.getVars() v.varName.encode(): self.model.cbGetSolution(v)
for v in self.model.getVars()
} }
else: else:
raise Exception( raise Exception(
@ -276,7 +278,7 @@ class GurobiSolver(InternalSolver):
) )
if self.model.solCount == 0: if self.model.solCount == 0:
return None return None
return {v.varName: v.x for v in self.model.getVars()} return {v.varName.encode(): v.x for v in self.model.getVars()}
@overrides @overrides
def get_variable_attrs(self) -> List[str]: def get_variable_attrs(self) -> List[str]:
@ -584,7 +586,10 @@ class GurobiSolver(InternalSolver):
assert self.model is not None assert self.model is not None
gp_vars: List["gurobipy.Var"] = self.model.getVars() gp_vars: List["gurobipy.Var"] = self.model.getVars()
gp_constrs: List["gurobipy.Constr"] = self.model.getConstrs() gp_constrs: List["gurobipy.Constr"] = self.model.getConstrs()
var_names: List[str] = self.model.getAttr("varName", gp_vars) var_names: np.ndarray = np.array(
self.model.getAttr("varName", gp_vars),
dtype="S",
)
var_types: List[str] = self.model.getAttr("vtype", gp_vars) var_types: List[str] = self.model.getAttr("vtype", gp_vars)
var_ubs: np.ndarray = np.array( var_ubs: np.ndarray = np.array(
self.model.getAttr("ub", gp_vars), self.model.getAttr("ub", gp_vars),
@ -599,7 +604,7 @@ class GurobiSolver(InternalSolver):
dtype=float, dtype=float,
) )
constr_names: List[str] = self.model.getAttr("constrName", gp_constrs) constr_names: List[str] = self.model.getAttr("constrName", gp_constrs)
varname_to_var: Dict = {} varname_to_var: Dict[bytes, "gurobipy.Var"] = {}
cname_to_constr: Dict = {} cname_to_constr: Dict = {}
for (i, gp_var) in enumerate(gp_vars): for (i, gp_var) in enumerate(gp_vars):
assert var_names[i] not in varname_to_var, ( assert var_names[i] not in varname_to_var, (

@ -50,7 +50,7 @@ class MIPSolveStats:
@dataclass @dataclass
class Variables: class Variables:
names: Optional[List[str]] = None names: Optional[np.ndarray] = None
basis_status: Optional[List[str]] = None basis_status: Optional[List[str]] = None
lower_bounds: Optional[np.ndarray] = None lower_bounds: Optional[np.ndarray] = None
obj_coeffs: Optional[np.ndarray] = None obj_coeffs: Optional[np.ndarray] = None
@ -71,7 +71,7 @@ class Constraints:
basis_status: Optional[List[str]] = None basis_status: Optional[List[str]] = None
dual_values: Optional[np.ndarray] = None dual_values: Optional[np.ndarray] = None
lazy: Optional[List[bool]] = None lazy: Optional[List[bool]] = None
lhs: Optional[List[List[Tuple[str, float]]]] = None lhs: Optional[List[List[Tuple[bytes, float]]]] = None
names: Optional[List[str]] = None names: Optional[List[str]] = None
rhs: Optional[np.ndarray] = None rhs: Optional[np.ndarray] = None
sa_rhs_down: Optional[np.ndarray] = None sa_rhs_down: Optional[np.ndarray] = None

@ -34,8 +34,6 @@ from miplearn.types import (
SolverParams, SolverParams,
UserCutCallback, UserCutCallback,
Solution, Solution,
VariableName,
Category,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -59,7 +57,7 @@ class BasePyomoSolver(InternalSolver):
self._is_warm_start_available: bool = False self._is_warm_start_available: bool = False
self._pyomo_solver: SolverFactory = solver_factory self._pyomo_solver: SolverFactory = solver_factory
self._obj_sense: str = "min" self._obj_sense: str = "min"
self._varname_to_var: Dict[str, pe.Var] = {} self._varname_to_var: Dict[bytes, pe.Var] = {}
self._cname_to_constr: Dict[str, pe.Constraint] = {} self._cname_to_constr: Dict[str, pe.Constraint] = {}
self._termination_condition: str = "" self._termination_condition: str = ""
self._has_lp_solution = False self._has_lp_solution = False
@ -166,7 +164,7 @@ class BasePyomoSolver(InternalSolver):
names: List[str] = [] names: List[str] = []
rhs: List[float] = [] rhs: List[float] = []
lhs: List[List[Tuple[str, float]]] = [] lhs: List[List[Tuple[bytes, float]]] = []
senses: List[str] = [] senses: List[str] = []
dual_values: List[float] = [] dual_values: List[float] = []
slacks: List[float] = [] slacks: List[float] = []
@ -199,18 +197,18 @@ class BasePyomoSolver(InternalSolver):
if isinstance(term, MonomialTermExpression): if isinstance(term, MonomialTermExpression):
lhsc.append( lhsc.append(
( (
term._args_[1].name, term._args_[1].name.encode(),
float(term._args_[0]), float(term._args_[0]),
) )
) )
elif isinstance(term, _GeneralVarData): elif isinstance(term, _GeneralVarData):
lhsc.append((term.name, 1.0)) lhsc.append((term.name.encode(), 1.0))
else: else:
raise Exception( raise Exception(
f"Unknown term type: {term.__class__.__name__}" f"Unknown term type: {term.__class__.__name__}"
) )
elif isinstance(expr, _GeneralVarData): elif isinstance(expr, _GeneralVarData):
lhsc.append((expr.name, 1.0)) lhsc.append((expr.name.encode(), 1.0))
else: else:
raise Exception( raise Exception(
f"Unknown expression type: {expr.__class__.__name__}" f"Unknown expression type: {expr.__class__.__name__}"
@ -264,7 +262,7 @@ class BasePyomoSolver(InternalSolver):
for index in var: for index in var:
if var[index].fixed: if var[index].fixed:
continue continue
solution[f"{var}[{index}]"] = var[index].value solution[f"{var}[{index}]".encode()] = var[index].value
return solution return solution
@overrides @overrides
@ -328,7 +326,7 @@ class BasePyomoSolver(InternalSolver):
values.append(v.value) values.append(v.value)
return Variables( return Variables(
names=_none_if_empty(names), names=_none_if_empty(np.array(names, dtype="S")),
types=_none_if_empty(types), types=_none_if_empty(types),
upper_bounds=_none_if_empty(np.array(upper_bounds, dtype=float)), upper_bounds=_none_if_empty(np.array(upper_bounds, dtype=float)),
lower_bounds=_none_if_empty(np.array(lower_bounds, dtype=float)), lower_bounds=_none_if_empty(np.array(lower_bounds, dtype=float)),
@ -558,9 +556,9 @@ class BasePyomoSolver(InternalSolver):
self._varname_to_var = {} self._varname_to_var = {}
for var in self.model.component_objects(Var): for var in self.model.component_objects(Var):
for idx in var: for idx in var:
varname = f"{var.name}[{idx}]" varname = f"{var.name}[{idx}]".encode()
if idx is None: if idx is None:
varname = var.name varname = var.name.encode()
self._varname_to_var[varname] = var[idx] self._varname_to_var[varname] = var[idx]
self._all_vars += [var[idx]] self._all_vars += [var[idx]]
if var[idx].domain == pyomo.core.base.set_types.Binary: if var[idx].domain == pyomo.core.base.set_types.Binary:

@ -10,6 +10,7 @@ from miplearn.solvers.internal import InternalSolver, Variables, Constraints
inf = float("inf") inf = float("inf")
# NOTE: # NOTE:
# 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.
@ -40,7 +41,7 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
assert_equals( assert_equals(
solver.get_variables(), solver.get_variables(),
Variables( Variables(
names=["x[0]", "x[1]", "x[2]", "x[3]", "z"], names=np.array(["x[0]", "x[1]", "x[2]", "x[3]", "z"], dtype="S"),
lower_bounds=np.array([0.0, 0.0, 0.0, 0.0, 0.0]), lower_bounds=np.array([0.0, 0.0, 0.0, 0.0, 0.0]),
upper_bounds=np.array([1.0, 1.0, 1.0, 1.0, 67.0]), upper_bounds=np.array([1.0, 1.0, 1.0, 1.0, 67.0]),
types=["B", "B", "B", "B", "C"], types=["B", "B", "B", "B", "C"],
@ -56,11 +57,11 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
rhs=np.array([0.0]), rhs=np.array([0.0]),
lhs=[ lhs=[
[ [
("x[0]", 23.0), (b"x[0]", 23.0),
("x[1]", 26.0), (b"x[1]", 26.0),
("x[2]", 20.0), (b"x[2]", 20.0),
("x[3]", 18.0), (b"x[3]", 18.0),
("z", -1.0), (b"z", -1.0),
], ],
], ],
senses=["="], senses=["="],
@ -83,7 +84,7 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
_filter_attrs( _filter_attrs(
solver.get_variable_attrs(), solver.get_variable_attrs(),
Variables( Variables(
names=["x[0]", "x[1]", "x[2]", "x[3]", "z"], names=np.array(["x[0]", "x[1]", "x[2]", "x[3]", "z"], dtype="S"),
basis_status=["U", "B", "U", "L", "U"], basis_status=["U", "B", "U", "L", "U"],
reduced_costs=np.array( reduced_costs=np.array(
[193.615385, 0.0, 187.230769, -23.692308, 13.538462] [193.615385, 0.0, 187.230769, -23.692308, 13.538462]
@ -140,7 +141,7 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
_filter_attrs( _filter_attrs(
solver.get_variable_attrs(), solver.get_variable_attrs(),
Variables( Variables(
names=["x[0]", "x[1]", "x[2]", "x[3]", "z"], names=np.array(["x[0]", "x[1]", "x[2]", "x[3]", "z"], dtype="S"),
values=np.array([1.0, 0.0, 1.0, 1.0, 61.0]), values=np.array([1.0, 0.0, 1.0, 1.0, 61.0]),
), ),
), ),
@ -161,7 +162,7 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
# Build new constraint and verify that it is violated # Build new constraint and verify that it is violated
cf = Constraints( cf = Constraints(
names=["cut"], names=["cut"],
lhs=[[("x[0]", 1.0)]], lhs=[[(b"x[0]", 1.0)]],
rhs=np.array([0.0]), rhs=np.array([0.0]),
senses=["<"], senses=["<"],
) )
@ -178,14 +179,14 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
rhs=np.array([0.0, 0.0]), rhs=np.array([0.0, 0.0]),
lhs=[ lhs=[
[ [
("x[0]", 23.0), (b"x[0]", 23.0),
("x[1]", 26.0), (b"x[1]", 26.0),
("x[2]", 20.0), (b"x[2]", 20.0),
("x[3]", 18.0), (b"x[3]", 18.0),
("z", -1.0), (b"z", -1.0),
], ],
[ [
("x[0]", 1.0), (b"x[0]", 1.0),
], ],
], ],
senses=["=", "<"], senses=["=", "<"],
@ -208,16 +209,16 @@ def run_warm_start_tests(solver: InternalSolver) -> None:
instance = solver.build_test_instance_knapsack() instance = solver.build_test_instance_knapsack()
model = instance.to_model() model = instance.to_model()
solver.set_instance(instance, model) solver.set_instance(instance, model)
solver.set_warm_start({"x[0]": 1.0, "x[1]": 0.0, "x[2]": 0.0, "x[3]": 1.0}) solver.set_warm_start({b"x[0]": 1.0, b"x[1]": 0.0, b"x[2]": 0.0, b"x[3]": 1.0})
stats = solver.solve(tee=True) stats = solver.solve(tee=True)
if stats.mip_warm_start_value is not None: if stats.mip_warm_start_value is not None:
assert_equals(stats.mip_warm_start_value, 725.0) assert_equals(stats.mip_warm_start_value, 725.0)
solver.set_warm_start({"x[0]": 1.0, "x[1]": 1.0, "x[2]": 1.0, "x[3]": 1.0}) solver.set_warm_start({b"x[0]": 1.0, b"x[1]": 1.0, b"x[2]": 1.0, b"x[3]": 1.0})
stats = solver.solve(tee=True) stats = solver.solve(tee=True)
assert stats.mip_warm_start_value is None assert stats.mip_warm_start_value is None
solver.fix({"x[0]": 1.0, "x[1]": 0.0, "x[2]": 0.0, "x[3]": 1.0}) solver.fix({b"x[0]": 1.0, b"x[1]": 0.0, b"x[2]": 0.0, b"x[3]": 1.0})
stats = solver.solve(tee=True) stats = solver.solve(tee=True)
assert_equals(stats.mip_lower_bound, 725.0) assert_equals(stats.mip_lower_bound, 725.0)
assert_equals(stats.mip_upper_bound, 725.0) assert_equals(stats.mip_upper_bound, 725.0)
@ -257,15 +258,15 @@ def run_lazy_cb_tests(solver: InternalSolver) -> None:
def lazy_cb(cb_solver: InternalSolver, cb_model: Any) -> None: def lazy_cb(cb_solver: InternalSolver, cb_model: Any) -> None:
relsol = cb_solver.get_solution() relsol = cb_solver.get_solution()
assert relsol is not None assert relsol is not None
assert relsol["x[0]"] is not None assert relsol[b"x[0]"] is not None
if relsol["x[0]"] > 0: if relsol[b"x[0]"] > 0:
instance.enforce_lazy_constraint(cb_solver, cb_model, "cut") instance.enforce_lazy_constraint(cb_solver, cb_model, "cut")
solver.set_instance(instance, model) solver.set_instance(instance, model)
solver.solve(lazy_cb=lazy_cb) solver.solve(lazy_cb=lazy_cb)
solution = solver.get_solution() solution = solver.get_solution()
assert solution is not None assert solution is not None
assert_equals(solution["x[0]"], 0.0) assert_equals(solution[b"x[0]"], 0.0)
def _equals_preprocess(obj: Any) -> Any: def _equals_preprocess(obj: Any) -> Any:
@ -274,7 +275,7 @@ def _equals_preprocess(obj: Any) -> Any:
return np.round(obj, decimals=6).tolist() return np.round(obj, decimals=6).tolist()
else: else:
return obj.tolist() return obj.tolist()
elif isinstance(obj, (int, str, bool, np.bool_)): elif isinstance(obj, (int, str, bool, np.bool_, np.bytes_, bytes)):
return obj return obj
elif isinstance(obj, float): elif isinstance(obj, float):
return round(obj, 6) return round(obj, 6)

@ -15,8 +15,7 @@ IterationCallback = Callable[[], bool]
LazyCallback = Callable[[Any, Any], None] LazyCallback = Callable[[Any, Any], None]
SolverParams = Dict[str, Any] SolverParams = Dict[str, Any]
UserCutCallback = Callable[["InternalSolver", Any], None] UserCutCallback = Callable[["InternalSolver", Any], None]
VariableName = str Solution = Dict[bytes, Optional[float]]
Solution = Dict[VariableName, Optional[float]]
LearningSolveStats = TypedDict( LearningSolveStats = TypedDict(
"LearningSolveStats", "LearningSolveStats",

@ -22,7 +22,7 @@ from miplearn.solvers.tests import assert_equals
def sample() -> Sample: def sample() -> Sample:
sample = MemorySample( sample = MemorySample(
{ {
"static_var_names": ["x[0]", "x[1]", "x[2]", "x[3]"], "static_var_names": np.array(["x[0]", "x[1]", "x[2]", "x[3]"], dtype="S"),
"static_var_categories": ["default", None, "default", "default"], "static_var_categories": ["default", None, "default", "default"],
"mip_var_values": np.array([0.0, 1.0, 1.0, 0.0]), "mip_var_values": np.array([0.0, 1.0, 1.0, 0.0]),
"static_instance_features": [5.0], "static_instance_features": [5.0],
@ -112,10 +112,10 @@ def test_usage() -> None:
def test_evaluate(sample: Sample) -> None: def test_evaluate(sample: Sample) -> None:
comp = PrimalSolutionComponent() comp = PrimalSolutionComponent()
comp.sample_predict = lambda _: { # type: ignore comp.sample_predict = lambda _: { # type: ignore
"x[0]": 1.0, b"x[0]": 1.0,
"x[1]": 1.0, b"x[1]": 1.0,
"x[2]": 0.0, b"x[2]": 0.0,
"x[3]": None, b"x[3]": None,
} }
ev = comp.sample_evaluate(None, sample) ev = comp.sample_evaluate(None, sample)
assert_equals( assert_equals(
@ -150,8 +150,8 @@ def test_predict(sample: Sample) -> None:
assert_array_equal(x["default"], clf.predict_proba.call_args[0][0]) assert_array_equal(x["default"], clf.predict_proba.call_args[0][0])
assert_array_equal(x["default"], thr.predict.call_args[0][0]) assert_array_equal(x["default"], thr.predict.call_args[0][0])
assert pred == { assert pred == {
"x[0]": 0.0, b"x[0]": 0.0,
"x[1]": None, b"x[1]": None,
"x[2]": None, b"x[2]": None,
"x[3]": 1.0, b"x[3]": 1.0,
} }

@ -33,7 +33,7 @@ def test_knapsack() -> None:
extractor.extract_after_load_features(instance, solver, sample) extractor.extract_after_load_features(instance, solver, sample)
assert_equals( assert_equals(
sample.get_vector("static_var_names"), sample.get_vector("static_var_names"),
["x[0]", "x[1]", "x[2]", "x[3]", "z"], np.array(["x[0]", "x[1]", "x[2]", "x[3]", "z"], dtype="S"),
) )
assert_equals( assert_equals(
sample.get_vector("static_var_lower_bounds"), [0.0, 0.0, 0.0, 0.0, 0.0] sample.get_vector("static_var_lower_bounds"), [0.0, 0.0, 0.0, 0.0, 0.0]
@ -126,16 +126,16 @@ def test_constraint_getindex() -> None:
senses=["=", "<", ">"], senses=["=", "<", ">"],
lhs=[ lhs=[
[ [
("x1", 1.0), (b"x1", 1.0),
("x2", 1.0), (b"x2", 1.0),
], ],
[ [
("x2", 2.0), (b"x2", 2.0),
("x3", 2.0), (b"x3", 2.0),
], ],
[ [
("x3", 3.0), (b"x3", 3.0),
("x4", 3.0), (b"x4", 3.0),
], ],
], ],
) )
@ -147,12 +147,12 @@ def test_constraint_getindex() -> None:
senses=["=", ">"], senses=["=", ">"],
lhs=[ lhs=[
[ [
("x1", 1.0), (b"x1", 1.0),
("x2", 1.0), (b"x2", 1.0),
], ],
[ [
("x3", 3.0), (b"x3", 3.0),
("x4", 3.0), (b"x4", 3.0),
], ],
], ],
), ),

Loading…
Cancel
Save