Circuit Partitioning Examples

Examples demonstrating circuit partitioning algorithms.


Naive Capacity-Based Circuit Partitioning on a Grover Circuit

This example demonstrates naive capacity-based partitioning, which distributes gates evenly across partitions based purely on capacity, ignoring connectivity.

capacity_based_partitioning_grover_example.py
 1from kosmos.partitioning.algorithms.capacity_partitioner import CapacityBasedPartitioner
 2from kosmos.partitioning.mqt_bench.bench_circuit import MQTBenchCircuit
 3from kosmos.utils.rng import RNG
 4
 5GATE_VISUALIZATION_LENGTH = 5
 6
 7
 8def partitioning_result_description(
 9    algorithm_name: str, assignments: dict[int, int], num_gates: int
10) -> list[str]:
11    """Format partitioning results as human-readable text lines.
12
13    Args:
14        algorithm_name: Name of the partitioning algorithm.
15        assignments: Gate-to-partition assignments.
16        num_gates: Total number of gates in the circuit.
17
18    Returns:
19        list[str]: Formatted output lines.
20
21    """
22    output = [f"\n{'=' * 60}", f"Algorithm: {algorithm_name}", f"{'=' * 60}"]
23
24    # Group gates by partition
25    partitions: dict[int, list[int]] = {}
26    for gate_idx, partition_id in assignments.items():
27        if partition_id not in partitions:
28            partitions[partition_id] = []
29        partitions[partition_id].append(gate_idx)
30
31    # Calculate statistics
32    num_partitions = len(partitions)
33    partition_sizes = [len(gates) for gates in partitions.values()]
34    avg_size = sum(partition_sizes) / num_partitions if num_partitions > 0 else 0
35    max_size = max(partition_sizes) if partition_sizes else 0
36    min_size = min(partition_sizes) if partition_sizes else 0
37
38    output.append("\nStatistics:")
39    output.append(f"  Total gates: {num_gates}")
40    output.append(f"  Number of partitions: {num_partitions}")
41    output.append(f"  Partition sizes: min={min_size}, max={max_size}, avg={avg_size:.1f}")
42
43    # Calculate balance metric
44    if avg_size > 0:
45        balance = max(abs(size - avg_size) for size in partition_sizes) / avg_size
46        output.append(f"  Balance (max deviation): {balance:.2%}")
47
48    output.append("\nPartition Details:")
49    for partition_id in sorted(partitions.keys()):
50        gates = sorted(partitions[partition_id])
51        gate_str = (
52            f"[{gates[0]}...{gates[-1]}]" if len(gates) > GATE_VISUALIZATION_LENGTH else str(gates)
53        )
54        output.append(f"  Partition {partition_id}: {len(gates)} gates {gate_str}")
55
56    return output
57
58
59def capacity_based_grover_example() -> None:
60    """Run example for naive capacity-based circuit partitioning on a Grover circuit."""
61    RNG.initialize(seed=1)
62
63    output = ["\n=== Circuit Characteristics ==="]
64
65    # Load Grover circuit from MQT Bench
66    benchmark = MQTBenchCircuit(circuit_type="grover-noancilla", num_qubits=8)
67    circuit = benchmark.circuit()
68
69    output.append(f"Qubits: {benchmark.num_qubits}")
70    output.append(f"Gates: {benchmark.num_gates}")
71    output.append(f"Depth: {benchmark.depth}")
72
73    partitioner = CapacityBasedPartitioner(network=None, num_partitions=3)
74    assignments = partitioner.partition(circuit)
75
76    output.extend(
77        partitioning_result_description("Capacity-Based", assignments, benchmark.num_gates)
78    )
79
80    print("\n".join(output))  # noqa: T201
81
82
83if __name__ == "__main__":
84    capacity_based_grover_example()

Circuit Partitioning Using Metis on a QFT Circuit

This example demonstrates partitioning using METIS.

metis_partitioning_qft_example.py
 1from kosmos.partitioning.algorithms.metis_partitioner import METISPartitioner
 2from kosmos.partitioning.mqt_bench.bench_circuit import MQTBenchCircuit
 3from kosmos.utils.rng import RNG
 4
 5GATE_VISUALIZATION_LENGTH = 5
 6
 7
 8def partitioning_result_description(
 9    algorithm_name: str, assignments: dict[int, int], num_gates: int
10) -> list[str]:
11    """Format partitioning results as human-readable text lines.
12
13    Args:
14        algorithm_name: Name of the partitioning algorithm.
15        assignments: Gate-to-partition assignments.
16        num_gates: Total number of gates in the circuit.
17
18    Returns:
19        list[str]: Formatted output lines.
20
21    """
22    output = [f"\n{'=' * 60}", f"Algorithm: {algorithm_name}", f"{'=' * 60}"]
23
24    # Group gates by partition
25    partitions: dict[int, list[int]] = {}
26    for gate_idx, partition_id in assignments.items():
27        if partition_id not in partitions:
28            partitions[partition_id] = []
29        partitions[partition_id].append(gate_idx)
30
31    # Calculate statistics
32    num_partitions = len(partitions)
33    partition_sizes = [len(gates) for gates in partitions.values()]
34    avg_size = sum(partition_sizes) / num_partitions if num_partitions > 0 else 0
35    max_size = max(partition_sizes) if partition_sizes else 0
36    min_size = min(partition_sizes) if partition_sizes else 0
37
38    output.append("\nStatistics:")
39    output.append(f"  Total gates: {num_gates}")
40    output.append(f"  Number of partitions: {num_partitions}")
41    output.append(f"  Partition sizes: min={min_size}, max={max_size}, avg={avg_size:.1f}")
42
43    # Calculate balance metric
44    if avg_size > 0:
45        balance = max(abs(size - avg_size) for size in partition_sizes) / avg_size
46        output.append(f"  Balance (max deviation): {balance:.2%}")
47
48    output.append("\nPartition Details:")
49    for partition_id in sorted(partitions.keys()):
50        gates = sorted(partitions[partition_id])
51        gate_str = (
52            f"[{gates[0]}...{gates[-1]}]" if len(gates) > GATE_VISUALIZATION_LENGTH else str(gates)
53        )
54        output.append(f"  Partition {partition_id}: {len(gates)} gates {gate_str}")
55
56    return output
57
58
59def metis_partition_qft_example() -> None:
60    """Run example for circuit partitioning using METIS on a QFT circuit."""
61    RNG.initialize(seed=1)
62
63    output = ["\n=== Circuit Characteristics ==="]
64
65    # Load QFT circuit from MQT Bench
66    benchmark = MQTBenchCircuit(circuit_type="qft", num_qubits=16)
67    circuit = benchmark.circuit()
68
69    output.append(f"Qubits: {benchmark.num_qubits}")
70    output.append(f"Gates: {benchmark.num_gates}")
71    output.append(f"Depth: {benchmark.depth}")
72
73    partitioner = METISPartitioner(network=None, num_partitions=3)
74    assignments = partitioner.partition(circuit)
75
76    output.extend(partitioning_result_description("METIS", assignments, benchmark.num_gates))
77
78    print("\n".join(output))  # noqa: T201
79
80
81if __name__ == "__main__":
82    metis_partition_qft_example()

Spectral Circuit Partitioning on a QFT Circuit

This example demonstrates spectral partitioning using the Fiedler vector of the graph Laplacian.

spectral_partitioning_qft_example.py
 1from kosmos.partitioning.algorithms.spectral_partitioner import SpectralPartitioner
 2from kosmos.partitioning.mqt_bench.bench_circuit import MQTBenchCircuit
 3from kosmos.utils.rng import RNG
 4
 5GATE_VISUALIZATION_LENGTH = 5
 6
 7
 8def partitioning_result_description(
 9    algorithm_name: str, assignments: dict[int, int], num_gates: int
10) -> list[str]:
11    """Format partitioning results as human-readable text lines.
12
13    Args:
14        algorithm_name: Name of the partitioning algorithm.
15        assignments: Gate-to-partition assignments.
16        num_gates: Total number of gates in the circuit.
17
18    Returns:
19        list[str]: Formatted output lines.
20
21    """
22    output = [f"\n{'=' * 60}", f"Algorithm: {algorithm_name}", f"{'=' * 60}"]
23
24    # Group gates by partition
25    partitions: dict[int, list[int]] = {}
26    for gate_idx, partition_id in assignments.items():
27        if partition_id not in partitions:
28            partitions[partition_id] = []
29        partitions[partition_id].append(gate_idx)
30
31    # Calculate statistics
32    num_partitions = len(partitions)
33    partition_sizes = [len(gates) for gates in partitions.values()]
34    avg_size = sum(partition_sizes) / num_partitions if num_partitions > 0 else 0
35    max_size = max(partition_sizes) if partition_sizes else 0
36    min_size = min(partition_sizes) if partition_sizes else 0
37
38    output.append("\nStatistics:")
39    output.append(f"  Total gates: {num_gates}")
40    output.append(f"  Number of partitions: {num_partitions}")
41    output.append(f"  Partition sizes: min={min_size}, max={max_size}, avg={avg_size:.1f}")
42
43    # Calculate balance metric
44    if avg_size > 0:
45        balance = max(abs(size - avg_size) for size in partition_sizes) / avg_size
46        output.append(f"  Balance (max deviation): {balance:.2%}")
47
48    output.append("\nPartition Details:")
49    for partition_id in sorted(partitions.keys()):
50        gates = sorted(partitions[partition_id])
51        gate_str = (
52            f"[{gates[0]}...{gates[-1]}]" if len(gates) > GATE_VISUALIZATION_LENGTH else str(gates)
53        )
54        output.append(f"  Partition {partition_id}: {len(gates)} gates {gate_str}")
55
56    return output
57
58
59def spectral_partition_qft_example() -> None:
60    """Run example for spectral circuit partitioning on a QFT circuit."""
61    RNG.initialize(seed=1)
62
63    output = ["\n=== Circuit Characteristics ==="]
64
65    # Load QFT circuit from MQT Bench
66    benchmark = MQTBenchCircuit(circuit_type="qft", num_qubits=64)
67    circuit = benchmark.circuit()
68
69    output.append(f"Qubits: {benchmark.num_qubits}")
70    output.append(f"Gates: {benchmark.num_gates}")
71    output.append(f"Depth: {benchmark.depth}")
72
73    partitioner = SpectralPartitioner(network=None, num_partitions=2)
74    assignments = partitioner.partition(circuit)
75
76    output.extend(
77        partitioning_result_description(
78            "Spectral (Fiedler Vector)", assignments, benchmark.num_gates
79        )
80    )
81
82    print("\n".join(output))  # noqa: T201
83
84
85if __name__ == "__main__":
86    spectral_partition_qft_example()