Add _gurobipy suffix to all build_model functions

dev
Alinson S. Xavier 2 years ago
parent fb3f219ea8
commit b55554d410

@ -183,7 +183,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 2,
"id": "ac6f8c6f", "id": "ac6f8c6f",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {

@ -101,7 +101,7 @@
"from miplearn.io import write_pkl_gz\n", "from miplearn.io import write_pkl_gz\n",
"from miplearn.problems.multiknapsack import (\n", "from miplearn.problems.multiknapsack import (\n",
" MultiKnapsackGenerator,\n", " MultiKnapsackGenerator,\n",
" build_multiknapsack_model,\n", " build_multiknapsack_model_gurobipy,\n",
")\n", ")\n",
"\n", "\n",
"# Set random seed to make example reproducible\n", "# Set random seed to make example reproducible\n",
@ -127,7 +127,7 @@
"# Run the basic collector\n", "# Run the basic collector\n",
"BasicCollector().collect(\n", "BasicCollector().collect(\n",
" glob(\"data/multiknapsack/*\"),\n", " glob(\"data/multiknapsack/*\"),\n",
" build_multiknapsack_model,\n", " build_multiknapsack_model_gurobipy,\n",
" n_jobs=4,\n", " n_jobs=4,\n",
")\n", ")\n",
"\n", "\n",

@ -39,7 +39,6 @@
"cell_type": "markdown", "cell_type": "markdown",
"id": "830f3784-a3fc-4e2f-a484-e7808841ffe8", "id": "830f3784-a3fc-4e2f-a484-e7808841ffe8",
"metadata": { "metadata": {
"jp-MarkdownHeadingCollapsed": true,
"tags": [] "tags": []
}, },
"source": [ "source": [
@ -159,20 +158,22 @@
"H 0 0 2.0000000 1.27484 36.3% - 0s\n", "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", " 0 0 1.27484 0 4 2.00000 1.27484 36.3% - 0s\n",
"\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", "Thread count was 20 (of 20 available processors)\n",
"\n", "\n",
"Solution count 3: 2 4 5 \n", "Solution count 3: 2 4 5 \n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from scipy.stats import uniform, randint\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", "\n",
"# Set random seed, to make example reproducible\n", "# Set random seed, to make example reproducible\n",
"np.random.seed(42)\n", "np.random.seed(42)\n",
@ -193,7 +194,7 @@
"print()\n", "print()\n",
"\n", "\n",
"# Optimize first instance\n", "# Optimize first instance\n",
"model = build_binpack_model(data[0])\n", "model = build_binpack_model_gurobipy(data[0])\n",
"model.optimize()" "model.optimize()"
] ]
}, },
@ -360,7 +361,9 @@
"No other solutions better than -1279\n", "No other solutions better than -1279\n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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 scipy.stats import uniform, randint\n",
"from miplearn.problems.multiknapsack import (\n", "from miplearn.problems.multiknapsack import (\n",
" MultiKnapsackGenerator,\n", " MultiKnapsackGenerator,\n",
" build_multiknapsack_model,\n", " build_multiknapsack_model_gurobipy,\n",
")\n", ")\n",
"\n", "\n",
"# Set random seed, to make example reproducible\n", "# Set random seed, to make example reproducible\n",
@ -396,7 +399,7 @@
"print()\n", "print()\n",
"\n", "\n",
"# Build model and optimize\n", "# Build model and optimize\n",
"model = build_multiknapsack_model(data[0])\n", "model = build_multiknapsack_model_gurobipy(data[0])\n",
"model.optimize()" "model.optimize()"
] ]
}, },
@ -535,20 +538,22 @@
" 0 0 86.06884 0 15 93.92000 86.06884 8.36% - 0s\n", " 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", "* 0 0 0 91.2300000 91.23000 0.00% - 0s\n",
"\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", "Thread count was 20 (of 20 available processors)\n",
"\n", "\n",
"Solution count 10: 91.23 93.92 93.98 ... 368.79\n", "Solution count 10: 91.23 93.92 93.98 ... 368.79\n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from scipy.stats import uniform, randint\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", "\n",
"# Set random seed, to make example reproducible\n", "# Set random seed, to make example reproducible\n",
"np.random.seed(42)\n", "np.random.seed(42)\n",
@ -576,7 +581,7 @@
"print()\n", "print()\n",
"\n", "\n",
"# Build and optimize model\n", "# Build and optimize model\n",
"model = build_pmedian_model(data[0])\n", "model = build_pmedian_model_gurobipy(data[0])\n",
"model.optimize()" "model.optimize()"
] ]
}, },
@ -694,7 +699,9 @@
"Solution count 1: 213.49 \n", "Solution count 1: 213.49 \n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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", "No other solutions better than -1986.37\n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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": [ "source": [
"import numpy as np\n", "import numpy as np\n",
"from scipy.stats import uniform, randint\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", "\n",
"# Set random seed, to make example reproducible\n", "# Set random seed, to make example reproducible\n",
"np.random.seed(42)\n", "np.random.seed(42)\n",
@ -865,7 +874,7 @@
"print()\n", "print()\n",
"\n", "\n",
"# Build and optimize model\n", "# Build and optimize model\n",
"model = build_setpack_model(data[0])\n", "model = build_setpack_model_gurobipy(data[0])\n",
"model.optimize()" "model.optimize()"
] ]
}, },
@ -1374,13 +1383,15 @@
" RLT: 1\n", " RLT: 1\n",
" Relax-and-lift: 7\n", " Relax-and-lift: 7\n",
"\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", "Thread count was 20 (of 20 available processors)\n",
"\n", "\n",
"Solution count 5: 364722 368600 374044 ... 440662\n", "Solution count 5: 364722 368600 374044 ... 440662\n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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 random\n",
"import numpy as np\n", "import numpy as np\n",
"from scipy.stats import uniform, randint\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", "\n",
"# Set random seed to make example reproducible\n", "# Set random seed to make example reproducible\n",
"random.seed(42)\n", "random.seed(42)\n",
@ -1424,7 +1435,7 @@
" print()\n", " print()\n",
"\n", "\n",
"# Load and optimize the first instance\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()" "model.optimize()"
] ]
}, },
@ -1532,7 +1543,9 @@
"Solution count 1: 301 \n", "Solution count 1: 301 \n",
"\n", "\n",
"Optimal solution found (tolerance 1.00e-04)\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 scipy.stats import uniform, randint\n",
"from miplearn.problems.vertexcover import (\n", "from miplearn.problems.vertexcover import (\n",
" MinWeightVertexCoverGenerator,\n", " MinWeightVertexCoverGenerator,\n",
" build_vertexcover_model,\n", " build_vertexcover_model_gurobipy,\n",
")\n", ")\n",
"\n", "\n",
"# Set random seed to make example reproducible\n", "# Set random seed to make example reproducible\n",
@ -1565,26 +1578,9 @@
"print()\n", "print()\n",
"\n", "\n",
"# Load and optimize the first instance\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()" "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": { "metadata": {

@ -92,6 +92,8 @@
"\n", "\n",
"Solved in 15 iterations and 0.00 seconds (0.00 work units)\n", "Solved in 15 iterations and 0.00 seconds (0.00 work units)\n",
"Optimal objective 2.761000000e+03\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 PreCrush to value 1\n",
"Set parameter LazyConstraints to value 1\n", "Set parameter LazyConstraints to value 1\n",
"Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (linux64)\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (linux64)\n",

@ -87,8 +87,10 @@
"\n", "\n",
"# Set up Python logging\n", "# Set up Python logging\n",
"import logging\n", "import logging\n",
"\n",
"logging.basicConfig(level=logging.WARNING)\n", "logging.basicConfig(level=logging.WARNING)\n",
"\n", "\n",
"\n",
"def build_tsp_model_gurobipy_simplified(data):\n", "def build_tsp_model_gurobipy_simplified(data):\n",
" # Read data from file if a filename is provided\n", " # Read data from file if a filename is provided\n",
" if isinstance(data, str):\n", " if isinstance(data, str):\n",
@ -99,9 +101,7 @@
"\n", "\n",
" # Create set of edges between every pair of cities, for convenience\n", " # Create set of edges between every pair of cities, for convenience\n",
" edges = tuplelist(\n", " edges = tuplelist(\n",
" (i, j)\n", " (i, j) for i in range(data.n_cities) for j in range(i + 1, data.n_cities)\n",
" for i in range(data.n_cities)\n",
" for j in range(i + 1, data.n_cities)\n",
" )\n", " )\n",
"\n", "\n",
" # Add binary variable x[e] for each edge e\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", " # Add constraint: must choose two edges adjacent to each city\n",
" model.addConstrs(\n", " model.addConstrs(\n",
" (\n", " (\n",
" quicksum(\n", " quicksum(x[min(i, j), max(i, j)] for j in range(data.n_cities) if i != j)\n",
" x[min(i, j), max(i, j)]\n", " == 2\n",
" for j in range(data.n_cities)\n",
" if i != j\n",
" ) == 2\n",
" for i in range(data.n_cities)\n", " for i in range(data.n_cities)\n",
" ),\n", " ),\n",
" name=\"eq_degree\",\n", " name=\"eq_degree\",\n",
@ -129,7 +126,7 @@
" \"\"\"\n", " \"\"\"\n",
" # Query current value of the x variables\n", " # Query current value of the x variables\n",
" x_val = m.inner.cbGetSolution(x)\n", " x_val = m.inner.cbGetSolution(x)\n",
" \n", "\n",
" # Initialize empty set of violations\n", " # Initialize empty set of violations\n",
" violations = []\n", " violations = []\n",
"\n", "\n",
@ -164,9 +161,7 @@
" \"\"\"\n", " \"\"\"\n",
" print(f\"Enforcing {len(violations)} subtour elimination constraints\")\n", " print(f\"Enforcing {len(violations)} subtour elimination constraints\")\n",
" for violation in violations:\n", " for violation in violations:\n",
" m.add_constr(\n", " m.add_constr(quicksum(x[e[0], e[1]] for e in violation) >= 2)\n",
" quicksum(x[e[0], e[1]] for e in violation) >= 2\n",
" )\n",
"\n", "\n",
" return GurobiModel(\n", " return GurobiModel(\n",
" model,\n", " model,\n",

@ -54,7 +54,7 @@ class MinProbabilityClassifier(BaseEstimator):
y_pred = [] y_pred = []
for sample_idx in range(n_samples): for sample_idx in range(n_samples):
yi = float("nan") 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]: if y_proba[sample_idx, class_idx] >= self.thresholds[class_idx]:
yi = class_val yi = class_val
y_pred.append(yi) y_pred.append(yi)

@ -71,7 +71,7 @@ class EnforceProximity(PrimalComponentAction):
constr_lhs = [] constr_lhs = []
constr_vars = [] constr_vars = []
constr_rhs = 0.0 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]): if np.isnan(var_values[i]):
continue continue
constr_lhs.append(1.0 if var_values[i] < 0.5 else -1.0) constr_lhs.append(1.0 if var_values[i] < 0.5 else -1.0)

@ -91,7 +91,7 @@ class IndependentVarsPrimalComponent:
logger.info(f"Training {n_bin_vars} classifiers...") logger.info(f"Training {n_bin_vars} classifiers...")
self.clf_ = {} 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] = self.clone_fn(self.base_clf)
self.clf_[var_name].fit( self.clf_[var_name].fit(
x_np[var_idx::n_bin_vars, :], y_np[var_idx::n_bin_vars] x_np[var_idx::n_bin_vars, :], y_np[var_idx::n_bin_vars]
@ -117,7 +117,7 @@ class IndependentVarsPrimalComponent:
# Predict optimal solution # Predict optimal solution
logger.info("Predicting warm starts...") logger.info("Predicting warm starts...")
y_pred = [] 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) x_var = x_sample[var_idx, :].reshape(1, -1)
y_var = self.clf_[var_name].predict(x_var) y_var = self.clf_[var_name].predict(x_var)
assert y_var.shape == (1,) assert y_var.shape == (1,)

@ -25,7 +25,7 @@ class ExpertBranchPriorityComponent:
assert var_priority is not None assert var_priority is not None
assert var_names 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]): if np.isfinite(var_priority[var_idx]):
var = model.getVarByName(var_name.decode()) var = model.getVarByName(var_name.decode())
var.branchPriority = int(log(1 + var_priority[var_idx])) var.branchPriority = int(log(1 + var_priority[var_idx]))

@ -11,7 +11,7 @@ from pyomo import environ as pe
def _gurobipy_set_params(model: gp.Model, params: Optional[dict[str, Any]]) -> None: def _gurobipy_set_params(model: gp.Model, params: Optional[dict[str, Any]]) -> None:
assert isinstance(model, gp.Model) assert isinstance(model, gp.Model)
if params is not None: 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) setattr(model.params, param_name, param_value)
@ -24,5 +24,5 @@ def _pyomo_set_params(
solver == "gurobi_persistent" solver == "gurobi_persistent"
), "setting parameters is only supported with gurobi_persistent" ), "setting parameters is only supported with gurobi_persistent"
if solver == "gurobi_persistent" and params is not None: 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) model.solver.set_gurobi_param(param_name, param_value)

@ -109,7 +109,7 @@ class BinPackGenerator:
return [_sample() for n in range(n_samples)] 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.""" """Converts bin packing problem data into a concrete Gurobipy model."""
if isinstance(data, str): if isinstance(data, str):
data = read_pkl_gz(data) data = read_pkl_gz(data)

@ -174,7 +174,9 @@ class MultiKnapsackGenerator:
return [_sample() for _ in range(n_samples)] 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.""" """Converts multi-knapsack problem data into a concrete Gurobipy model."""
if isinstance(data, str): if isinstance(data, str):
data = read_pkl_gz(data) data = read_pkl_gz(data)

@ -141,7 +141,7 @@ class PMedianGenerator:
return [_sample() for _ in range(n_samples)] 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.""" """Converts capacitated p-median data into a concrete Gurobipy model."""
if isinstance(data, str): if isinstance(data, str):
data = read_pkl_gz(data) data = read_pkl_gz(data)

@ -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): if isinstance(data, str):
data = read_pkl_gz(data) data = read_pkl_gz(data)
assert isinstance(data, SetPackData) assert isinstance(data, SetPackData)

@ -101,7 +101,7 @@ def build_stab_model_gurobipy(
model.setObjective(quicksum(-data.weights[i] * x[i] for i in nodes)) model.setObjective(quicksum(-data.weights[i] * x[i] for i in nodes))
# Edge inequalities # Edge inequalities
for (i1, i2) in data.graph.edges: for i1, i2 in data.graph.edges:
model.addConstr(x[i1] + x[i2] <= 1) model.addConstr(x[i1] + x[i2] <= 1)
def cuts_separate(m: GurobiModel) -> List[Hashable]: def cuts_separate(m: GurobiModel) -> List[Hashable]:
@ -137,7 +137,7 @@ def build_stab_model_pyomo(
# Edge inequalities # Edge inequalities
model.edge_eqs = pe.ConstraintList() 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) model.edge_eqs.add(model.x[i1] + model.x[i2] <= 1)
# Clique inequalities # Clique inequalities

@ -119,7 +119,6 @@ def build_tsp_model_gurobipy(
data: Union[str, TravelingSalesmanData], data: Union[str, TravelingSalesmanData],
params: Optional[dict[str, Any]] = None, params: Optional[dict[str, Any]] = None,
) -> GurobiModel: ) -> GurobiModel:
model = gp.Model() model = gp.Model()
_gurobipy_set_params(model, params) _gurobipy_set_params(model, params)
@ -173,7 +172,6 @@ def build_tsp_model_pyomo(
solver: str = "gurobi_persistent", solver: str = "gurobi_persistent",
params: Optional[dict[str, Any]] = None, params: Optional[dict[str, Any]] = None,
) -> PyomoModel: ) -> PyomoModel:
model = pe.ConcreteModel() model = pe.ConcreteModel()
data = _tsp_read(data) data = _tsp_read(data)

@ -112,7 +112,7 @@ class UnitCommitmentGenerator:
return [_sample() for _ in range(n_samples)] 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: Models the unit commitment problem according to equations (1)-(5) of:

@ -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): if isinstance(data, str):
data = read_pkl_gz(data) data = read_pkl_gz(data)
assert isinstance(data, MinWeightVertexCoverData) assert isinstance(data, MinWeightVertexCoverData)
@ -48,7 +50,7 @@ def build_vertexcover_model(data: Union[str, MinWeightVertexCoverData]) -> Gurob
nodes = list(data.graph.nodes) nodes = list(data.graph.nodes)
x = model.addVars(nodes, vtype=GRB.BINARY, name="x") x = model.addVars(nodes, vtype=GRB.BINARY, name="x")
model.setObjective(quicksum(data.weights[i] * x[i] for i in nodes)) 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.addConstr(x[v1] + x[v2] >= 1)
model.update() model.update()
return GurobiModel(model) return GurobiModel(model)

@ -184,7 +184,7 @@ class GurobiModel(AbstractModel):
assert var_names.shape == var_values.shape assert var_names.shape == var_values.shape
n_fixed = 0 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] var_val = var_values[var_idx]
if np.isfinite(var_val): if np.isfinite(var_val):
var = self.inner.getVarByName(var_name.decode()) var = self.inner.getVarByName(var_name.decode())
@ -229,7 +229,7 @@ class GurobiModel(AbstractModel):
self.inner.numStart = n_starts self.inner.numStart = n_starts
for start_idx in range(n_starts): for start_idx in range(n_starts):
self.inner.params.startNumber = start_idx 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] var_val = var_values[start_idx, var_idx]
if np.isfinite(var_val): if np.isfinite(var_val):
var = self.inner.getVarByName(var_name.decode()) var = self.inner.getVarByName(var_name.decode())
@ -243,14 +243,14 @@ class GurobiModel(AbstractModel):
def _extract_after_load_vars(self, h5: H5File) -> None: def _extract_after_load_vars(self, h5: H5File) -> None:
gp_vars = self.inner.getVars() gp_vars = self.inner.getVars()
for (h5_field, gp_field) in { for h5_field, gp_field in {
"static_var_names": "varName", "static_var_names": "varName",
"static_var_types": "vtype", "static_var_types": "vtype",
}.items(): }.items():
h5.put_array( h5.put_array(
h5_field, np.array(self.inner.getAttr(gp_field, gp_vars), dtype="S") 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_upper_bounds": "ub",
"static_var_lower_bounds": "lb", "static_var_lower_bounds": "lb",
"static_var_obj_coeffs": "obj", "static_var_obj_coeffs": "obj",
@ -267,7 +267,7 @@ class GurobiModel(AbstractModel):
names = np.array(self.inner.getAttr("constrName", gp_constrs), dtype="S") names = np.array(self.inner.getAttr("constrName", gp_constrs), dtype="S")
nrows, ncols = len(gp_constrs), len(gp_vars) nrows, ncols = len(gp_constrs), len(gp_vars)
tmp = lil_matrix((nrows, ncols), dtype=float) 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) expr = self.inner.getRow(gp_constr)
for j in range(expr.size()): for j in range(expr.size()):
tmp[i, expr.getVar(j).index] = expr.getCoeff(j) tmp[i, expr.getVar(j).index] = expr.getCoeff(j)
@ -302,7 +302,7 @@ class GurobiModel(AbstractModel):
dtype="S", dtype="S",
), ),
) )
for (h5_field, gp_field) in { for h5_field, gp_field in {
"lp_var_reduced_costs": "rc", "lp_var_reduced_costs": "rc",
"lp_var_sa_obj_up": "saobjUp", "lp_var_sa_obj_up": "saobjUp",
"lp_var_sa_obj_down": "saobjLow", "lp_var_sa_obj_down": "saobjLow",
@ -336,7 +336,7 @@ class GurobiModel(AbstractModel):
dtype="S", dtype="S",
), ),
) )
for (h5_field, gp_field) in { for h5_field, gp_field in {
"lp_constr_dual_values": "pi", "lp_constr_dual_values": "pi",
"lp_constr_sa_rhs_up": "saRhsUp", "lp_constr_sa_rhs_up": "saRhsUp",
"lp_constr_sa_rhs_down": "saRhsLow", "lp_constr_sa_rhs_down": "saRhsLow",

@ -141,7 +141,7 @@ class PyomoModel(AbstractModel):
stats: Optional[Dict] = None, stats: Optional[Dict] = None,
) -> None: ) -> None:
variables = self._var_names_to_vars(var_names) 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): if np.isfinite(val):
var.fix(val) var.fix(val)
self.solver.update_var(var) self.solver.update_var(var)
@ -195,7 +195,7 @@ class PyomoModel(AbstractModel):
assert var_names.shape[0] == n_vars assert var_names.shape[0] == n_vars
assert n_starts == 1, "Pyomo does not support multiple warm starts" assert n_starts == 1, "Pyomo does not support multiple warm starts"
variables = self._var_names_to_vars(var_names) 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): if np.isfinite(val):
var.value = val var.value = val
self._is_warm_start_available = True self._is_warm_start_available = True
@ -215,7 +215,7 @@ class PyomoModel(AbstractModel):
obj_count += 1 obj_count += 1
assert obj_count == 1, f"One objective function expected; found {obj_count}" 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: for idx in var:
v = var[idx] v = var[idx]
@ -316,9 +316,7 @@ class PyomoModel(AbstractModel):
raise Exception(f"Unknown expression type: {expr.__class__.__name__}") raise Exception(f"Unknown expression type: {expr.__class__.__name__}")
curr_row = 0 curr_row = 0
for (i, constr) in enumerate( for i, constr in enumerate(self.inner.component_objects(pyomo.core.Constraint)):
self.inner.component_objects(pyomo.core.Constraint)
):
if len(constr) > 1: if len(constr) > 1:
for idx in constr: for idx in constr:
names.append(constr[idx].name) names.append(constr[idx].name)

@ -62,7 +62,7 @@ def test_usage_stab(
stab_pyo_h5: List[str], stab_pyo_h5: List[str],
default_extractor: FeaturesExtractor, default_extractor: FeaturesExtractor,
) -> None: ) -> None:
for (h5, build_model) in [ for h5, build_model in [
(stab_pyo_h5, build_stab_model_pyomo), (stab_pyo_h5, build_stab_model_pyomo),
(stab_gp_h5, build_stab_model_gurobipy), (stab_gp_h5, build_stab_model_gurobipy),
]: ]:

@ -56,7 +56,7 @@ def test_usage_tsp(
tsp_pyo_h5: List[str], tsp_pyo_h5: List[str],
default_extractor: FeaturesExtractor, default_extractor: FeaturesExtractor,
) -> None: ) -> None:
for (h5, build_model) in [ for h5, build_model in [
(tsp_pyo_h5, build_tsp_model_pyomo), (tsp_pyo_h5, build_tsp_model_pyomo),
(tsp_gp_h5, build_tsp_model_gurobipy), (tsp_gp_h5, build_tsp_model_gurobipy),
]: ]:

@ -5,7 +5,11 @@
import numpy as np import numpy as np
from scipy.stats import uniform, randint 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: def test_binpack_generator() -> None:
@ -48,7 +52,7 @@ def test_binpack_generator() -> None:
def test_binpack() -> None: def test_binpack() -> None:
model = build_binpack_model( model = build_binpack_model_gurobipy(
BinPackData( BinPackData(
sizes=np.array([4, 8, 1, 4, 2, 1]), sizes=np.array([4, 8, 1, 4, 2, 1]),
capacity=10, capacity=10,

@ -8,7 +8,7 @@ from scipy.stats import uniform, randint
from miplearn.problems.multiknapsack import ( from miplearn.problems.multiknapsack import (
MultiKnapsackGenerator, MultiKnapsackGenerator,
MultiKnapsackData, 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() model.optimize()
assert model.inner.objVal == -460.0 assert model.inner.objVal == -460.0

@ -5,7 +5,7 @@
import numpy as np import numpy as np
from scipy.stats import uniform, randint 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: def test_pmedian() -> None:
@ -46,7 +46,7 @@ def test_pmedian() -> None:
[31.95, 17.05, 67.62, 58.88, 0.0], [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.numVars == 30
assert model.inner.numConstrs == 11 assert model.inner.numConstrs == 11
model.optimize() model.optimize()

@ -6,7 +6,7 @@ import numpy as np
from miplearn.problems.setpack import ( from miplearn.problems.setpack import (
SetPackData, 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() model.optimize()
assert model.inner.objval == -22.0 assert model.inner.objval == -22.0

@ -7,7 +7,7 @@ from scipy.stats import uniform, randint
from miplearn.problems.uc import ( from miplearn.problems.uc import (
UnitCommitmentData, UnitCommitmentData,
build_uc_model, build_uc_model_gurobipy,
UnitCommitmentGenerator, UnitCommitmentGenerator,
) )
@ -60,12 +60,12 @@ def test_uc() -> None:
cost_prod=np.array([1.0, 1.25, 1.5]), cost_prod=np.array([1.0, 1.25, 1.5]),
cost_fixed=np.array([10, 12, 9]), cost_fixed=np.array([10, 12, 9]),
) )
model = build_uc_model(data) model = build_uc_model_gurobipy(data)
model.optimize() model.optimize()
assert model.inner.objVal == 154.5 assert model.inner.objVal == 154.5
if __name__ == "__main__": if __name__ == "__main__":
data = UnitCommitmentGenerator().generate(1)[0] data = UnitCommitmentGenerator().generate(1)[0]
model = build_uc_model(data) model = build_uc_model_gurobipy(data)
model.optimize() model.optimize()

@ -7,7 +7,7 @@ import numpy as np
from miplearn.problems.vertexcover import ( from miplearn.problems.vertexcover import (
MinWeightVertexCoverData, MinWeightVertexCoverData,
build_vertexcover_model, build_vertexcover_model_gurobipy,
) )
@ -16,6 +16,6 @@ def test_stab() -> None:
graph=nx.cycle_graph(5), graph=nx.cycle_graph(5),
weights=np.array([1.0, 1.0, 1.0, 1.0, 1.0]), 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() model.optimize()
assert model.inner.objVal == 3.0 assert model.inner.objVal == 3.0

Loading…
Cancel
Save