From b55554d410298c922efdfeb24e87d4abe306648d Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Tue, 6 Feb 2024 16:08:24 -0600 Subject: [PATCH] Add _gurobipy suffix to all build_model functions --- docs/guide/collectors.ipynb | 2 +- docs/guide/features.ipynb | 4 +- docs/guide/problems.ipynb | 76 +++++++++++++-------------- docs/guide/solvers.ipynb | 2 + docs/tutorials/cuts-gurobipy.ipynb | 21 +++----- miplearn/classifiers/minprob.py | 2 +- miplearn/components/primal/actions.py | 2 +- miplearn/components/primal/indep.py | 4 +- miplearn/components/priority.py | 2 +- miplearn/problems/__init__.py | 4 +- miplearn/problems/binpack.py | 2 +- miplearn/problems/multiknapsack.py | 4 +- miplearn/problems/pmedian.py | 2 +- miplearn/problems/setpack.py | 2 +- miplearn/problems/stab.py | 4 +- miplearn/problems/tsp.py | 2 - miplearn/problems/uc.py | 2 +- miplearn/problems/vertexcover.py | 6 ++- miplearn/solvers/gurobi.py | 14 ++--- miplearn/solvers/pyomo.py | 10 ++-- tests/components/cuts/test_mem.py | 2 +- tests/components/lazy/test_mem.py | 2 +- tests/problems/test_binpack.py | 8 ++- tests/problems/test_multiknapsack.py | 4 +- tests/problems/test_pmedian.py | 4 +- tests/problems/test_setpack.py | 4 +- tests/problems/test_uc.py | 6 +-- tests/problems/test_vertexcover.py | 4 +- 28 files changed, 99 insertions(+), 102 deletions(-) diff --git a/docs/guide/collectors.ipynb b/docs/guide/collectors.ipynb index a9b4bb6..443802e 100644 --- a/docs/guide/collectors.ipynb +++ b/docs/guide/collectors.ipynb @@ -183,7 +183,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "id": "ac6f8c6f", "metadata": { "ExecuteTime": { diff --git a/docs/guide/features.ipynb b/docs/guide/features.ipynb index 81c2629..495e8ea 100644 --- a/docs/guide/features.ipynb +++ b/docs/guide/features.ipynb @@ -101,7 +101,7 @@ "from miplearn.io import write_pkl_gz\n", "from miplearn.problems.multiknapsack import (\n", " MultiKnapsackGenerator,\n", - " build_multiknapsack_model,\n", + " build_multiknapsack_model_gurobipy,\n", ")\n", "\n", "# Set random seed to make example reproducible\n", @@ -127,7 +127,7 @@ "# Run the basic collector\n", "BasicCollector().collect(\n", " glob(\"data/multiknapsack/*\"),\n", - " build_multiknapsack_model,\n", + " build_multiknapsack_model_gurobipy,\n", " n_jobs=4,\n", ")\n", "\n", diff --git a/docs/guide/problems.ipynb b/docs/guide/problems.ipynb index bf7d9fb..acc35fb 100644 --- a/docs/guide/problems.ipynb +++ b/docs/guide/problems.ipynb @@ -39,7 +39,6 @@ "cell_type": "markdown", "id": "830f3784-a3fc-4e2f-a484-e7808841ffe8", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -159,20 +158,22 @@ "H 0 0 2.0000000 1.27484 36.3% - 0s\n", " 0 0 1.27484 0 4 2.00000 1.27484 36.3% - 0s\n", "\n", - "Explored 1 nodes (38 simplex iterations) in 0.01 seconds (0.00 work units)\n", + "Explored 1 nodes (38 simplex iterations) in 0.03 seconds (0.00 work units)\n", "Thread count was 20 (of 20 available processors)\n", "\n", "Solution count 3: 2 4 5 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective 2.000000000000e+00, best bound 2.000000000000e+00, gap 0.0000%\n" + "Best objective 2.000000000000e+00, best bound 2.000000000000e+00, gap 0.0000%\n", + "\n", + "User-callback calls 143, time in user-callback 0.00 sec\n" ] } ], "source": [ "import numpy as np\n", "from scipy.stats import uniform, randint\n", - "from miplearn.problems.binpack import BinPackGenerator, build_binpack_model\n", + "from miplearn.problems.binpack import BinPackGenerator, build_binpack_model_gurobipy\n", "\n", "# Set random seed, to make example reproducible\n", "np.random.seed(42)\n", @@ -193,7 +194,7 @@ "print()\n", "\n", "# Optimize first instance\n", - "model = build_binpack_model(data[0])\n", + "model = build_binpack_model_gurobipy(data[0])\n", "model.optimize()" ] }, @@ -360,7 +361,9 @@ "No other solutions better than -1279\n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective -1.279000000000e+03, best bound -1.279000000000e+03, gap 0.0000%\n" + "Best objective -1.279000000000e+03, best bound -1.279000000000e+03, gap 0.0000%\n", + "\n", + "User-callback calls 490, time in user-callback 0.00 sec\n" ] } ], @@ -369,7 +372,7 @@ "from scipy.stats import uniform, randint\n", "from miplearn.problems.multiknapsack import (\n", " MultiKnapsackGenerator,\n", - " build_multiknapsack_model,\n", + " build_multiknapsack_model_gurobipy,\n", ")\n", "\n", "# Set random seed, to make example reproducible\n", @@ -396,7 +399,7 @@ "print()\n", "\n", "# Build model and optimize\n", - "model = build_multiknapsack_model(data[0])\n", + "model = build_multiknapsack_model_gurobipy(data[0])\n", "model.optimize()" ] }, @@ -535,20 +538,22 @@ " 0 0 86.06884 0 15 93.92000 86.06884 8.36% - 0s\n", "* 0 0 0 91.2300000 91.23000 0.00% - 0s\n", "\n", - "Explored 1 nodes (70 simplex iterations) in 0.07 seconds (0.00 work units)\n", + "Explored 1 nodes (70 simplex iterations) in 0.08 seconds (0.00 work units)\n", "Thread count was 20 (of 20 available processors)\n", "\n", "Solution count 10: 91.23 93.92 93.98 ... 368.79\n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective 9.123000000000e+01, best bound 9.123000000000e+01, gap 0.0000%\n" + "Best objective 9.123000000000e+01, best bound 9.123000000000e+01, gap 0.0000%\n", + "\n", + "User-callback calls 190, time in user-callback 0.00 sec\n" ] } ], "source": [ "import numpy as np\n", "from scipy.stats import uniform, randint\n", - "from miplearn.problems.pmedian import PMedianGenerator, build_pmedian_model\n", + "from miplearn.problems.pmedian import PMedianGenerator, build_pmedian_model_gurobipy\n", "\n", "# Set random seed, to make example reproducible\n", "np.random.seed(42)\n", @@ -576,7 +581,7 @@ "print()\n", "\n", "# Build and optimize model\n", - "model = build_pmedian_model(data[0])\n", + "model = build_pmedian_model_gurobipy(data[0])\n", "model.optimize()" ] }, @@ -694,7 +699,9 @@ "Solution count 1: 213.49 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective 2.134900000000e+02, best bound 2.134900000000e+02, gap 0.0000%\n" + "Best objective 2.134900000000e+02, best bound 2.134900000000e+02, gap 0.0000%\n", + "\n", + "User-callback calls 178, time in user-callback 0.00 sec\n" ] } ], @@ -834,14 +841,16 @@ "No other solutions better than -1986.37\n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective -1.986370000000e+03, best bound -1.986370000000e+03, gap 0.0000%\n" + "Best objective -1.986370000000e+03, best bound -1.986370000000e+03, gap 0.0000%\n", + "\n", + "User-callback calls 238, time in user-callback 0.00 sec\n" ] } ], "source": [ "import numpy as np\n", "from scipy.stats import uniform, randint\n", - "from miplearn.problems.setpack import SetPackGenerator, build_setpack_model\n", + "from miplearn.problems.setpack import SetPackGenerator, build_setpack_model_gurobipy\n", "\n", "# Set random seed, to make example reproducible\n", "np.random.seed(42)\n", @@ -865,7 +874,7 @@ "print()\n", "\n", "# Build and optimize model\n", - "model = build_setpack_model(data[0])\n", + "model = build_setpack_model_gurobipy(data[0])\n", "model.optimize()" ] }, @@ -1374,13 +1383,15 @@ " RLT: 1\n", " Relax-and-lift: 7\n", "\n", - "Explored 1 nodes (234 simplex iterations) in 0.03 seconds (0.02 work units)\n", + "Explored 1 nodes (234 simplex iterations) in 0.02 seconds (0.02 work units)\n", "Thread count was 20 (of 20 available processors)\n", "\n", "Solution count 5: 364722 368600 374044 ... 440662\n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective 3.647217661000e+05, best bound 3.647217661000e+05, gap 0.0000%\n" + "Best objective 3.647217661000e+05, best bound 3.647217661000e+05, gap 0.0000%\n", + "\n", + "User-callback calls 677, time in user-callback 0.00 sec\n" ] } ], @@ -1388,7 +1399,7 @@ "import random\n", "import numpy as np\n", "from scipy.stats import uniform, randint\n", - "from miplearn.problems.uc import UnitCommitmentGenerator, build_uc_model\n", + "from miplearn.problems.uc import UnitCommitmentGenerator, build_uc_model_gurobipy\n", "\n", "# Set random seed to make example reproducible\n", "random.seed(42)\n", @@ -1424,7 +1435,7 @@ " print()\n", "\n", "# Load and optimize the first instance\n", - "model = build_uc_model(data[0])\n", + "model = build_uc_model_gurobipy(data[0])\n", "model.optimize()" ] }, @@ -1532,7 +1543,9 @@ "Solution count 1: 301 \n", "\n", "Optimal solution found (tolerance 1.00e-04)\n", - "Best objective 3.010000000000e+02, best bound 3.010000000000e+02, gap 0.0000%\n" + "Best objective 3.010000000000e+02, best bound 3.010000000000e+02, gap 0.0000%\n", + "\n", + "User-callback calls 326, time in user-callback 0.00 sec\n" ] } ], @@ -1542,7 +1555,7 @@ "from scipy.stats import uniform, randint\n", "from miplearn.problems.vertexcover import (\n", " MinWeightVertexCoverGenerator,\n", - " build_vertexcover_model,\n", + " build_vertexcover_model_gurobipy,\n", ")\n", "\n", "# Set random seed to make example reproducible\n", @@ -1565,26 +1578,9 @@ "print()\n", "\n", "# Load and optimize the first instance\n", - "model = build_vertexcover_model(data[0])\n", + "model = build_vertexcover_model_gurobipy(data[0])\n", "model.optimize()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9f12e91f", - "metadata": { - "ExecuteTime": { - "end_time": "2023-11-07T16:29:49.075852252Z", - "start_time": "2023-11-07T16:29:49.050243601Z" - }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } - }, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/docs/guide/solvers.ipynb b/docs/guide/solvers.ipynb index d89824a..c4ee9bc 100644 --- a/docs/guide/solvers.ipynb +++ b/docs/guide/solvers.ipynb @@ -92,6 +92,8 @@ "\n", "Solved in 15 iterations and 0.00 seconds (0.00 work units)\n", "Optimal objective 2.761000000e+03\n", + "\n", + "User-callback calls 56, time in user-callback 0.00 sec\n", "Set parameter PreCrush to value 1\n", "Set parameter LazyConstraints to value 1\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (linux64)\n", diff --git a/docs/tutorials/cuts-gurobipy.ipynb b/docs/tutorials/cuts-gurobipy.ipynb index 11da95e..ffdc13d 100644 --- a/docs/tutorials/cuts-gurobipy.ipynb +++ b/docs/tutorials/cuts-gurobipy.ipynb @@ -87,8 +87,10 @@ "\n", "# Set up Python logging\n", "import logging\n", + "\n", "logging.basicConfig(level=logging.WARNING)\n", "\n", + "\n", "def build_tsp_model_gurobipy_simplified(data):\n", " # Read data from file if a filename is provided\n", " if isinstance(data, str):\n", @@ -99,9 +101,7 @@ "\n", " # Create set of edges between every pair of cities, for convenience\n", " edges = tuplelist(\n", - " (i, j)\n", - " for i in range(data.n_cities)\n", - " for j in range(i + 1, data.n_cities)\n", + " (i, j) for i in range(data.n_cities) for j in range(i + 1, data.n_cities)\n", " )\n", "\n", " # Add binary variable x[e] for each edge e\n", @@ -113,11 +113,8 @@ " # Add constraint: must choose two edges adjacent to each city\n", " model.addConstrs(\n", " (\n", - " quicksum(\n", - " x[min(i, j), max(i, j)]\n", - " for j in range(data.n_cities)\n", - " if i != j\n", - " ) == 2\n", + " quicksum(x[min(i, j), max(i, j)] for j in range(data.n_cities) if i != j)\n", + " == 2\n", " for i in range(data.n_cities)\n", " ),\n", " name=\"eq_degree\",\n", @@ -129,7 +126,7 @@ " \"\"\"\n", " # Query current value of the x variables\n", " x_val = m.inner.cbGetSolution(x)\n", - " \n", + "\n", " # Initialize empty set of violations\n", " violations = []\n", "\n", @@ -164,9 +161,7 @@ " \"\"\"\n", " print(f\"Enforcing {len(violations)} subtour elimination constraints\")\n", " for violation in violations:\n", - " m.add_constr(\n", - " quicksum(x[e[0], e[1]] for e in violation) >= 2\n", - " )\n", + " m.add_constr(quicksum(x[e[0], e[1]] for e in violation) >= 2)\n", "\n", " return GurobiModel(\n", " model,\n", @@ -494,7 +489,7 @@ } ], "source": [ - "solver = LearningSolver(components=[]) # empty set of ML components\n", + "solver = LearningSolver(components=[]) # empty set of ML components\n", "solver.optimize(test_data[0], build_tsp_model_gurobipy_simplified);" ] }, diff --git a/miplearn/classifiers/minprob.py b/miplearn/classifiers/minprob.py index 330d925..06345ba 100644 --- a/miplearn/classifiers/minprob.py +++ b/miplearn/classifiers/minprob.py @@ -54,7 +54,7 @@ class MinProbabilityClassifier(BaseEstimator): y_pred = [] for sample_idx in range(n_samples): yi = float("nan") - for (class_idx, class_val) in enumerate(self.classes_): + for class_idx, class_val in enumerate(self.classes_): if y_proba[sample_idx, class_idx] >= self.thresholds[class_idx]: yi = class_val y_pred.append(yi) diff --git a/miplearn/components/primal/actions.py b/miplearn/components/primal/actions.py index 0a1a1d9..06b37c3 100644 --- a/miplearn/components/primal/actions.py +++ b/miplearn/components/primal/actions.py @@ -71,7 +71,7 @@ class EnforceProximity(PrimalComponentAction): constr_lhs = [] constr_vars = [] constr_rhs = 0.0 - for (i, var_name) in enumerate(var_names): + for i, var_name in enumerate(var_names): if np.isnan(var_values[i]): continue constr_lhs.append(1.0 if var_values[i] < 0.5 else -1.0) diff --git a/miplearn/components/primal/indep.py b/miplearn/components/primal/indep.py index 45c509d..1479d92 100644 --- a/miplearn/components/primal/indep.py +++ b/miplearn/components/primal/indep.py @@ -91,7 +91,7 @@ class IndependentVarsPrimalComponent: logger.info(f"Training {n_bin_vars} classifiers...") self.clf_ = {} - for (var_idx, var_name) in enumerate(self.bin_var_names_): + for var_idx, var_name in enumerate(self.bin_var_names_): self.clf_[var_name] = self.clone_fn(self.base_clf) self.clf_[var_name].fit( x_np[var_idx::n_bin_vars, :], y_np[var_idx::n_bin_vars] @@ -117,7 +117,7 @@ class IndependentVarsPrimalComponent: # Predict optimal solution logger.info("Predicting warm starts...") y_pred = [] - for (var_idx, var_name) in enumerate(self.bin_var_names_): + for var_idx, var_name in enumerate(self.bin_var_names_): x_var = x_sample[var_idx, :].reshape(1, -1) y_var = self.clf_[var_name].predict(x_var) assert y_var.shape == (1,) diff --git a/miplearn/components/priority.py b/miplearn/components/priority.py index c232525..56c3b40 100644 --- a/miplearn/components/priority.py +++ b/miplearn/components/priority.py @@ -25,7 +25,7 @@ class ExpertBranchPriorityComponent: assert var_priority is not None assert var_names is not None - for (var_idx, var_name) in enumerate(var_names): + for var_idx, var_name in enumerate(var_names): if np.isfinite(var_priority[var_idx]): var = model.getVarByName(var_name.decode()) var.branchPriority = int(log(1 + var_priority[var_idx])) diff --git a/miplearn/problems/__init__.py b/miplearn/problems/__init__.py index bdf9921..6431fb6 100644 --- a/miplearn/problems/__init__.py +++ b/miplearn/problems/__init__.py @@ -11,7 +11,7 @@ from pyomo import environ as pe def _gurobipy_set_params(model: gp.Model, params: Optional[dict[str, Any]]) -> None: assert isinstance(model, gp.Model) if params is not None: - for (param_name, param_value) in params.items(): + for param_name, param_value in params.items(): setattr(model.params, param_name, param_value) @@ -24,5 +24,5 @@ def _pyomo_set_params( solver == "gurobi_persistent" ), "setting parameters is only supported with gurobi_persistent" if solver == "gurobi_persistent" and params is not None: - for (param_name, param_value) in params.items(): + for param_name, param_value in params.items(): model.solver.set_gurobi_param(param_name, param_value) diff --git a/miplearn/problems/binpack.py b/miplearn/problems/binpack.py index 0523192..2312e1d 100644 --- a/miplearn/problems/binpack.py +++ b/miplearn/problems/binpack.py @@ -109,7 +109,7 @@ class BinPackGenerator: return [_sample() for n in range(n_samples)] -def build_binpack_model(data: Union[str, BinPackData]) -> GurobiModel: +def build_binpack_model_gurobipy(data: Union[str, BinPackData]) -> GurobiModel: """Converts bin packing problem data into a concrete Gurobipy model.""" if isinstance(data, str): data = read_pkl_gz(data) diff --git a/miplearn/problems/multiknapsack.py b/miplearn/problems/multiknapsack.py index 79d65a0..adc38e4 100644 --- a/miplearn/problems/multiknapsack.py +++ b/miplearn/problems/multiknapsack.py @@ -174,7 +174,9 @@ class MultiKnapsackGenerator: return [_sample() for _ in range(n_samples)] -def build_multiknapsack_model(data: Union[str, MultiKnapsackData]) -> GurobiModel: +def build_multiknapsack_model_gurobipy( + data: Union[str, MultiKnapsackData] +) -> GurobiModel: """Converts multi-knapsack problem data into a concrete Gurobipy model.""" if isinstance(data, str): data = read_pkl_gz(data) diff --git a/miplearn/problems/pmedian.py b/miplearn/problems/pmedian.py index 6e85f1e..d1dbf2e 100644 --- a/miplearn/problems/pmedian.py +++ b/miplearn/problems/pmedian.py @@ -141,7 +141,7 @@ class PMedianGenerator: return [_sample() for _ in range(n_samples)] -def build_pmedian_model(data: Union[str, PMedianData]) -> GurobiModel: +def build_pmedian_model_gurobipy(data: Union[str, PMedianData]) -> GurobiModel: """Converts capacitated p-median data into a concrete Gurobipy model.""" if isinstance(data, str): data = read_pkl_gz(data) diff --git a/miplearn/problems/setpack.py b/miplearn/problems/setpack.py index a194b90..453e7f0 100644 --- a/miplearn/problems/setpack.py +++ b/miplearn/problems/setpack.py @@ -53,7 +53,7 @@ class SetPackGenerator: ] -def build_setpack_model(data: Union[str, SetPackData]) -> GurobiModel: +def build_setpack_model_gurobipy(data: Union[str, SetPackData]) -> GurobiModel: if isinstance(data, str): data = read_pkl_gz(data) assert isinstance(data, SetPackData) diff --git a/miplearn/problems/stab.py b/miplearn/problems/stab.py index 0f39eb4..0e35404 100644 --- a/miplearn/problems/stab.py +++ b/miplearn/problems/stab.py @@ -101,7 +101,7 @@ def build_stab_model_gurobipy( model.setObjective(quicksum(-data.weights[i] * x[i] for i in nodes)) # Edge inequalities - for (i1, i2) in data.graph.edges: + for i1, i2 in data.graph.edges: model.addConstr(x[i1] + x[i2] <= 1) def cuts_separate(m: GurobiModel) -> List[Hashable]: @@ -137,7 +137,7 @@ def build_stab_model_pyomo( # Edge inequalities model.edge_eqs = pe.ConstraintList() - for (i1, i2) in data.graph.edges: + for i1, i2 in data.graph.edges: model.edge_eqs.add(model.x[i1] + model.x[i2] <= 1) # Clique inequalities diff --git a/miplearn/problems/tsp.py b/miplearn/problems/tsp.py index 61ddcf3..f06b9f0 100644 --- a/miplearn/problems/tsp.py +++ b/miplearn/problems/tsp.py @@ -119,7 +119,6 @@ def build_tsp_model_gurobipy( data: Union[str, TravelingSalesmanData], params: Optional[dict[str, Any]] = None, ) -> GurobiModel: - model = gp.Model() _gurobipy_set_params(model, params) @@ -173,7 +172,6 @@ def build_tsp_model_pyomo( solver: str = "gurobi_persistent", params: Optional[dict[str, Any]] = None, ) -> PyomoModel: - model = pe.ConcreteModel() data = _tsp_read(data) diff --git a/miplearn/problems/uc.py b/miplearn/problems/uc.py index 28fc314..63f4178 100644 --- a/miplearn/problems/uc.py +++ b/miplearn/problems/uc.py @@ -112,7 +112,7 @@ class UnitCommitmentGenerator: return [_sample() for _ in range(n_samples)] -def build_uc_model(data: Union[str, UnitCommitmentData]) -> GurobiModel: +def build_uc_model_gurobipy(data: Union[str, UnitCommitmentData]) -> GurobiModel: """ Models the unit commitment problem according to equations (1)-(5) of: diff --git a/miplearn/problems/vertexcover.py b/miplearn/problems/vertexcover.py index 097c48a..eeb5a99 100644 --- a/miplearn/problems/vertexcover.py +++ b/miplearn/problems/vertexcover.py @@ -40,7 +40,9 @@ class MinWeightVertexCoverGenerator: ] -def build_vertexcover_model(data: Union[str, MinWeightVertexCoverData]) -> GurobiModel: +def build_vertexcover_model_gurobipy( + data: Union[str, MinWeightVertexCoverData] +) -> GurobiModel: if isinstance(data, str): data = read_pkl_gz(data) assert isinstance(data, MinWeightVertexCoverData) @@ -48,7 +50,7 @@ def build_vertexcover_model(data: Union[str, MinWeightVertexCoverData]) -> Gurob nodes = list(data.graph.nodes) x = model.addVars(nodes, vtype=GRB.BINARY, name="x") model.setObjective(quicksum(data.weights[i] * x[i] for i in nodes)) - for (v1, v2) in data.graph.edges: + for v1, v2 in data.graph.edges: model.addConstr(x[v1] + x[v2] >= 1) model.update() return GurobiModel(model) diff --git a/miplearn/solvers/gurobi.py b/miplearn/solvers/gurobi.py index 021c043..c9c71b3 100644 --- a/miplearn/solvers/gurobi.py +++ b/miplearn/solvers/gurobi.py @@ -184,7 +184,7 @@ class GurobiModel(AbstractModel): assert var_names.shape == var_values.shape n_fixed = 0 - for (var_idx, var_name) in enumerate(var_names): + for var_idx, var_name in enumerate(var_names): var_val = var_values[var_idx] if np.isfinite(var_val): var = self.inner.getVarByName(var_name.decode()) @@ -229,7 +229,7 @@ class GurobiModel(AbstractModel): self.inner.numStart = n_starts for start_idx in range(n_starts): self.inner.params.startNumber = start_idx - for (var_idx, var_name) in enumerate(var_names): + for var_idx, var_name in enumerate(var_names): var_val = var_values[start_idx, var_idx] if np.isfinite(var_val): var = self.inner.getVarByName(var_name.decode()) @@ -243,14 +243,14 @@ class GurobiModel(AbstractModel): def _extract_after_load_vars(self, h5: H5File) -> None: gp_vars = self.inner.getVars() - for (h5_field, gp_field) in { + for h5_field, gp_field in { "static_var_names": "varName", "static_var_types": "vtype", }.items(): h5.put_array( h5_field, np.array(self.inner.getAttr(gp_field, gp_vars), dtype="S") ) - for (h5_field, gp_field) in { + for h5_field, gp_field in { "static_var_upper_bounds": "ub", "static_var_lower_bounds": "lb", "static_var_obj_coeffs": "obj", @@ -267,7 +267,7 @@ class GurobiModel(AbstractModel): names = np.array(self.inner.getAttr("constrName", gp_constrs), dtype="S") nrows, ncols = len(gp_constrs), len(gp_vars) tmp = lil_matrix((nrows, ncols), dtype=float) - for (i, gp_constr) in enumerate(gp_constrs): + for i, gp_constr in enumerate(gp_constrs): expr = self.inner.getRow(gp_constr) for j in range(expr.size()): tmp[i, expr.getVar(j).index] = expr.getCoeff(j) @@ -302,7 +302,7 @@ class GurobiModel(AbstractModel): dtype="S", ), ) - for (h5_field, gp_field) in { + for h5_field, gp_field in { "lp_var_reduced_costs": "rc", "lp_var_sa_obj_up": "saobjUp", "lp_var_sa_obj_down": "saobjLow", @@ -336,7 +336,7 @@ class GurobiModel(AbstractModel): dtype="S", ), ) - for (h5_field, gp_field) in { + for h5_field, gp_field in { "lp_constr_dual_values": "pi", "lp_constr_sa_rhs_up": "saRhsUp", "lp_constr_sa_rhs_down": "saRhsLow", diff --git a/miplearn/solvers/pyomo.py b/miplearn/solvers/pyomo.py index 55c819a..2cce5c5 100644 --- a/miplearn/solvers/pyomo.py +++ b/miplearn/solvers/pyomo.py @@ -141,7 +141,7 @@ class PyomoModel(AbstractModel): stats: Optional[Dict] = None, ) -> None: variables = self._var_names_to_vars(var_names) - for (var, val) in zip(variables, var_values): + for var, val in zip(variables, var_values): if np.isfinite(val): var.fix(val) self.solver.update_var(var) @@ -195,7 +195,7 @@ class PyomoModel(AbstractModel): assert var_names.shape[0] == n_vars assert n_starts == 1, "Pyomo does not support multiple warm starts" variables = self._var_names_to_vars(var_names) - for (var, val) in zip(variables, var_values[0, :]): + for var, val in zip(variables, var_values[0, :]): if np.isfinite(val): var.value = val self._is_warm_start_available = True @@ -215,7 +215,7 @@ class PyomoModel(AbstractModel): obj_count += 1 assert obj_count == 1, f"One objective function expected; found {obj_count}" - for (i, var) in enumerate(self.inner.component_objects(pyomo.core.Var)): + for i, var in enumerate(self.inner.component_objects(pyomo.core.Var)): for idx in var: v = var[idx] @@ -316,9 +316,7 @@ class PyomoModel(AbstractModel): raise Exception(f"Unknown expression type: {expr.__class__.__name__}") curr_row = 0 - for (i, constr) in enumerate( - self.inner.component_objects(pyomo.core.Constraint) - ): + for i, constr in enumerate(self.inner.component_objects(pyomo.core.Constraint)): if len(constr) > 1: for idx in constr: names.append(constr[idx].name) diff --git a/tests/components/cuts/test_mem.py b/tests/components/cuts/test_mem.py index 7bebfb0..4659f10 100644 --- a/tests/components/cuts/test_mem.py +++ b/tests/components/cuts/test_mem.py @@ -62,7 +62,7 @@ def test_usage_stab( stab_pyo_h5: List[str], default_extractor: FeaturesExtractor, ) -> None: - for (h5, build_model) in [ + for h5, build_model in [ (stab_pyo_h5, build_stab_model_pyomo), (stab_gp_h5, build_stab_model_gurobipy), ]: diff --git a/tests/components/lazy/test_mem.py b/tests/components/lazy/test_mem.py index 88b2a74..b3e484c 100644 --- a/tests/components/lazy/test_mem.py +++ b/tests/components/lazy/test_mem.py @@ -56,7 +56,7 @@ def test_usage_tsp( tsp_pyo_h5: List[str], default_extractor: FeaturesExtractor, ) -> None: - for (h5, build_model) in [ + for h5, build_model in [ (tsp_pyo_h5, build_tsp_model_pyomo), (tsp_gp_h5, build_tsp_model_gurobipy), ]: diff --git a/tests/problems/test_binpack.py b/tests/problems/test_binpack.py index 7ffe5ac..18cf7df 100644 --- a/tests/problems/test_binpack.py +++ b/tests/problems/test_binpack.py @@ -5,7 +5,11 @@ import numpy as np from scipy.stats import uniform, randint -from miplearn.problems.binpack import build_binpack_model, BinPackData, BinPackGenerator +from miplearn.problems.binpack import ( + build_binpack_model_gurobipy, + BinPackData, + BinPackGenerator, +) def test_binpack_generator() -> None: @@ -48,7 +52,7 @@ def test_binpack_generator() -> None: def test_binpack() -> None: - model = build_binpack_model( + model = build_binpack_model_gurobipy( BinPackData( sizes=np.array([4, 8, 1, 4, 2, 1]), capacity=10, diff --git a/tests/problems/test_multiknapsack.py b/tests/problems/test_multiknapsack.py index 2a86338..5ddd06f 100644 --- a/tests/problems/test_multiknapsack.py +++ b/tests/problems/test_multiknapsack.py @@ -8,7 +8,7 @@ from scipy.stats import uniform, randint from miplearn.problems.multiknapsack import ( MultiKnapsackGenerator, MultiKnapsackData, - build_multiknapsack_model, + build_multiknapsack_model_gurobipy, ) @@ -56,6 +56,6 @@ def test_knapsack_model() -> None: ] ), ) - model = build_multiknapsack_model(data) + model = build_multiknapsack_model_gurobipy(data) model.optimize() assert model.inner.objVal == -460.0 diff --git a/tests/problems/test_pmedian.py b/tests/problems/test_pmedian.py index 4e4d40f..0781c56 100644 --- a/tests/problems/test_pmedian.py +++ b/tests/problems/test_pmedian.py @@ -5,7 +5,7 @@ import numpy as np from scipy.stats import uniform, randint -from miplearn.problems.pmedian import PMedianGenerator, build_pmedian_model +from miplearn.problems.pmedian import PMedianGenerator, build_pmedian_model_gurobipy def test_pmedian() -> None: @@ -46,7 +46,7 @@ def test_pmedian() -> None: [31.95, 17.05, 67.62, 58.88, 0.0], ] - model = build_pmedian_model(data[0]) + model = build_pmedian_model_gurobipy(data[0]) assert model.inner.numVars == 30 assert model.inner.numConstrs == 11 model.optimize() diff --git a/tests/problems/test_setpack.py b/tests/problems/test_setpack.py index 4ef0dd9..8f41810 100644 --- a/tests/problems/test_setpack.py +++ b/tests/problems/test_setpack.py @@ -6,7 +6,7 @@ import numpy as np from miplearn.problems.setpack import ( SetPackData, - build_setpack_model, + build_setpack_model_gurobipy, ) @@ -21,6 +21,6 @@ def test_setpack() -> None: ], ), ) - model = build_setpack_model(data) + model = build_setpack_model_gurobipy(data) model.optimize() assert model.inner.objval == -22.0 diff --git a/tests/problems/test_uc.py b/tests/problems/test_uc.py index d27d8fb..a730540 100644 --- a/tests/problems/test_uc.py +++ b/tests/problems/test_uc.py @@ -7,7 +7,7 @@ from scipy.stats import uniform, randint from miplearn.problems.uc import ( UnitCommitmentData, - build_uc_model, + build_uc_model_gurobipy, UnitCommitmentGenerator, ) @@ -60,12 +60,12 @@ def test_uc() -> None: cost_prod=np.array([1.0, 1.25, 1.5]), cost_fixed=np.array([10, 12, 9]), ) - model = build_uc_model(data) + model = build_uc_model_gurobipy(data) model.optimize() assert model.inner.objVal == 154.5 if __name__ == "__main__": data = UnitCommitmentGenerator().generate(1)[0] - model = build_uc_model(data) + model = build_uc_model_gurobipy(data) model.optimize() diff --git a/tests/problems/test_vertexcover.py b/tests/problems/test_vertexcover.py index 327d6bd..1140bd7 100644 --- a/tests/problems/test_vertexcover.py +++ b/tests/problems/test_vertexcover.py @@ -7,7 +7,7 @@ import numpy as np from miplearn.problems.vertexcover import ( MinWeightVertexCoverData, - build_vertexcover_model, + build_vertexcover_model_gurobipy, ) @@ -16,6 +16,6 @@ def test_stab() -> None: graph=nx.cycle_graph(5), weights=np.array([1.0, 1.0, 1.0, 1.0, 1.0]), ) - model = build_vertexcover_model(data) + model = build_vertexcover_model_gurobipy(data) model.optimize() assert model.inner.objVal == 3.0