Add maxcut to problems.ipynb

dev
Alinson S. Xavier 4 days ago
parent bfaae7c005
commit 4eeb1c1ab3
No known key found for this signature in database
GPG Key ID: 727EF7F619B0F35E

@ -130,10 +130,10 @@
"9 [ 8.57 22.77 17.06 16.25 4.14 4. 1.56 22.97 14.09 19.09] 100.79\n",
"\n",
"Restricted license - for non-production use only - expires 2026-11-23\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 20 rows, 110 columns and 210 nonzeros\n",
"Model fingerprint: 0x1ff9913f\n",
@ -159,15 +159,15 @@
"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.03 seconds (0.00 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Explored 1 nodes (38 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 4: 2 3 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",
"\n",
"User-callback calls 151, time in user-callback 0.00 sec\n"
"User-callback calls 148, time in user-callback 0.00 sec\n"
]
}
],
@ -325,10 +325,10 @@
"capacities\n",
" [1310. 988. 1004. 1269. 1007.]\n",
"\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 5 rows, 10 columns and 50 nonzeros\n",
"Model fingerprint: 0xaf3ac15e\n",
@ -354,8 +354,8 @@
"H 0 0 -1279.000000 -1428.7265 11.7% - 0s\n",
" 0 0 -1428.7265 0 4 -1279.0000 -1428.7265 11.7% - 0s\n",
"\n",
"Explored 1 nodes (4 simplex iterations) in 0.02 seconds (0.00 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Explored 1 nodes (4 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 3: -1279 -995 -804 \n",
"No other solutions better than -1279\n",
@ -363,7 +363,7 @@
"Optimal solution found (tolerance 1.00e-04)\n",
"Best objective -1.279000000000e+03, best bound -1.279000000000e+03, gap 0.0000%\n",
"\n",
"User-callback calls 417, time in user-callback 0.00 sec\n"
"User-callback calls 416, time in user-callback 0.00 sec\n"
]
}
],
@ -501,10 +501,10 @@
"demands = [6.12 1.39 2.92 3.66 4.56 7.85 2. 5.14 5.92 0.46]\n",
"capacities = [151.89 42.63 16.26 237.22 241.41 202.1 76.15 24.42 171.06 110.04]\n",
"\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 21 rows, 110 columns and 220 nonzeros\n",
"Model fingerprint: 0x8d8d9346\n",
@ -542,14 +542,14 @@
" StrongCG: 1\n",
"\n",
"Explored 1 nodes (42 simplex iterations) in 0.02 seconds (0.00 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 9: 91.23 98.39 114.53 ... 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",
"\n",
"User-callback calls 189, time in user-callback 0.00 sec\n"
"User-callback calls 187, time in user-callback 0.00 sec\n"
]
}
],
@ -678,10 +678,10 @@
"costs [1044.58 850.13 1014.5 944.83 697.9 971.87 213.49 220.98 70.23\n",
" 425.33]\n",
"\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 5 rows, 10 columns and 28 nonzeros\n",
"Model fingerprint: 0xe5c2d4fa\n",
@ -697,7 +697,7 @@
"Presolve: All rows and columns removed\n",
"\n",
"Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)\n",
"Thread count was 1 (of 20 available processors)\n",
"Thread count was 1 (of 32 available processors)\n",
"\n",
"Solution count 1: 213.49 \n",
"\n",
@ -819,10 +819,10 @@
"costs [1044.58 850.13 1014.5 944.83 697.9 971.87 213.49 220.98 70.23\n",
" 425.33]\n",
"\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 5 rows, 10 columns and 28 nonzeros\n",
"Model fingerprint: 0x4ee91388\n",
@ -837,8 +837,8 @@
"Presolve time: 0.00s\n",
"Presolve: All rows and columns removed\n",
"\n",
"Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)\n",
"Thread count was 1 (of 20 available processors)\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",
"\n",
"Solution count 2: -1986.37 -1265.56 \n",
"No other solutions better than -1986.37\n",
@ -846,7 +846,7 @@
"Optimal solution found (tolerance 1.00e-04)\n",
"Best objective -1.986370000000e+03, best bound -1.986370000000e+03, gap 0.0000%\n",
"\n",
"User-callback calls 244, time in user-callback 0.00 sec\n"
"User-callback calls 245, time in user-callback 0.00 sec\n"
]
}
],
@ -946,10 +946,10 @@
"weights[1] [ 2.06 96.99 83.24 21.23 18.18 18.34 30.42 52.48 43.19 29.12]\n",
"\n",
"Set parameter PreCrush to value 1\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Non-default parameters:\n",
"PreCrush 1\n",
@ -975,8 +975,8 @@
"\n",
" 0 0 infeasible 0 -219.14000 -219.14000 0.00% - 0s\n",
"\n",
"Explored 1 nodes (5 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Explored 1 nodes (5 simplex iterations) in 0.02 seconds (0.00 work units)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 1: -219.14 \n",
"No other solutions better than -219.14\n",
@ -984,7 +984,7 @@
"Optimal solution found (tolerance 1.00e-04)\n",
"Best objective -2.191400000000e+02, best bound -2.191400000000e+02, gap 0.0000%\n",
"\n",
"User-callback calls 303, time in user-callback 0.00 sec\n"
"User-callback calls 304, time in user-callback 0.01 sec\n"
]
}
],
@ -1129,10 +1129,10 @@
"\n",
"Set parameter PreCrush to value 1\n",
"Set parameter LazyConstraints to value 1\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Non-default parameters:\n",
"PreCrush 1\n",
@ -1161,14 +1161,14 @@
" Lazy constraints: 3\n",
"\n",
"Explored 1 nodes (17 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 1: 2921 \n",
"\n",
"Optimal solution found (tolerance 1.00e-04)\n",
"Best objective 2.921000000000e+03, best bound 2.921000000000e+03, gap 0.0000%\n",
"\n",
"User-callback calls 111, time in user-callback 0.00 sec\n"
"User-callback calls 112, time in user-callback 0.00 sec\n"
]
}
],
@ -1352,10 +1352,10 @@
" 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",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 578 rows, 360 columns and 2128 nonzeros\n",
"Model fingerprint: 0x4dc1c661\n",
@ -1397,14 +1397,14 @@
" Relax-and-lift: 1\n",
"\n",
"Explored 1 nodes (181 simplex iterations) in 0.03 seconds (0.01 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 7: 364722 368600 374515 ... 475244\n",
"\n",
"Optimal solution found (tolerance 1.00e-04)\n",
"Best objective 3.647217661000e+05, best bound 3.647217661000e+05, gap 0.0000%\n",
"\n",
"User-callback calls 815, time in user-callback 0.00 sec\n"
"User-callback calls 816, time in user-callback 0.00 sec\n"
]
}
],
@ -1524,10 +1524,10 @@
"weights[0] [37.45 95.07 73.2 59.87 15.6 15.6 5.81 86.62 60.11 70.81]\n",
"weights[1] [ 2.06 96.99 83.24 21.23 18.18 18.34 30.42 52.48 43.19 29.12]\n",
"\n",
"Gurobi Optimizer version 12.0.2 build v12.0.2rc0 (linux64 - \"Ubuntu 22.04.4 LTS\")\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\n",
"CPU model: 13th Gen Intel(R) Core(TM) i7-13800H, instruction set [SSE2|AVX|AVX2]\n",
"Thread count: 10 physical cores, 20 logical processors, using up to 20 threads\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",
"\n",
"Optimize a model with 15 rows, 10 columns and 30 nonzeros\n",
"Model fingerprint: 0x2d2d1390\n",
@ -1551,7 +1551,7 @@
" 0 0 cutoff 0 301.00000 301.00000 0.00% - 0s\n",
"\n",
"Explored 1 nodes (8 simplex iterations) in 0.01 seconds (0.00 work units)\n",
"Thread count was 20 (of 20 available processors)\n",
"Thread count was 32 (of 32 available processors)\n",
"\n",
"Solution count 1: 301 \n",
"\n",
@ -1594,6 +1594,148 @@
"model = build_vertexcover_model_gurobipy(data[0])\n",
"model.optimize()"
]
},
{
"cell_type": "markdown",
"id": "k4ojjjni3z",
"metadata": {},
"source": [
"## Maximum Cut\n",
"\n",
"The **maximum cut problem** is a classical optimization problem in graph theory and combinatorial optimization. Given a graph with weighted edges, the goal is to partition the vertices into two disjoint sets such that the sum of the weights of the edges crossing the partition is maximized. This problem is one of Karp's 21 NP-complete problems and has important applications in theoretical physics, machine learning, and VLSI design."
]
},
{
"cell_type": "markdown",
"id": "kzdqjib7lac",
"metadata": {},
"source": [
"### Formulation\n",
"\n",
"Let $G=(V,E)$ be an undirected graph, and for each edge $e \\in E$, let $w_e$ be its weight. For each vertex $v \\in V$, let $x_v$ be a binary decision variable that equals one if vertex $v$ is assigned to the first partition, and zero if it is assigned to the second partition. The maximum cut problem is formulated as:"
]
},
{
"cell_type": "markdown",
"id": "lnmj134ojad",
"metadata": {},
"source": [
"$$\n",
"\\begin{align*}\n",
"\\text{minimize} \\;\\;\\;\n",
" & -\\sum_{(i,j) \\in E} w_{ij} x_i \\left( 1 - x_j \\right) \\\\\n",
"\\text{such that} \\;\\;\\;\n",
" & x_v \\in \\{0, 1\\} & \\forall v \\in V\n",
"\\end{align*}\n",
"$$\n",
"\n",
"The objective function counts the total weight of edges that cross the cut (i.e., edges connecting vertices in different partitions)."
]
},
{
"cell_type": "markdown",
"id": "j49upfw2o8k",
"metadata": {},
"source": [
"### Random instance generator\n",
"\n",
"The class [MaxCutGenerator][MaxCutGenerator] can be used to generate random instances of this problem. The generator operates in two modes:\n",
"\n",
"When `fix_graph=False`, a new random Erdős-Rényi graph $G_{n,p}$ is generated for each instance, where $n$ (number of vertices) and $p$ (edge probability) are sampled from the provided probability distributions. Each edge is assigned a random weight drawn from the set $\\{-1, +1\\}$ with equal probability.\n",
"\n",
"When `fix_graph=True`, a single random graph is generated during initialization and reused across all instances. To create variations, the generator randomly flips the sign of each edge weight with probability `w_jitter`, allowing for instances with the same graph structure but different edge weight patterns.\n",
"\n",
"[MaxCutGenerator]: ../../api/problems/#miplearn.problems.maxcut.MaxCutGenerator"
]
},
{
"cell_type": "markdown",
"id": "wsd5jlowc4k",
"metadata": {},
"source": [
"### Example"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "uge28hmv3a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"graph edges: [(0, 2), (0, 3), (0, 4), (0, 8), (1, 2), (1, 3), (1, 5), (1, 6), (1, 9), (2, 5), (2, 9), (3, 6), (3, 7), (6, 9), (7, 8), (7, 9), (8, 9)]\n",
"weights[0]: [ 1 1 1 -1 -1 -1 -1 -1 -1 -1 1 -1 -1 1 1 -1 -1]\n",
"weights[1]: [-1 1 -1 -1 -1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1]\n",
"\n",
"Gurobi Optimizer version 12.0.3 build v12.0.3rc0 (linux64 - \"Ubuntu 24.04.3 LTS\")\n",
"\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",
"\n",
"Optimize a model with 0 rows, 10 columns and 0 nonzeros\n",
"Model fingerprint: 0x005f9eac\n",
"Model has 17 quadratic objective terms\n",
"Variable types: 0 continuous, 10 integer (10 binary)\n",
"Coefficient statistics:\n",
" Matrix range [0e+00, 0e+00]\n",
" Objective range [1e+00, 5e+00]\n",
" QObjective range [2e+00, 2e+00]\n",
" Bounds range [1e+00, 1e+00]\n",
" RHS range [0e+00, 0e+00]\n",
"Found heuristic solution: objective 0.0000000\n",
"Found heuristic solution: objective -3.0000000\n",
"Presolve removed 0 rows and 10 columns\n",
"Presolve time: 0.00s\n",
"Presolve: All rows and columns removed\n",
"\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",
"\n",
"Solution count 2: -3 0 \n",
"No other solutions better than -3\n",
"\n",
"Optimal solution found (tolerance 1.00e-04)\n",
"Best objective -3.000000000000e+00, best bound -3.000000000000e+00, gap 0.0000%\n",
"\n",
"User-callback calls 86, time in user-callback 0.00 sec\n"
]
}
],
"source": [
"import random\n",
"import numpy as np\n",
"from scipy.stats import uniform, randint\n",
"from miplearn.problems.maxcut import (\n",
" MaxCutGenerator,\n",
" build_maxcut_model_gurobipy,\n",
")\n",
"\n",
"# Set random seed to make example reproducible\n",
"random.seed(42)\n",
"np.random.seed(42)\n",
"\n",
"# Generate random instances with a fixed 10-node graph,\n",
"# 30% edge probability, and random weight jittering\n",
"data = MaxCutGenerator(\n",
" n=randint(low=10, high=11),\n",
" p=uniform(loc=0.3, scale=0.0),\n",
" w_jitter=0.2,\n",
" fix_graph=True,\n",
").generate(10)\n",
"\n",
"# Print the graph and weights for two instances\n",
"print(\"graph edges:\", list(data[0].graph.edges()))\n",
"print(\"weights[0]:\", data[0].weights)\n",
"print(\"weights[1]:\", data[1].weights)\n",
"print()\n",
"\n",
"# Build and optimize the first instance\n",
"model = build_maxcut_model_gurobipy(data[0])\n",
"model.optimize()"
]
}
],
"metadata": {
@ -1612,7 +1754,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.12.3"
}
},
"nbformat": 4,

Loading…
Cancel
Save