For a QAOA mixer that preserves the constraint "the selected edges form a
spanning tree" (a basis of the graph's graphic matroid), does the compiled
mixer circuit's gate count and depth grow, stay flat, or shrink as the
graph gets larger — for sparse graphs resembling real distribution
feeders? See docs/circuit-validity.md for what "the mixer" means
precisely and how its correctness was verified; this document covers graph
generation, move generation, and the measurement definitions.
Each instance is a synthetic feeder graph: n_nodes points placed
uniformly at random in the unit square, connected by a Euclidean minimum
spanning tree (a defensible model of a feeder's primary backbone — minimum
conductor length is a real design objective), plus k_ties extra edges
connecting the geometrically nearest node pairs not already in the tree
(modelling normally-open tie switches used for reconfiguration/
redundancy). Edge count is therefore exactly n_nodes - 1 + k_ties.
This is a synthetic model, not derived from real feeder topology data. It is chosen for reproducibility and structural resemblance to real feeders (sparse, spatial, mostly-tree-plus-a-few-ties) — not because it has been validated against utility network data.
k_ties is held fixed across the whole sweep (k_ties=3). This
matters for two reasons: (1) it keeps the graph's cycle space dimension
(number of independent cycles) constant regardless of n_nodes, which is
the property docs/circuit-validity.md argues keeps the witness-set size
bounded; (2) a fixed, small tie-switch count independent of feeder size is
also a reasonable model of real feeders — adding busbars doesn't
necessarily add proportionally more reconfiguration switches.
Minimum n_nodes is chosen, not arbitrary. With k_ties fixed, a
graph is only genuinely sparse once n_nodes is large enough that
n_qubits = n_nodes - 1 + k_ties is small relative to the C(n_nodes, 2)
possible edges. At n_nodes=4, k_ties=3, the graph has 6 edges on 4
nodes — that is the complete graph K4, not sparse at all. This was
caught by inspecting an anomalously expensive small instance during
development, not assumed away. scripts/run_scaling_study.py computes the
smallest n_nodes at which edge density (n_qubits / C(n_nodes,2)) drops
below 0.4, and starts the sweep there (n_nodes=8 for k_ties=3).
Qubit i = 1 iff edge i is closed. Feasible states are exactly the
spanning trees of the feeder graph (bases of its graphic matroid) — see
docs/mixer-construction.md for the full matroid formalization and
exact circuit-level derivation of the mixer built on it.
Feasible-set enumeration (scripts/graphs.py::enumerate_spanning_trees)
is brute force over all size-(n_nodes-1) edge subsets — C(n_qubits, k_ties), polynomial in n_nodes for the fixed, small k_ties this study
uses (verified against Kirchhoff's Matrix-Tree theorem during
development, not just assumed correct).
Candidate mixer moves are every pair of distinct edges (e,f)
(C(n_qubits,2), cheap since n_qubits stays small for sparse graphs).
Each candidate is checked against the actual enumerated spanning-tree set
— an edge pair that doesn't connect any previously-disconnected pair of
trees is discarded. Selected candidates are added greedily via a
union-find over the spanning-tree set until every spanning tree is
connected to every other by some sequence of selected moves (all
candidates have equal weight-2 cost here, since the matroid basis-exchange
axiom guarantees single-edge exchanges always suffice — no higher-weight
moves are needed, unlike more general constraint classes).
Each selected exchange becomes a circuit term: an RXX+RYY swap block on
qubits e,f, made conditional on a small "witness" qubit set when
(as is usually the case) the exchange's validity depends on other qubits —
see docs/circuit-validity.md for why this conditioning is necessary and
how it was derived and verified. This "small witness" property holds
for the synthetic graph family this sweep uses, but was found not to hold
on the whole real IEEE 33-bus graph — see docs/circuit-validity.md
and scripts/investigate_fundamental_cycles.py for why, and for how this
was resolved (zone decomposition, scripts/zone_decomposition.py,
restoring witness size ≤4 on every tested configuration). The results and
claims in this document are scoped to the synthetic sweep only; see
docs/circuit-validity.md and results/zone_decomposition_results.csv
for the real-feeder numbers. The full mixer circuit is the composition
of all selected terms, in edge-index order, at a single fixed Trotter
angle (beta=0.37, an arbitrary nonzero value — chosen only so that no
term's rotation accidentally vanishes; not tuned).
"Gate count" and "depth" are measured on the transpiled circuit, not estimated analytically:
- Backend:
qiskit.transpile,optimization_level=1. - Basis gates:
["cx", "rz", "sx", "x"]— representative of gate-model hardware (single-qubit rotations + a two-qubit entangler), not a claim about any specific device or vendor. - "CX count" = number of
cxoperations in the transpiled circuit (qiskit'scount_ops()); "depth" =QuantumCircuit.depth()on the same transpiled circuit. - "Qubit count" per instance =
n_qubits = n_nodes - 1 + k_ties(one qubit per feeder edge) — reported directly in every results row, never inferred.
- Measured, per instance, for every size in the sweep, across 5 random
seeds: qubit count, number of spanning trees, mixer term count, the
largest witness-set size used, whether any candidate exchange had to be
dropped (no small witness found), whether the resulting mixer is fully
connected, transpiled CX count, transpiled total gate count, and
transpiled depth. Every field is in
results/scaling_results.csv(per-seed) andresults/scaling_summary.csv(mean/min/max per size). - Not measured: hardware execution, noise, real device compilation (routing/layout for a specific coupling map), or QAOA solution quality (approximation ratio) — this study is scoped to mixer construction cost only, per the open question it answers.
- Range actually tested:
n_qubitsfrom 10 to 35 (n_nodes8 to 33), 5 seeds per size. This range is what brute-force spanning-tree enumeration keeps fast (well under a second per instance in this range); it is not extrapolated beyond what is inresults/.
See README.md's "How to reproduce" for the full, current command list
(this document doesn't duplicate it, to avoid the two drifting out of
sync as scripts are added). All scripts are deterministic (fixed seeds);
re-running should reproduce the committed CSVs exactly, modulo qiskit/
networkx version differences in transpilation.