55
66import cirq
77import stim
8+ import sympy
89
910from ._ii_gate import IIGate
1011
@@ -152,10 +153,15 @@ def _stim_append_classically_controlled_gate(
152153
153154 if len (op .classical_controls ) != 1 :
154155 raise NotImplementedError (f'Stim only supports single-control Pauli feedback, but got { op = } ' )
155- control , = op .classical_controls
156- if not isinstance (control , cirq .KeyCondition ):
157- raise NotImplementedError (f'Stim only supports single-control Pauli feedback (i.e. a `cirq.KeyCondition` control), but got { control = } ' )
158- control : cirq .KeyCondition
156+ controls : list [cirq .KeyCondition ] = []
157+ single_control , = op .classical_controls
158+ if isinstance (single_control , cirq .KeyCondition ):
159+ controls .append (single_control )
160+ elif isinstance (single_control , cirq .SympyCondition ) and isinstance (single_control .expr , sympy .Xor ) and all (isinstance (e , sympy .Symbol ) for e in single_control .expr .args ):
161+ for symbol in single_control .expr .args :
162+ controls .append (cirq .KeyCondition (key = cirq .MeasurementKey (str (symbol )), index = - 1 ))
163+ else :
164+ raise NotImplementedError (f'Stim only supports single-control Pauli feedback (i.e. a `cirq.KeyCondition` control), but got { single_control = } ' )
159165 gate = op .without_classical_controls ().gate
160166
161167 if gate == cirq .X :
@@ -168,24 +174,25 @@ def _stim_append_classically_controlled_gate(
168174 raise NotImplementedError (f'Stim only supports Pauli feedback, but got { op = } ' )
169175 assert len (targets ) == 1
170176
171- skips_left = control .index
172- for offset in range (len (measurement_key_lengths )):
173- m_key , m_len = measurement_key_lengths [- 1 - offset ]
174- if m_len != 1 :
175- raise NotImplementedError (f"multi-qubit measurement { m_key !r} " )
176- if m_key == control .key :
177- if skips_left > 0 :
178- skips_left -= 1
179- else :
180- rec_target = stim .target_rec (- 1 - offset )
181- break
182- else :
183- raise ValueError (
184- f"{ control !r} was processed before the measurement it referenced."
185- f" Make sure the referenced measurements keys are actually in the circuit, and come"
186- f" in an earlier moment (or earlier in the same moment's operation order)."
187- )
188- circuit .append (f"C{ stim_gate } " , [rec_target , targets [0 ]], tag = tag )
177+ for control in controls :
178+ skips_left = control .index
179+ for offset in range (len (measurement_key_lengths )):
180+ m_key , m_len = measurement_key_lengths [- 1 - offset ]
181+ if m_len != 1 :
182+ raise NotImplementedError (f"multi-qubit measurement { m_key !r} " )
183+ if m_key == control .key :
184+ if skips_left > 0 :
185+ skips_left -= 1
186+ else :
187+ rec_target = stim .target_rec (- 1 - offset )
188+ break
189+ else :
190+ raise ValueError (
191+ f"{ control !r} was processed before the measurement it referenced."
192+ f" Make sure the referenced measurements keys are actually in the circuit, and come"
193+ f" in an earlier moment (or earlier in the same moment's operation order)."
194+ )
195+ circuit .append (f"C{ stim_gate } " , [rec_target , targets [0 ]], tag = tag )
189196
190197
191198@functools .lru_cache (maxsize = 1 )
0 commit comments