Implement MinWeightVertexCoverPerturber

This commit is contained in:
2025-12-08 15:37:16 -06:00
parent 146fb6b615
commit 485625e07f
3 changed files with 85 additions and 16 deletions

View File

@@ -1596,7 +1596,10 @@
"\n",
"The class [MinWeightVertexCoverGenerator][MinWeightVertexCoverGenerator] can be used to generate random instances of this problem. The class accepts the same parameters and behaves in the same way as [MaxWeightStableSetGenerator][MaxWeightStableSetGenerator]. See the [stable set section](#Stable-Set) for more details on the generation process.\n",
"\n",
"To create multiple instances with the same graph structure but different vertex weights, you can use [MinWeightVertexCoverPerturber][MinWeightVertexCoverPerturber]. This class takes an existing MinWeightVertexCoverData instance and generates new instances by applying random scaling factors to the vertex weights while keeping the graph fixed.\n",
"\n",
"[MinWeightVertexCoverGenerator]: ../../api/problems/#module-miplearn.problems.vertexcover\n",
"[MinWeightVertexCoverPerturber]: ../../api/problems/#module-miplearn.problems.vertexcover\n",
"[MaxWeightStableSetGenerator]: ../../api/problems/#miplearn.problems.stab.MaxWeightStableSetGenerator\n",
"\n",
"### Example"
@@ -1604,7 +1607,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 13,
"id": "5fff7afe-5b7a-4889-a502-66751ec979bf",
"metadata": {
"ExecuteTime": {
@@ -1618,8 +1621,8 @@
"output_type": "stream",
"text": [
"graph [(0, 2), (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), (8, 9)]\n",
"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",
"weights[0] [33.78 94.78 71.97 55.15 14.32 14.33 5.41 82.5 56.7 65.79]\n",
"weights[1] [36. 86.89 68.02 56.08 14.75 15.26 5.35 82.41 57.66 64.06]\n",
"\n",
"Gurobi Optimizer version 13.0.0 build v13.0.0rc1 (linux64 - \"Ubuntu 22.04.5 LTS\")\n",
"\n",
@@ -1627,34 +1630,34 @@
"Thread count: 16 physical cores, 16 logical processors, using up to 16 threads\n",
"\n",
"Optimize a model with 15 rows, 10 columns and 30 nonzeros (Min)\n",
"Model fingerprint: 0x2d2d1390\n",
"Model fingerprint: 0xf99bd426\n",
"Model has 10 linear objective coefficients\n",
"Variable types: 0 continuous, 10 integer (10 binary)\n",
"Coefficient statistics:\n",
" Matrix range [1e+00, 1e+00]\n",
" Objective range [6e+00, 1e+02]\n",
" Objective range [5e+00, 9e+01]\n",
" Bounds range [1e+00, 1e+00]\n",
" RHS range [1e+00, 1e+00]\n",
"Found heuristic solution: objective 301.0000000\n",
"Found heuristic solution: objective 283.6700000\n",
"Presolve removed 7 rows and 2 columns\n",
"Presolve time: 0.00s\n",
"Presolved: 8 rows, 8 columns, 19 nonzeros\n",
"Variable types: 0 continuous, 8 integer (8 binary)\n",
"\n",
"Root relaxation: cutoff, 8 iterations, 0.00 seconds (0.00 work units)\n",
"Root relaxation: cutoff, 6 iterations, 0.00 seconds (0.00 work units)\n",
"\n",
" Nodes | Current Node | Objective Bounds | Work\n",
" Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n",
"\n",
" 0 0 cutoff 0 301.00000 301.00000 0.00% - 0s\n",
" 0 0 cutoff 0 283.67000 283.67000 0.00% - 0s\n",
"\n",
"Explored 1 nodes (8 simplex iterations) in 0.00 seconds (0.00 work units)\n",
"Explored 1 nodes (6 simplex iterations) in 0.00 seconds (0.00 work units)\n",
"Thread count was 16 (of 16 available processors)\n",
"\n",
"Solution count 1: 301 \n",
"Solution count 1: 283.67 \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 2.836700000000e+02, best bound 2.836700000000e+02, gap 0.0000%\n",
"\n",
"User-callback calls 335, time in user-callback 0.00 sec\n"
]
@@ -1666,6 +1669,7 @@
"from scipy.stats import uniform, randint\n",
"from miplearn.problems.vertexcover import (\n",
" MinWeightVertexCoverGenerator,\n",
" MinWeightVertexCoverPerturber,\n",
" build_vertexcover_model_gurobipy,\n",
")\n",
"\n",
@@ -1673,13 +1677,20 @@
"random.seed(42)\n",
"np.random.seed(42)\n",
"\n",
"# Generate random instances with a 10-node graph,\n",
"# Generate a reference instance with a 10-node graph,\n",
"# 25% density and random weights in the [0, 100] interval.\n",
"data = MinWeightVertexCoverGenerator(\n",
"generator = MinWeightVertexCoverGenerator(\n",
" w=uniform(loc=0.0, scale=100.0),\n",
" n=randint(low=10, high=11),\n",
" p=uniform(loc=0.25, scale=0.0),\n",
").generate(10)\n",
")\n",
"reference_instance = generator.generate(1)[0]\n",
"\n",
"# Generate perturbed instances using the reference\n",
"perturber = MinWeightVertexCoverPerturber(\n",
" w_jitter=uniform(loc=0.9, scale=0.1),\n",
")\n",
"data = perturber.perturb(reference_instance, 10)\n",
"\n",
"# Print the graph and weights for two instances\n",
"print(\"graph\", data[0].graph.edges)\n",