Compare commits

...

2 Commits

@ -14,7 +14,7 @@
</a> </a>
</p> </p>
**MIPLearn** is an extensible framework for solving discrete optimization problems using a combination of Mixed-Integer Linear Programming (MIP) and Machine Learning (ML). MIPLearn uses ML methods to automatically identify patterns in previously solved instances of the problem, then uses these patterns to accelerate the performance of conventional state-of-the-art MIP solvers such as CPLEX, Gurobi or XPRESS. **MIPLearn** is an extensible framework for solving discrete optimization problems using a combination of Mixed-Integer Programming (MIP) and Machine Learning (ML). MIPLearn uses ML methods to automatically identify patterns in previously solved instances of the problem, then uses these patterns to accelerate the performance of conventional state-of-the-art MIP solvers such as CPLEX, Gurobi or XPRESS.
Unlike pure ML methods, MIPLearn is not only able to find high-quality solutions to discrete optimization problems, but it can also prove the optimality and feasibility of these solutions. Unlike conventional MIP solvers, MIPLearn can take full advantage of very specific observations that happen to be true in a particular family of instances (such as the observation that a particular constraint is typically redundant, or that a particular variable typically assumes a certain value). For certain classes of problems, this approach may provide significant performance benefits. Unlike pure ML methods, MIPLearn is not only able to find high-quality solutions to discrete optimization problems, but it can also prove the optimality and feasibility of these solutions. Unlike conventional MIP solvers, MIPLearn can take full advantage of very specific observations that happen to be true in a particular family of instances (such as the observation that a particular constraint is typically redundant, or that a particular variable typically assumes a certain value). For certain classes of problems, this approach may provide significant performance benefits.

@ -118,3 +118,13 @@ table tr:last-child {
border-bottom: 0; border-bottom: 0;
} }
@media (min-width: 960px) {
.bd-page-width {
max-width: 100rem;
}
}
.bd-sidebar-primary .sidebar-primary-items__end {
margin-bottom: 0;
margin-top: 0;
}

@ -55,3 +55,9 @@ miplearn.problems.vertexcover
.. automodule:: miplearn.problems.vertexcover .. automodule:: miplearn.problems.vertexcover
:members: :members:
miplearn.problems.maxcut
-----------------------------
.. automodule:: miplearn.problems.maxcut
:members:

@ -696,7 +696,7 @@
"Presolve time: 0.00s\n", "Presolve time: 0.00s\n",
"Presolve: All rows and columns removed\n", "Presolve: All rows and columns removed\n",
"\n", "\n",
"Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)\n", "Explored 0 nodes (0 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 1 (of 32 available processors)\n", "Thread count was 1 (of 32 available processors)\n",
"\n", "\n",
"Solution count 1: 213.49 \n", "Solution count 1: 213.49 \n",
@ -846,7 +846,7 @@
"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", "\n",
"User-callback calls 245, time in user-callback 0.00 sec\n" "User-callback calls 244, time in user-callback 0.00 sec\n"
] ]
} }
], ],
@ -975,7 +975,7 @@
"\n", "\n",
" 0 0 infeasible 0 -219.14000 -219.14000 0.00% - 0s\n", " 0 0 infeasible 0 -219.14000 -219.14000 0.00% - 0s\n",
"\n", "\n",
"Explored 1 nodes (5 simplex iterations) in 0.02 seconds (0.00 work units)\n", "Explored 1 nodes (5 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 32 (of 32 available processors)\n", "Thread count was 32 (of 32 available processors)\n",
"\n", "\n",
"Solution count 1: -219.14 \n", "Solution count 1: -219.14 \n",
@ -984,7 +984,7 @@
"Optimal solution found (tolerance 1.00e-04)\n", "Optimal solution found (tolerance 1.00e-04)\n",
"Best objective -2.191400000000e+02, best bound -2.191400000000e+02, gap 0.0000%\n", "Best objective -2.191400000000e+02, best bound -2.191400000000e+02, gap 0.0000%\n",
"\n", "\n",
"User-callback calls 304, time in user-callback 0.01 sec\n" "User-callback calls 303, time in user-callback 0.00 sec\n"
] ]
} }
], ],
@ -1168,7 +1168,7 @@
"Optimal solution found (tolerance 1.00e-04)\n", "Optimal solution found (tolerance 1.00e-04)\n",
"Best objective 2.921000000000e+03, best bound 2.921000000000e+03, gap 0.0000%\n", "Best objective 2.921000000000e+03, best bound 2.921000000000e+03, gap 0.0000%\n",
"\n", "\n",
"User-callback calls 112, time in user-callback 0.00 sec\n" "User-callback calls 111, time in user-callback 0.00 sec\n"
] ]
} }
], ],
@ -1221,7 +1221,6 @@
"id": "7048d771", "id": "7048d771",
"metadata": {}, "metadata": {},
"source": [ "source": [
"\n",
"<div class=\"alert alert-info\">\n", "<div class=\"alert alert-info\">\n",
"Note\n", "Note\n",
"\n", "\n",
@ -1230,7 +1229,7 @@
"\n", "\n",
"### Formulation\n", "### Formulation\n",
"\n", "\n",
"Let $T$ be the number of time steps, $G$ be the number of generation units, and let $D_t$ be the power demand (in MW) at time $t$. For each generating unit $g$, let $P^\\max_g$ and $P^\\min_g$ be the maximum and minimum amount of power the unit is able to produce when switched on; let $L_g$ and $l_g$ be the minimum up- and down-time for unit $g$; let $C^\\text{fixed}$ be the cost to keep unit $g$ on for one time step, regardless of its power output level; let $C^\\text{start}$ be the cost to switch unit $g$ on; and let $C^\\text{var}$ be the cost for generator $g$ to produce 1 MW of power. In this formulation, we assume linear production costs. For each generator $g$ and time $t$, let $x_{gt}$ be a binary variable which equals one if unit $g$ is on at time $t$, let $w_{gt}$ be a binary variable which equals one if unit $g$ switches from being off at time $t-1$ to being on at time $t$, and let $p_{gt}$ be a continuous variable which indicates the amount of power generated. The formulation is given by:" "Let $T$ be the number of time steps, $G$ be the number of generation units, and let $D_t$ be the power demand (in MW) at time $t$. For each generating unit $g$, let $P^\\max_g$ and $P^\\min_g$ be the maximum and minimum amount of power the unit is able to produce when switched on; let $L_g$ and $l_g$ be the minimum up- and down-time for unit $g$; let $C^\\text{fixed}$ be the cost to keep unit $g$ on for one time step, regardless of its power output level; let $C^\\text{start}$ be the cost to switch unit $g$ on; let $C^\\text{prod-lin}$ be the linear cost coefficient for generator $g$ to produce 1 MW of power; and let $C^\\text{prod-quad}$ be the quadratic cost coefficient for unit $g$. For each generator $g$ and time $t$, let $x_{gt}$ be a binary variable which equals one if unit $g$ is on at time $t$, let $w_{gt}$ be a binary variable which equals one if unit $g$ switches from being off at time $t-1$ to being on at time $t$, and let $p_{gt}$ be a continuous variable which indicates the amount of power generated. The formulation is given by:"
] ]
}, },
{ {
@ -1238,14 +1237,14 @@
"id": "bec5ee1c", "id": "bec5ee1c",
"metadata": {}, "metadata": {},
"source": [ "source": [
"\n",
"$$\n", "$$\n",
"\\begin{align*}\n", "\\begin{align*}\n",
"\\text{minimize} \\;\\;\\;\n", "\\text{minimize} \\;\\;\\;\n",
" & \\sum_{t=1}^T \\sum_{g=1}^G \\left(\n", " & \\sum_{t=1}^T \\sum_{g=1}^G \\left(\n",
" x_{gt} C^\\text{fixed}_g\n", " x_{gt} C^\\text{fixed}_g\n",
" + w_{gt} C^\\text{start}_g\n", " + w_{gt} C^\\text{start}_g\n",
" + p_{gt} C^\\text{var}_g\n", " + p_{gt} C^\\text{prod-lin}_g\n",
" + p_{gt}^2 C^\\text{prod-quad}_g\n",
" \\right)\n", " \\right)\n",
" \\\\\n", " \\\\\n",
"\\text{such that} \\;\\;\\;\n", "\\text{such that} \\;\\;\\;\n",
@ -1287,12 +1286,11 @@
"id": "01bed9fc", "id": "01bed9fc",
"metadata": {}, "metadata": {},
"source": [ "source": [
"\n",
"### Random instance generator\n", "### Random instance generator\n",
"\n", "\n",
"The class `UnitCommitmentGenerator` can be used to generate random instances of this problem.\n", "The class `UnitCommitmentGenerator` can be used to generate random instances of this problem.\n",
"\n", "\n",
"First, the user-provided probability distributions `n_units` and `n_periods` are sampled to determine the number of generating units and the number of time steps, respectively. Then, for each unit, the probabilities `max_power` and `min_power` are sampled to determine the unit's maximum and minimum power output. To make it easier to generate valid ranges, `min_power` is not specified as the absolute power level in MW, but rather as a multiplier of `max_power`; for example, if `max_power` samples to 100 and `min_power` samples to 0.5, then the unit's power range is set to `[50,100]`. Then, the distributions `cost_startup`, `cost_prod` and `cost_fixed` are sampled to determine the unit's startup, variable and fixed costs, while the distributions `min_uptime` and `min_downtime` are sampled to determine its minimum up/down-time.\n", "First, the user-provided probability distributions `n_units` and `n_periods` are sampled to determine the number of generating units and the number of time steps, respectively. Then, for each unit, the probabilities `max_power` and `min_power` are sampled to determine the unit's maximum and minimum power output. To make it easier to generate valid ranges, `min_power` is not specified as the absolute power level in MW, but rather as a multiplier of `max_power`; for example, if `max_power` samples to 100 and `min_power` samples to 0.5, then the unit's power range is set to `[50,100]`. Then, the distributions `cost_startup`, `cost_prod`, `cost_prod_quad` and `cost_fixed` are sampled to determine the unit's startup, linear variable, quadratic variable, and fixed costs, while the distributions `min_uptime` and `min_downtime` are sampled to determine its minimum up/down-time.\n",
"\n", "\n",
"After parameters for the units have been generated, the class then generates a periodic demand curve, with a peak every 12 time steps, in the range $(0.4C, 0.8C)$, where $C$ is the sum of all units' maximum power output. Finally, all costs and demand values are perturbed by random scaling factors independently sampled from the distributions `cost_jitter` and `demand_jitter`, respectively.\n", "After parameters for the units have been generated, the class then generates a periodic demand curve, with a peak every 12 time steps, in the range $(0.4C, 0.8C)$, where $C$ is the sum of all units' maximum power output. Finally, all costs and demand values are perturbed by random scaling factors independently sampled from the distributions `cost_jitter` and `demand_jitter`, respectively.\n",
"\n", "\n",
@ -1309,7 +1307,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 12,
"id": "6217da7c", "id": "6217da7c",
"metadata": { "metadata": {
"ExecuteTime": { "ExecuteTime": {
@ -1333,78 +1331,94 @@
"min_power[0] [117.79 245.85 271.85 207.7 81.38]\n", "min_power[0] [117.79 245.85 271.85 207.7 81.38]\n",
"cost_startup[0] [3042.42 5247.56 4319.45 2912.29 6118.53]\n", "cost_startup[0] [3042.42 5247.56 4319.45 2912.29 6118.53]\n",
"cost_prod[0] [ 6.97 14.61 18.32 22.8 39.26]\n", "cost_prod[0] [ 6.97 14.61 18.32 22.8 39.26]\n",
"cost_fixed[0] [199.67 514.23 592.41 46.45 607.54]\n", "cost_prod_quad[0] [0.02 0.0514 0.0592 0.0046 0.0608]\n",
"cost_fixed[0] [170.52 65.05 948.89 965.63 808.4 ]\n",
"demand[0]\n", "demand[0]\n",
" [ 905.06 915.41 1166.52 1212.29 1127.81 953.52 905.06 796.21 783.78\n", " [ 869.31 897.58 1212.29 1124.08 930.48 1012.62 869.31 606.15]\n",
" 866.23 768.62 899.59 905.06 946.23 1087.61 1004.24 1048.36 992.03\n",
" 905.06 750.82 691.48 606.15 658.5 809.95]\n",
"\n", "\n",
"min_power[1] [117.79 245.85 271.85 207.7 81.38]\n", "min_power[1] [117.79 245.85 271.85 207.7 81.38]\n",
"max_power[1] [218.54 477.82 379.4 319.4 120.21]\n", "max_power[1] [218.54 477.82 379.4 319.4 120.21]\n",
"min_uptime[1] [7 6 3 5 7]\n", "min_uptime[1] [7 6 3 5 7]\n",
"min_downtime[1] [7 3 5 6 2]\n", "min_downtime[1] [7 3 5 6 2]\n",
"min_power[1] [117.79 245.85 271.85 207.7 81.38]\n", "min_power[1] [117.79 245.85 271.85 207.7 81.38]\n",
"cost_startup[1] [2458.08 6200.26 4585.74 2666.05 4783.34]\n", "cost_startup[1] [3710.99 6283.5 4530.89 3526.6 4859.62]\n",
"cost_prod[1] [ 6.31 13.33 20.42 24.37 46.86]\n", "cost_prod[1] [ 5.91 11.29 16.72 21.53 34.77]\n",
"cost_fixed[1] [196.9 416.42 655.57 52.51 626.15]\n", "cost_prod_quad[1] [0.0233 0.0477 0.0527 0.0047 0.0499]\n",
"cost_fixed[1] [ 196.29 51.21 1179.89 1097.07 686.62]\n",
"demand[1]\n", "demand[1]\n",
" [ 981.42 840.07 1095.59 1102.03 1088.41 932.29 863.67 848.56 761.33\n", " [ 827.37 926.76 1166.64 1128.59 939.17 948.8 950.95 639.5 ]\n",
" 828.28 775.18 834.99 959.76 865.72 1193.52 1058.92 985.19 893.92\n",
" 962.16 781.88 723.15 639.04 602.4 787.02]\n",
"\n", "\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n", "Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n", "\n",
"CPU model: AMD Ryzen 9 3950X 16-Core Processor, instruction set [SSE2|AVX|AVX2]\n", "CPU model: AMD Ryzen 9 3950X 16-Core Processor, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 16 physical cores, 32 logical processors, using up to 32 threads\n", "Thread count: 16 physical cores, 32 logical processors, using up to 32 threads\n",
"\n", "\n",
"Optimize a model with 578 rows, 360 columns and 2128 nonzeros\n", "Optimize a model with 162 rows, 120 columns and 512 nonzeros\n",
"Model fingerprint: 0x4dc1c661\n", "Model fingerprint: 0x1e3651da\n",
"Variable types: 120 continuous, 240 integer (240 binary)\n", "Model has 40 quadratic objective terms\n",
"Variable types: 40 continuous, 80 integer (80 binary)\n",
"Coefficient statistics:\n", "Coefficient statistics:\n",
" Matrix range [1e+00, 5e+02]\n", " Matrix range [1e+00, 5e+02]\n",
" Objective range [7e+00, 6e+03]\n", " Objective range [7e+00, 6e+03]\n",
" QObjective range [9e-03, 1e-01]\n",
" Bounds range [1e+00, 1e+00]\n", " Bounds range [1e+00, 1e+00]\n",
" RHS range [1e+00, 1e+03]\n", " RHS range [1e+00, 1e+03]\n",
"Presolve removed 341 rows and 133 columns\n", "Found heuristic solution: objective 282371.35206\n",
"Presolve time: 0.01s\n", "Presolve removed 61 rows and 40 columns\n",
"Presolved: 237 rows, 227 columns, 725 nonzeros\n", "Presolve time: 0.00s\n",
"Variable types: 114 continuous, 113 integer (113 binary)\n", "Presolved: 137 rows, 98 columns, 362 nonzeros\n",
"Found heuristic solution: objective 475243.89360\n", "Presolved model has 40 quadratic objective terms\n",
"Variable types: 58 continuous, 40 integer (40 binary)\n",
"\n", "\n",
"Root relaxation: objective 3.361348e+05, 96 iterations, 0.00 seconds (0.00 work units)\n", "Root relaxation: objective 1.995341e+05, 126 iterations, 0.00 seconds (0.00 work units)\n",
"\n", "\n",
" Nodes | Current Node | Objective Bounds | Work\n", " Nodes | Current Node | Objective Bounds | Work\n",
" Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n",
"\n", "\n",
" 0 0 336134.820 0 18 475243.894 336134.820 29.3% - 0s\n", " 0 0 199534.058 0 8 282371.352 199534.058 29.3% - 0s\n",
"H 0 0 471441.37480 336134.820 28.7% - 0s\n", "H 0 0 212978.80635 199534.058 6.31% - 0s\n",
"H 0 0 410679.27820 336134.820 18.2% - 0s\n", "H 0 0 208079.69920 199534.058 4.11% - 0s\n",
"H 0 0 391706.31610 336134.820 14.2% - 0s\n", " 0 0 203097.772 0 16 208079.699 203097.772 2.39% - 0s\n",
"H 0 0 374515.31390 336134.820 10.2% - 0s\n", " 0 0 203097.772 0 4 208079.699 203097.772 2.39% - 0s\n",
"H 0 0 369369.87450 336134.820 9.00% - 0s\n", " 0 0 203097.772 0 4 208079.699 203097.772 2.39% - 0s\n",
"H 0 0 368600.14450 344055.048 6.66% - 0s\n", " 0 0 203097.772 0 3 208079.699 203097.772 2.39% - 0s\n",
"H 0 0 368180.65796 364657.488 0.96% - 0s\n", " 0 0 203097.772 0 3 208079.699 203097.772 2.39% - 0s\n",
"H 0 0 364721.76610 364657.488 0.02% - 0s\n", " 0 0 203097.772 0 3 208079.699 203097.772 2.39% - 0s\n",
" 0 0 364721.766 0 6 364721.766 364721.766 0.00% - 0s\n", " 0 0 205275.299 0 - 208079.699 205275.299 1.35% - 0s\n",
" 0 0 205777.846 0 2 208079.699 205777.846 1.11% - 0s\n",
" 0 0 205789.407 0 - 208079.699 205789.407 1.10% - 0s\n",
" 0 0 postponed 0 208079.699 205789.407 1.10% - 0s\n",
" 0 0 postponed 0 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 4 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 4 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 1 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 - 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 - 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 - 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 - 208079.699 205789.408 1.10% - 0s\n",
" 0 0 205789.408 0 2 208079.699 205789.408 1.10% - 0s\n",
"H 0 0 207525.63560 205789.408 0.84% - 0s\n",
" 0 0 205789.408 0 2 207525.636 205789.408 0.84% - 0s\n",
" 0 2 205789.408 0 2 207525.636 205789.408 0.84% - 0s\n",
"* 9 0 5 205789.40812 205789.408 0.00% 0.0 0s\n",
"\n", "\n",
"Cutting planes:\n", "Cutting planes:\n",
" Gomory: 2\n", " Cover: 1\n",
" Cover: 7\n", " Implied bound: 6\n",
" Implied bound: 1\n", " MIR: 2\n",
" Clique: 19\n", " Flow cover: 2\n",
" MIR: 3\n", " RLT: 2\n",
" RLT: 10\n", "\n",
" Relax-and-lift: 1\n", "Explored 11 nodes (621 simplex iterations) in 0.32 seconds (0.19 work units)\n",
"\n",
"Explored 1 nodes (181 simplex iterations) in 0.03 seconds (0.01 work units)\n",
"Thread count was 32 (of 32 available processors)\n", "Thread count was 32 (of 32 available processors)\n",
"\n", "\n",
"Solution count 7: 364722 368600 374515 ... 475244\n", "Solution count 5: 205789 207526 208080 ... 282371\n",
"No other solutions better than 205789\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 2.057894080889e+05, best bound 2.057894081187e+05, gap 0.0000%\n",
"\n", "\n",
"User-callback calls 816, time in user-callback 0.00 sec\n" "User-callback calls 650, time in user-callback 0.00 sec\n"
] ]
} }
], ],
@ -1418,14 +1432,15 @@
"random.seed(42)\n", "random.seed(42)\n",
"np.random.seed(42)\n", "np.random.seed(42)\n",
"\n", "\n",
"# Generate a random instance with 5 generators and 24 time steps\n", "# Generate a random instance with 5 generators and 8 time steps\n",
"data = UnitCommitmentGenerator(\n", "data = UnitCommitmentGenerator(\n",
" n_units=randint(low=5, high=6),\n", " n_units=randint(low=5, high=6),\n",
" n_periods=randint(low=24, high=25),\n", " n_periods=randint(low=8, high=9),\n",
" max_power=uniform(loc=50, scale=450),\n", " max_power=uniform(loc=50, scale=450),\n",
" min_power=uniform(loc=0.5, scale=0.25),\n", " min_power=uniform(loc=0.5, scale=0.25),\n",
" cost_startup=uniform(loc=0, scale=10_000),\n", " cost_startup=uniform(loc=0, scale=10_000),\n",
" cost_prod=uniform(loc=0, scale=50),\n", " cost_prod=uniform(loc=0, scale=50),\n",
" cost_prod_quad=uniform(loc=0, scale=0.1),\n",
" cost_fixed=uniform(loc=0, scale=1_000),\n", " cost_fixed=uniform(loc=0, scale=1_000),\n",
" min_uptime=randint(low=2, high=8),\n", " min_uptime=randint(low=2, high=8),\n",
" min_downtime=randint(low=2, high=8),\n", " min_downtime=randint(low=2, high=8),\n",
@ -1443,6 +1458,7 @@
" print(f\"min_power[{i}]\", data[i].min_power)\n", " print(f\"min_power[{i}]\", data[i].min_power)\n",
" print(f\"cost_startup[{i}]\", data[i].cost_startup)\n", " print(f\"cost_startup[{i}]\", data[i].cost_startup)\n",
" print(f\"cost_prod[{i}]\", data[i].cost_prod)\n", " print(f\"cost_prod[{i}]\", data[i].cost_prod)\n",
" print(f\"cost_prod_quad[{i}]\", data[i].cost_prod_quad)\n",
" print(f\"cost_fixed[{i}]\", data[i].cost_fixed)\n", " print(f\"cost_fixed[{i}]\", data[i].cost_fixed)\n",
" print(f\"demand[{i}]\\n\", data[i].demand)\n", " print(f\"demand[{i}]\\n\", data[i].demand)\n",
" print()\n", " print()\n",

@ -1,6 +1,6 @@
MIPLearn MIPLearn
======== ========
**MIPLearn** is an extensible framework for solving discrete optimization problems using a combination of Mixed-Integer Linear Programming (MIP) and Machine Learning (ML). MIPLearn uses ML methods to automatically identify patterns in previously solved instances of the problem, then uses these patterns to accelerate the performance of conventional state-of-the-art MIP solvers such as CPLEX, Gurobi or XPRESS. **MIPLearn** is an extensible framework for solving discrete optimization problems using a combination of Mixed-Integer Programming (MIP) and Machine Learning (ML). MIPLearn uses ML methods to automatically identify patterns in previously solved instances of the problem, then uses these patterns to accelerate the performance of conventional state-of-the-art MIP solvers such as CPLEX, Gurobi or XPRESS.
Unlike pure ML methods, MIPLearn is not only able to find high-quality solutions to discrete optimization problems, but it can also prove the optimality and feasibility of these solutions. Unlike conventional MIP solvers, MIPLearn can take full advantage of very specific observations that happen to be true in a particular family of instances (such as the observation that a particular constraint is typically redundant, or that a particular variable typically assumes a certain value). For certain classes of problems, this approach may provide significant performance benefits. Unlike pure ML methods, MIPLearn is not only able to find high-quality solutions to discrete optimization problems, but it can also prove the optimality and feasibility of these solutions. Unlike conventional MIP solvers, MIPLearn can take full advantage of very specific observations that happen to be true in a particular family of instances (such as the observation that a particular constraint is typically redundant, or that a particular variable typically assumes a certain value). For certain classes of problems, this approach may provide significant performance benefits.

@ -25,6 +25,7 @@ class UnitCommitmentData:
min_downtime: np.ndarray min_downtime: np.ndarray
cost_startup: np.ndarray cost_startup: np.ndarray
cost_prod: np.ndarray cost_prod: np.ndarray
cost_prod_quad: np.ndarray
cost_fixed: np.ndarray cost_fixed: np.ndarray
@ -37,6 +38,7 @@ class UnitCommitmentGenerator:
min_power: rv_frozen = uniform(loc=0.5, scale=0.25), min_power: rv_frozen = uniform(loc=0.5, scale=0.25),
cost_startup: rv_frozen = uniform(loc=0, scale=10_000), cost_startup: rv_frozen = uniform(loc=0, scale=10_000),
cost_prod: rv_frozen = uniform(loc=0, scale=50), cost_prod: rv_frozen = uniform(loc=0, scale=50),
cost_prod_quad: rv_frozen = uniform(loc=0, scale=0),
cost_fixed: rv_frozen = uniform(loc=0, scale=1_000), cost_fixed: rv_frozen = uniform(loc=0, scale=1_000),
min_uptime: rv_frozen = randint(low=2, high=8), min_uptime: rv_frozen = randint(low=2, high=8),
min_downtime: rv_frozen = randint(low=2, high=8), min_downtime: rv_frozen = randint(low=2, high=8),
@ -50,6 +52,7 @@ class UnitCommitmentGenerator:
self.min_power = min_power self.min_power = min_power
self.cost_startup = cost_startup self.cost_startup = cost_startup
self.cost_prod = cost_prod self.cost_prod = cost_prod
self.cost_prod_quad = cost_prod_quad
self.cost_fixed = cost_fixed self.cost_fixed = cost_fixed
self.min_uptime = min_uptime self.min_uptime = min_uptime
self.min_downtime = min_downtime self.min_downtime = min_downtime
@ -72,6 +75,7 @@ class UnitCommitmentGenerator:
min_downtime = self.min_downtime.rvs(G) min_downtime = self.min_downtime.rvs(G)
cost_startup = self.cost_startup.rvs(G) cost_startup = self.cost_startup.rvs(G)
cost_prod = self.cost_prod.rvs(G) cost_prod = self.cost_prod.rvs(G)
cost_prod_quad = self.cost_prod_quad.rvs(G)
cost_fixed = self.cost_fixed.rvs(G) cost_fixed = self.cost_fixed.rvs(G)
capacity = max_power.sum() capacity = max_power.sum()
@ -91,6 +95,7 @@ class UnitCommitmentGenerator:
min_downtime = self.ref_data.min_downtime min_downtime = self.ref_data.min_downtime
cost_startup = self.ref_data.cost_startup * self.cost_jitter.rvs(G) cost_startup = self.ref_data.cost_startup * self.cost_jitter.rvs(G)
cost_prod = self.ref_data.cost_prod * self.cost_jitter.rvs(G) cost_prod = self.ref_data.cost_prod * self.cost_jitter.rvs(G)
cost_prod_quad = self.ref_data.cost_prod_quad * self.cost_jitter.rvs(G)
cost_fixed = self.ref_data.cost_fixed * self.cost_jitter.rvs(G) cost_fixed = self.ref_data.cost_fixed * self.cost_jitter.rvs(G)
data = UnitCommitmentData( data = UnitCommitmentData(
@ -101,6 +106,7 @@ class UnitCommitmentGenerator:
min_downtime, min_downtime,
cost_startup.round(2), cost_startup.round(2),
cost_prod.round(2), cost_prod.round(2),
cost_prod_quad.round(4),
cost_fixed.round(2), cost_fixed.round(2),
) )
@ -143,6 +149,7 @@ def build_uc_model_gurobipy(data: Union[str, UnitCommitmentData]) -> GurobiModel
is_on[g, t] * data.cost_fixed[g] is_on[g, t] * data.cost_fixed[g]
+ switch_on[g, t] * data.cost_startup[g] + switch_on[g, t] * data.cost_startup[g]
+ prod[g, t] * data.cost_prod[g] + prod[g, t] * data.cost_prod[g]
+ prod[g, t] * prod[g, t] * data.cost_prod_quad[g]
for g in range(G) for g in range(G)
for t in range(T) for t in range(T)
) )

Loading…
Cancel
Save