Skip to content

Commit 674eea2

Browse files
Copilotfgfuchs
andcommitted
Fix Grover circuit drawing: labeled Dicke†/Dicke boxes and clean register names
Co-authored-by: fgfuchs <2428162+fgfuchs@users.noreply.github.com>
1 parent a8511ae commit 674eea2

File tree

6 files changed

+47
-10
lines changed

6 files changed

+47
-10
lines changed

README.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,26 +171,37 @@ Assuming all-to-all connectivity of qubits, one can minimize the depth of the ci
171171

172172
Components can be freely composed ("lego style") to build more complex circuits without needing to configure qubit counts manually.
173173

174-
For example, a Grover mixer over 3 independent Dicke-2 sub-registers can be assembled like this:
174+
For example, a Grover mixer over 3 independent Dicke sub-registers (each with 4 qubits, Hamming weight k=2) can be assembled like this:
175175

176176
from qaoa import initialstates, mixers
177177

178-
dicke = initialstates.Dicke(2) # Dicke state with k=2 excitations
179-
grover = mixers.Grover(dicke) # Grover mixer over the Dicke feasible space
180-
tensor = initialstates.Tensor(grover, 3) # 3 independent copies (6 qubits total)
178+
dicke = initialstates.Dicke(2) # Dicke state with k=2 excitations
179+
dicke.setNumQubits(4) # 4-qubit register per block
180+
grover = mixers.Grover(dicke) # Grover mixer over the Dicke feasible space
181+
tensor = initialstates.Tensor(grover, 3) # 3 independent copies (12 qubits total)
181182

182183
tensor.create_circuit()
183184
tensor.circuit.draw('mpl')
184185

185-
`Dicke(k)` automatically sets `N_qubits = k` (the minimum needed register), and
186-
`Grover` inherits that qubit count from its sub-circuit, so no explicit
187-
`setNumQubits` call is required.
186+
`Grover` inherits the qubit count from its sub-circuit, so no extra `setNumQubits`
187+
call is needed for the mixer itself.
188188

189-
![Lego circuit](images/lego_circuit.png "Lego circuit: three Grover blocks on 6 qubits")
189+
![Lego circuit](images/lego_circuit.png "Lego circuit: three Grover blocks on 12 qubits")
190190

191191
Each sub-circuit is shown as a labelled block in the drawing so the "lego" structure
192192
is immediately visible.
193193

194+
To inspect the internal structure of a single Grover block, draw it directly:
195+
196+
grover.create_circuit()
197+
grover.circuit.draw('mpl')
198+
199+
![Grover circuit](images/grover_circuit.png "Grover mixer: Dicke† – X^n – C^{n-1}Phase – X^n – Dicke")
200+
201+
The Grover mixer is constructed as U_S† X^n C^{n-1}P X^n U_S, where the Dicke
202+
state-preparation circuit U_S and its inverse are each shown as a single labelled
203+
box (`Dicke†` / `Dicke`).
204+
194205
### Annotating circuits
195206

196207
Every component (initial state or mixer) carries a `label` attribute that is used as

images/grover_circuit.png

-3.78 KB
Loading

images/lego_circuit.png

-6.47 KB
Loading

qaoa/initialstates/tensor_initialstate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def create_circuit(self) -> None:
5050
sub_label = getattr(self.subcircuit, "label", self.subcircuit.__class__.__name__)
5151
sub_instr = self.subcircuit.circuit.to_instruction(label=sub_label)
5252

53-
qr = QuantumRegister(self.N_qubits)
53+
qr = QuantumRegister(self.N_qubits, name="q")
5454
self.circuit = QuantumCircuit(qr)
5555
n = self.subcircuit.N_qubits
5656
for i in range(self.num):

qaoa/mixers/grover_mixer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def create_circuit(self):
6363
sub_label = getattr(self.subcircuit, "label", self.subcircuit.__class__.__name__)
6464
n = self.subcircuit.N_qubits
6565

66-
qr = QuantumRegister(n)
66+
qr = QuantumRegister(n, name="q")
6767
self.circuit = QuantumCircuit(qr)
6868

6969
# US^\dagger — shown as a labelled box (e.g. "Dicke†")

unittests/test_mixers_initialstates.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ def test_grover_mixer_circuit_has_params(self):
4949
mixer.create_circuit()
5050
self.assertGreater(len(mixer.circuit.parameters), 0)
5151

52+
def test_grover_shows_labeled_subcircuit_instructions(self):
53+
"""Grover circuit should show US† and US as labeled instructions."""
54+
from qaoa.mixers import Grover
55+
from qaoa.initialstates import Dicke
56+
57+
grover = Grover(Dicke(2))
58+
grover.create_circuit()
59+
labels = [
60+
getattr(instr.operation, "label", None)
61+
for instr in grover.circuit.data
62+
]
63+
# The first instruction should be US† labelled "Dicke†"
64+
self.assertEqual(labels[0], "Dicke\u2020")
65+
# The last instruction should be US labelled "Dicke"
66+
self.assertEqual(labels[-1], "Dicke")
67+
68+
def test_grover_circuit_register_name(self):
69+
"""Grover circuit should use the register name 'q' for clean qubit labels."""
70+
from qaoa.mixers import Grover
71+
from qaoa.initialstates import Dicke
72+
73+
grover = Grover(Dicke(2))
74+
grover.create_circuit()
75+
reg_names = {q._register.name for q in grover.circuit.qubits}
76+
self.assertEqual(reg_names, {"q"})
77+
5278

5379
class TestXMultiAngleMixer(unittest.TestCase):
5480
"""Tests for the XMultiAngle mixer."""

0 commit comments

Comments
 (0)