|
15 | 15 | import numpy as np
|
16 | 16 | import pytest
|
17 | 17 | import sympy
|
| 18 | +from sympy.parsing import sympy_parser |
18 | 19 |
|
19 | 20 | import cirq
|
20 | 21 | from cirq.transformers.measurement_transformers import _ConfusionChannel, _MeasurementQid, _mod_add
|
@@ -79,6 +80,179 @@ def test_qudits():
|
79 | 80 | )
|
80 | 81 |
|
81 | 82 |
|
| 83 | +def test_sympy_control(): |
| 84 | + q0, q1 = cirq.LineQubit.range(2) |
| 85 | + circuit = cirq.Circuit( |
| 86 | + cirq.measure(q0, key='a'), |
| 87 | + cirq.X(q1).with_classical_controls(sympy.Symbol('a')), |
| 88 | + cirq.measure(q1, key='b'), |
| 89 | + ) |
| 90 | + assert_equivalent_to_deferred(circuit) |
| 91 | + deferred = cirq.defer_measurements(circuit) |
| 92 | + q_ma = _MeasurementQid('a', q0) |
| 93 | + cirq.testing.assert_same_circuits( |
| 94 | + deferred, |
| 95 | + cirq.Circuit( |
| 96 | + cirq.CX(q0, q_ma), |
| 97 | + cirq.CX(q_ma, q1), |
| 98 | + cirq.measure(q_ma, key='a'), |
| 99 | + cirq.measure(q1, key='b'), |
| 100 | + ), |
| 101 | + ) |
| 102 | + |
| 103 | + |
| 104 | +def test_sympy_qudits(): |
| 105 | + q0, q1 = cirq.LineQid.range(2, dimension=3) |
| 106 | + circuit = cirq.Circuit( |
| 107 | + cirq.measure(q0, key='a'), |
| 108 | + cirq.XPowGate(dimension=3).on(q1).with_classical_controls(sympy.Symbol('a')), |
| 109 | + cirq.measure(q1, key='b'), |
| 110 | + ) |
| 111 | + assert_equivalent_to_deferred(circuit) |
| 112 | + deferred = cirq.defer_measurements(circuit) |
| 113 | + q_ma = _MeasurementQid('a', q0) |
| 114 | + cirq.testing.assert_same_circuits( |
| 115 | + deferred, |
| 116 | + cirq.Circuit( |
| 117 | + _mod_add(q0, q_ma), |
| 118 | + cirq.XPowGate(dimension=3).on(q1).controlled_by(q_ma, control_values=[[1, 2]]), |
| 119 | + cirq.measure(q_ma, key='a'), |
| 120 | + cirq.measure(q1, key='b'), |
| 121 | + ), |
| 122 | + ) |
| 123 | + |
| 124 | + |
| 125 | +def test_sympy_control_complex(): |
| 126 | + q0, q1, q2 = cirq.LineQubit.range(3) |
| 127 | + circuit = cirq.Circuit( |
| 128 | + cirq.measure(q0, key='a'), |
| 129 | + cirq.measure(q1, key='b'), |
| 130 | + cirq.X(q2).with_classical_controls(sympy_parser.parse_expr('a >= b')), |
| 131 | + cirq.measure(q2, key='c'), |
| 132 | + ) |
| 133 | + assert_equivalent_to_deferred(circuit) |
| 134 | + deferred = cirq.defer_measurements(circuit) |
| 135 | + q_ma = _MeasurementQid('a', q0) |
| 136 | + q_mb = _MeasurementQid('b', q1) |
| 137 | + cirq.testing.assert_same_circuits( |
| 138 | + deferred, |
| 139 | + cirq.Circuit( |
| 140 | + cirq.CX(q0, q_ma), |
| 141 | + cirq.CX(q1, q_mb), |
| 142 | + cirq.ControlledOperation( |
| 143 | + [q_ma, q_mb], cirq.X(q2), cirq.SumOfProducts([[0, 0], [1, 0], [1, 1]]) |
| 144 | + ), |
| 145 | + cirq.measure(q_ma, key='a'), |
| 146 | + cirq.measure(q_mb, key='b'), |
| 147 | + cirq.measure(q2, key='c'), |
| 148 | + ), |
| 149 | + ) |
| 150 | + |
| 151 | + |
| 152 | +def test_sympy_control_complex_qudit(): |
| 153 | + q0, q1, q2 = cirq.LineQid.for_qid_shape((4, 2, 2)) |
| 154 | + circuit = cirq.Circuit( |
| 155 | + cirq.measure(q0, key='a'), |
| 156 | + cirq.measure(q1, key='b'), |
| 157 | + cirq.X(q2).with_classical_controls(sympy_parser.parse_expr('a > b')), |
| 158 | + cirq.measure(q2, key='c'), |
| 159 | + ) |
| 160 | + assert_equivalent_to_deferred(circuit) |
| 161 | + deferred = cirq.defer_measurements(circuit) |
| 162 | + q_ma = _MeasurementQid('a', q0) |
| 163 | + q_mb = _MeasurementQid('b', q1) |
| 164 | + cirq.testing.assert_same_circuits( |
| 165 | + deferred, |
| 166 | + cirq.Circuit( |
| 167 | + _mod_add(q0, q_ma), |
| 168 | + cirq.CX(q1, q_mb), |
| 169 | + cirq.ControlledOperation( |
| 170 | + [q_ma, q_mb], |
| 171 | + cirq.X(q2), |
| 172 | + cirq.SumOfProducts([[1, 0], [2, 0], [3, 0], [2, 1], [3, 1]]), |
| 173 | + ), |
| 174 | + cirq.measure(q_ma, key='a'), |
| 175 | + cirq.measure(q_mb, key='b'), |
| 176 | + cirq.measure(q2, key='c'), |
| 177 | + ), |
| 178 | + ) |
| 179 | + |
| 180 | + |
| 181 | +def test_multiple_sympy_control_complex(): |
| 182 | + q0, q1, q2 = cirq.LineQubit.range(3) |
| 183 | + circuit = cirq.Circuit( |
| 184 | + cirq.measure(q0, key='a'), |
| 185 | + cirq.measure(q1, key='b'), |
| 186 | + cirq.X(q2) |
| 187 | + .with_classical_controls(sympy_parser.parse_expr('a >= b')) |
| 188 | + .with_classical_controls(sympy_parser.parse_expr('a <= b')), |
| 189 | + cirq.measure(q2, key='c'), |
| 190 | + ) |
| 191 | + assert_equivalent_to_deferred(circuit) |
| 192 | + deferred = cirq.defer_measurements(circuit) |
| 193 | + q_ma = _MeasurementQid('a', q0) |
| 194 | + q_mb = _MeasurementQid('b', q1) |
| 195 | + cirq.testing.assert_same_circuits( |
| 196 | + deferred, |
| 197 | + cirq.Circuit( |
| 198 | + cirq.CX(q0, q_ma), |
| 199 | + cirq.CX(q1, q_mb), |
| 200 | + cirq.ControlledOperation( |
| 201 | + [q_ma, q_mb], cirq.X(q2), cirq.SumOfProducts([[0, 0], [1, 1]]) |
| 202 | + ), |
| 203 | + cirq.measure(q_ma, key='a'), |
| 204 | + cirq.measure(q_mb, key='b'), |
| 205 | + cirq.measure(q2, key='c'), |
| 206 | + ), |
| 207 | + ) |
| 208 | + |
| 209 | + |
| 210 | +def test_sympy_and_key_control(): |
| 211 | + q0, q1 = cirq.LineQubit.range(2) |
| 212 | + circuit = cirq.Circuit( |
| 213 | + cirq.measure(q0, key='a'), |
| 214 | + cirq.X(q1).with_classical_controls(sympy.Symbol('a')).with_classical_controls('a'), |
| 215 | + cirq.measure(q1, key='b'), |
| 216 | + ) |
| 217 | + assert_equivalent_to_deferred(circuit) |
| 218 | + deferred = cirq.defer_measurements(circuit) |
| 219 | + q_ma = _MeasurementQid('a', q0) |
| 220 | + cirq.testing.assert_same_circuits( |
| 221 | + deferred, |
| 222 | + cirq.Circuit( |
| 223 | + cirq.CX(q0, q_ma), |
| 224 | + cirq.CX(q_ma, q1), |
| 225 | + cirq.measure(q_ma, key='a'), |
| 226 | + cirq.measure(q1, key='b'), |
| 227 | + ), |
| 228 | + ) |
| 229 | + |
| 230 | + |
| 231 | +def test_sympy_control_multiqubit(): |
| 232 | + q0, q1, q2 = cirq.LineQubit.range(3) |
| 233 | + circuit = cirq.Circuit( |
| 234 | + cirq.measure(q0, q1, key='a'), |
| 235 | + cirq.X(q2).with_classical_controls(sympy_parser.parse_expr('a >= 2')), |
| 236 | + cirq.measure(q2, key='c'), |
| 237 | + ) |
| 238 | + assert_equivalent_to_deferred(circuit) |
| 239 | + deferred = cirq.defer_measurements(circuit) |
| 240 | + q_ma0 = _MeasurementQid('a', q0) |
| 241 | + q_ma1 = _MeasurementQid('a', q1) |
| 242 | + cirq.testing.assert_same_circuits( |
| 243 | + deferred, |
| 244 | + cirq.Circuit( |
| 245 | + cirq.CX(q0, q_ma0), |
| 246 | + cirq.CX(q1, q_ma1), |
| 247 | + cirq.ControlledOperation( |
| 248 | + [q_ma0, q_ma1], cirq.X(q2), cirq.SumOfProducts([[1, 0], [1, 1]]) |
| 249 | + ), |
| 250 | + cirq.measure(q_ma0, q_ma1, key='a'), |
| 251 | + cirq.measure(q2, key='c'), |
| 252 | + ), |
| 253 | + ) |
| 254 | + |
| 255 | + |
82 | 256 | def test_nocompile_context():
|
83 | 257 | q0, q1 = cirq.LineQubit.range(2)
|
84 | 258 | circuit = cirq.Circuit(
|
@@ -316,15 +490,6 @@ def test_repr(qid: _MeasurementQid):
|
316 | 490 | test_repr(_MeasurementQid('0:1:a', cirq.LineQid(9, 4)))
|
317 | 491 |
|
318 | 492 |
|
319 |
| -def test_sympy_control(): |
320 |
| - q0, q1 = cirq.LineQubit.range(2) |
321 |
| - circuit = cirq.Circuit( |
322 |
| - cirq.measure(q0, q1, key='a'), cirq.X(q1).with_classical_controls(sympy.Symbol('a')) |
323 |
| - ) |
324 |
| - with pytest.raises(ValueError, match='Only KeyConditions are allowed'): |
325 |
| - _ = cirq.defer_measurements(circuit) |
326 |
| - |
327 |
| - |
328 | 493 | def test_confusion_map():
|
329 | 494 | q0, q1 = cirq.LineQubit.range(2)
|
330 | 495 | circuit = cirq.Circuit(
|
|
0 commit comments