Use np.ndarray in Variables

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

@ -4,7 +4,7 @@
import logging import logging
import sys import sys
from typing import Any, List, TextIO, cast from typing import Any, List, TextIO, cast, TypeVar, Optional, Sized
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -38,7 +38,10 @@ class _RedirectOutput:
sys.stderr = self._original_stderr sys.stderr = self._original_stderr
def _none_if_empty(obj: Any) -> Any: T = TypeVar("T", bound=Sized)
def _none_if_empty(obj: T) -> Optional[T]:
if len(obj) == 0: if len(obj) == 0:
return None return None
else: else:

@ -6,8 +6,9 @@ import re
import sys import sys
from io import StringIO from io import StringIO
from random import randint from random import randint
from typing import List, Any, Dict, Optional, Tuple, TYPE_CHECKING from typing import List, Any, Dict, Optional, TYPE_CHECKING
import numpy as np
from overrides import overrides from overrides import overrides
from miplearn.instance.base import Instance from miplearn.instance.base import Instance
@ -79,9 +80,9 @@ class GurobiSolver(InternalSolver):
self._var_names: List[str] = [] self._var_names: List[str] = []
self._constr_names: List[str] = [] self._constr_names: List[str] = []
self._var_types: List[str] = [] self._var_types: List[str] = []
self._var_lbs: List[float] = [] self._var_lbs: np.ndarray = np.empty(0)
self._var_ubs: List[float] = [] self._var_ubs: np.ndarray = np.empty(0)
self._var_obj_coeffs: List[float] = [] self._var_obj_coeffs: np.ndarray = np.empty(0)
if self.lazy_cb_frequency == 1: if self.lazy_cb_frequency == 1:
self.lazy_cb_where = [self.gp.GRB.Callback.MIPSOL] self.lazy_cb_where = [self.gp.GRB.Callback.MIPSOL]
@ -338,15 +339,33 @@ class GurobiSolver(InternalSolver):
) )
if with_sa: if with_sa:
sa_obj_up = model.getAttr("saobjUp", self._gp_vars) sa_obj_up = np.array(
sa_obj_down = model.getAttr("saobjLow", self._gp_vars) model.getAttr("saobjUp", self._gp_vars),
sa_ub_up = model.getAttr("saubUp", self._gp_vars) dtype=float,
sa_ub_down = model.getAttr("saubLow", self._gp_vars) )
sa_lb_up = model.getAttr("salbUp", self._gp_vars) sa_obj_down = np.array(
sa_lb_down = model.getAttr("salbLow", self._gp_vars) model.getAttr("saobjLow", self._gp_vars),
dtype=float,
)
sa_ub_up = np.array(
model.getAttr("saubUp", self._gp_vars),
dtype=float,
)
sa_ub_down = np.array(
model.getAttr("saubLow", self._gp_vars),
dtype=float,
)
sa_lb_up = np.array(
model.getAttr("salbUp", self._gp_vars),
dtype=float,
)
sa_lb_down = np.array(
model.getAttr("salbLow", self._gp_vars),
dtype=float,
)
if model.solCount > 0: if model.solCount > 0:
values = model.getAttr("x", self._gp_vars) values = np.array(model.getAttr("x", self._gp_vars), dtype=float)
return Variables( return Variables(
names=self._var_names, names=self._var_names,
@ -565,9 +584,18 @@ class GurobiSolver(InternalSolver):
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: List[str] = self.model.getAttr("varName", gp_vars)
var_types: List[str] = self.model.getAttr("vtype", gp_vars) var_types: List[str] = self.model.getAttr("vtype", gp_vars)
var_ubs: List[float] = self.model.getAttr("ub", gp_vars) var_ubs: np.ndarray = np.array(
var_lbs: List[float] = self.model.getAttr("lb", gp_vars) self.model.getAttr("ub", gp_vars),
var_obj_coeffs: List[float] = self.model.getAttr("obj", gp_vars) dtype=float,
)
var_lbs: np.ndarray = np.array(
self.model.getAttr("lb", gp_vars),
dtype=float,
)
var_obj_coeffs: np.ndarray = np.array(
self.model.getAttr("obj", gp_vars),
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 = {}
cname_to_constr: Dict = {} cname_to_constr: Dict = {}

@ -7,6 +7,8 @@ from abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Optional, List, Tuple, TYPE_CHECKING from typing import Any, Optional, List, Tuple, TYPE_CHECKING
import numpy as np
from miplearn.instance.base import Instance from miplearn.instance.base import Instance
from miplearn.types import ( from miplearn.types import (
IterationCallback, IterationCallback,
@ -50,18 +52,18 @@ class MIPSolveStats:
class Variables: class Variables:
names: Optional[List[str]] = None names: Optional[List[str]] = None
basis_status: Optional[List[str]] = None basis_status: Optional[List[str]] = None
lower_bounds: Optional[List[float]] = None lower_bounds: Optional[np.ndarray] = None
obj_coeffs: Optional[List[float]] = None obj_coeffs: Optional[np.ndarray] = None
reduced_costs: Optional[List[float]] = None reduced_costs: Optional[np.ndarray] = None
sa_lb_down: Optional[List[float]] = None sa_lb_down: Optional[np.ndarray] = None
sa_lb_up: Optional[List[float]] = None sa_lb_up: Optional[np.ndarray] = None
sa_obj_down: Optional[List[float]] = None sa_obj_down: Optional[np.ndarray] = None
sa_obj_up: Optional[List[float]] = None sa_obj_up: Optional[np.ndarray] = None
sa_ub_down: Optional[List[float]] = None sa_ub_down: Optional[np.ndarray] = None
sa_ub_up: Optional[List[float]] = None sa_ub_up: Optional[np.ndarray] = None
types: Optional[List[str]] = None types: Optional[List[str]] = None
upper_bounds: Optional[List[float]] = None upper_bounds: Optional[np.ndarray] = None
values: Optional[List[float]] = None values: Optional[np.ndarray] = None
@dataclass @dataclass

@ -330,11 +330,11 @@ class BasePyomoSolver(InternalSolver):
return Variables( return Variables(
names=_none_if_empty(names), names=_none_if_empty(names),
types=_none_if_empty(types), types=_none_if_empty(types),
upper_bounds=_none_if_empty(upper_bounds), upper_bounds=_none_if_empty(np.array(upper_bounds, dtype=float)),
lower_bounds=_none_if_empty(lower_bounds), lower_bounds=_none_if_empty(np.array(lower_bounds, dtype=float)),
obj_coeffs=_none_if_empty(obj_coeffs), obj_coeffs=_none_if_empty(np.array(obj_coeffs, dtype=float)),
reduced_costs=_none_if_empty(reduced_costs), reduced_costs=_none_if_empty(np.array(reduced_costs, dtype=float)),
values=_none_if_empty(values), values=_none_if_empty(np.array(values, dtype=float)),
) )
@overrides @overrides

@ -41,10 +41,10 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
solver.get_variables(), solver.get_variables(),
Variables( Variables(
names=["x[0]", "x[1]", "x[2]", "x[3]", "z"], names=["x[0]", "x[1]", "x[2]", "x[3]", "z"],
lower_bounds=[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=[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"],
obj_coeffs=[505.0, 352.0, 458.0, 220.0, 0.0], obj_coeffs=np.array([505.0, 352.0, 458.0, 220.0, 0.0]),
), ),
) )
@ -85,14 +85,18 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
Variables( Variables(
names=["x[0]", "x[1]", "x[2]", "x[3]", "z"], names=["x[0]", "x[1]", "x[2]", "x[3]", "z"],
basis_status=["U", "B", "U", "L", "U"], basis_status=["U", "B", "U", "L", "U"],
reduced_costs=[193.615385, 0.0, 187.230769, -23.692308, 13.538462], reduced_costs=np.array(
sa_lb_down=[-inf, -inf, -inf, -0.111111, -inf], [193.615385, 0.0, 187.230769, -23.692308, 13.538462]
sa_lb_up=[1.0, 0.923077, 1.0, 1.0, 67.0], ),
sa_obj_down=[311.384615, 317.777778, 270.769231, -inf, -13.538462], sa_lb_down=np.array([-inf, -inf, -inf, -0.111111, -inf]),
sa_obj_up=[inf, 570.869565, inf, 243.692308, inf], sa_lb_up=np.array([1.0, 0.923077, 1.0, 1.0, 67.0]),
sa_ub_down=[0.913043, 0.923077, 0.9, 0.0, 43.0], sa_obj_down=np.array(
sa_ub_up=[2.043478, inf, 2.2, inf, 69.0], [311.384615, 317.777778, 270.769231, -inf, -13.538462]
values=[1.0, 0.923077, 1.0, 0.0, 67.0], ),
sa_obj_up=np.array([inf, 570.869565, inf, 243.692308, inf]),
sa_ub_down=np.array([0.913043, 0.923077, 0.9, 0.0, 43.0]),
sa_ub_up=np.array([2.043478, inf, 2.2, inf, 69.0]),
values=np.array([1.0, 0.923077, 1.0, 0.0, 67.0]),
), ),
), ),
) )
@ -137,7 +141,7 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
solver.get_variable_attrs(), solver.get_variable_attrs(),
Variables( Variables(
names=["x[0]", "x[1]", "x[2]", "x[3]", "z"], names=["x[0]", "x[1]", "x[2]", "x[3]", "z"],
values=[1.0, 0.0, 1.0, 1.0, 61.0], values=np.array([1.0, 0.0, 1.0, 1.0, 61.0]),
), ),
), ),
) )

@ -24,7 +24,7 @@ def sample() -> Sample:
{ {
"static_var_names": ["x[0]", "x[1]", "x[2]", "x[3]"], "static_var_names": ["x[0]", "x[1]", "x[2]", "x[3]"],
"static_var_categories": ["default", None, "default", "default"], "static_var_categories": ["default", None, "default", "default"],
"mip_var_values": [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],
"static_var_features": [ "static_var_features": [
[0.0, 0.0], [0.0, 0.0],

@ -32,7 +32,8 @@ 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"), ["x[0]", "x[1]", "x[2]", "x[3]", "z"] sample.get_vector("static_var_names"),
["x[0]", "x[1]", "x[2]", "x[3]", "z"],
) )
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]

@ -17,7 +17,7 @@ def test_usage() -> None:
# Save instance to disk # Save instance to disk
filename = tempfile.mktemp() filename = tempfile.mktemp()
FileInstance.save(original, filename) FileInstance.save(original, filename)
sample = Hdf5Sample(filename) sample = Hdf5Sample(filename, check_data=True)
assert len(sample.get_bytes("pickled")) > 0 assert len(sample.get_bytes("pickled")) > 0
# Solve instance from disk # Solve instance from disk

@ -9,6 +9,7 @@ from scipy.stats import uniform, randint
from miplearn.problems.tsp import TravelingSalesmanGenerator, TravelingSalesmanInstance from miplearn.problems.tsp import TravelingSalesmanGenerator, TravelingSalesmanInstance
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver
from miplearn.solvers.tests import assert_equals
def test_generator() -> None: def test_generator() -> None:
@ -41,7 +42,7 @@ def test_instance() -> None:
solver.solve(instance) solver.solve(instance)
assert len(instance.get_samples()) == 1 assert len(instance.get_samples()) == 1
sample = instance.get_samples()[0] sample = instance.get_samples()[0]
assert sample.get_vector("mip_var_values") == [1.0, 0.0, 1.0, 1.0, 0.0, 1.0] assert_equals(sample.get_vector("mip_var_values"), [1.0, 0.0, 1.0, 1.0, 0.0, 1.0])
assert sample.get_scalar("mip_lower_bound") == 4.0 assert sample.get_scalar("mip_lower_bound") == 4.0
assert sample.get_scalar("mip_upper_bound") == 4.0 assert sample.get_scalar("mip_upper_bound") == 4.0
@ -68,22 +69,25 @@ def test_subtour() -> None:
lazy_enforced = sample.get_set("mip_constr_lazy_enforced") lazy_enforced = sample.get_set("mip_constr_lazy_enforced")
assert lazy_enforced is not None assert lazy_enforced is not None
assert len(lazy_enforced) > 0 assert len(lazy_enforced) > 0
assert sample.get_vector("mip_var_values") == [ assert_equals(
1.0, sample.get_vector("mip_var_values"),
0.0, [
0.0, 1.0,
1.0, 0.0,
0.0, 0.0,
1.0, 1.0,
0.0, 0.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 0.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
1.0, 0.0,
] 1.0,
1.0,
],
)
solver.fit([instance]) solver.fit([instance])
solver.solve(instance) solver.solve(instance)

@ -38,7 +38,9 @@ def test_learning_solver(
assert len(instance.get_samples()) > 0 assert len(instance.get_samples()) > 0
sample = instance.get_samples()[0] sample = instance.get_samples()[0]
assert sample.get_vector("mip_var_values") == [1.0, 0.0, 1.0, 1.0, 61.0] assert_equals(
sample.get_vector("mip_var_values"), [1.0, 0.0, 1.0, 1.0, 61.0]
)
assert sample.get_scalar("mip_lower_bound") == 1183.0 assert sample.get_scalar("mip_lower_bound") == 1183.0
assert sample.get_scalar("mip_upper_bound") == 1183.0 assert sample.get_scalar("mip_upper_bound") == 1183.0
mip_log = sample.get_scalar("mip_log") mip_log = sample.get_scalar("mip_log")

Loading…
Cancel
Save