Maximum k-Cut Example
The Maximum k-Cut problem partitions the nodes of a weighted graph into k groups so that the total weight of edges crossing between different groups is maximized. For k = 2 it reduces to the classic Max-Cut problem. It is NP-hard and has applications in clustering, statistical physics, and VLSI design.
import getpass
import os
import networkx as nx
from dotenv import load_dotenv
from luna_quantum.algorithms import SCIP
from luna_usecases.maximum_k_cut import (
MaxKCutCollection,
MaxKCutData,
MaxKCutFormulation,
MaxKCutInstance,
)
load_dotenv()
if "LUNA_API_KEY" not in os.environ:
os.environ["LUNA_API_KEY"] = getpass.getpass("Enter your Luna API key: ")
Create Data
Build the graph from a NetworkX graph using the from_graph factory. Here we use a 6-node cycle and partition it into k = 3 groups.
Plot Data
Visualize the weighted graph structure.
Create Formulation
Maximize the total weight of edges whose endpoints fall into different groups.
Maximum k-Cut Formulation:
Nodes: 6
Edges: 6
Groups (k): 3
Decision Variables:
x[i,c] in {0,1} for i = 0, ..., 5, c = 0, ..., 2
x[i,c] = 1 if node i is assigned to group c
Total: 18 binary variables
Objective:
maximize sum_{(i,j) in E} w[i,j] * (1 - sum_c x[i,c] * x[j,c])
Constraints:
1. One group per node (6 constraints):
sum_c x[i,c] == 1 for all nodes i
Create Instance
Combine data and formulation into a solvable instance.
Data:Maximum k-Cut Data:
Nodes: 6
Edges: 6
Groups (k): 3
Formulation:Maximum k-Cut Formulation:
Nodes: 6
Edges: 6
Groups (k): 3
Decision Variables:
x[i,c] in {0,1} for i = 0, ..., 5, c = 0, ..., 2
x[i,c] = 1 if node i is assigned to group c
Total: 18 binary variables
Objective:
maximize sum_{(i,j) in E} w[i,j] * (1 - sum_c x[i,c] * x[j,c])
Constraints:
1. One group per node (6 constraints):
sum_c x[i,c] == 1 for all nodes i
Formulate Model
Translate the instance into a mathematical optimization model.
Solve and Interpret
Solve the model with SCIP and interpret the raw result into a use-case-specific solution.
scip = SCIP()
job = scip.run(model)
sol = job.result()
uc_solution = instance.interpret(sol)
print(uc_solution.to_string())
Waiting for result | elapsed 0:00:00 | poll 1 | next check in 0.5s
Waiting for result | elapsed 0:00:01 | poll 2 | next check in 1s
Waiting for result | elapsed 0:00:03 | poll 3 | next check in 2s
Waiting for result | elapsed 0:00:05 | poll 4 | next check in 4s
Waiting for result | elapsed 0:00:09 | poll 5 | next check in 8s
Waiting for result | elapsed 0:00:18 | poll 6 | next check in 16s
2026-08-20 12:09:41 INFO Solve job 'b27cea3b-0b06-4e57-aa8c-d6017bfc1d03' finished with status 'DONE' after 0:00:35.
Maximum k-Cut Solution:
Cut Weight: 6.0
Groups (k): 3
Group 0: [0, 2, 4]
Group 1: []
Group 2: [1, 3, 5]
Plot Solution
Visualize the partition: nodes are colored by group and cut edges are highlighted.
Collections
Generate a benchmark collection of random instances for batch processing.
collection = MaxKCutCollection.from_random(min_nodes=4, max_nodes=6, k=3, num_instances=2, seed=42)
model = collection.instances[0].formulate()
print(model)
Model: maximum_k_cut<s42_n4_k3_i0>
Maximize
-4 * x_0_0 * x_1_0 - 4 * x_0_0 * x_2_0 - 4 * x_0_1 * x_1_1 - 4 * x_0_1 * x_2_1
- 4 * x_0_2 * x_1_2 - 4 * x_0_2 * x_2_2 - 10 * x_1_0 * x_3_0
- 10 * x_1_1 * x_3_1 - 10 * x_1_2 * x_3_2 + 18
Subject To
assign_0: x_0_0 + x_0_1 + x_0_2 == 1
assign_1: x_1_0 + x_1_1 + x_1_2 == 1
assign_2: x_2_0 + x_2_1 + x_2_2 == 1
assign_3: x_3_0 + x_3_1 + x_3_2 == 1
Binary
x_0_0 x_0_1 x_0_2 x_1_0 x_1_1 x_1_2 x_2_0 x_2_1 x_2_2 x_3_0 x_3_1 x_3_2