|
18 | 18 | import sympy |
19 | 19 |
|
20 | 20 | import qsimcirq |
| 21 | +import qsimcirq.qsim_circuit |
21 | 22 |
|
22 | 23 |
|
23 | 24 | class NoiseTrigger(cirq.Gate): |
@@ -128,6 +129,26 @@ def _unitary_(self): |
128 | 129 | qsimSim.compute_amplitudes(cirq_circuit, bitstrings=[0b0, 0b1]) |
129 | 130 |
|
130 | 131 |
|
| 132 | +def test_translate_matrix_gate_too_big(): |
| 133 | + gate = cirq.MatrixGate(np.eye(128)) |
| 134 | + with pytest.raises( |
| 135 | + NotImplementedError, match="only up to 6-qubit gates are supported" |
| 136 | + ): |
| 137 | + qsimcirq.qsim_circuit._translate_MatrixGate(gate) |
| 138 | + |
| 139 | + |
| 140 | +def test_simulate_matrix_gate_too_big(): |
| 141 | + qubits = cirq.LineQubit.range(7) |
| 142 | + gate = cirq.MatrixGate(np.eye(128)) |
| 143 | + circuit = cirq.Circuit(gate.on(*qubits)) |
| 144 | + |
| 145 | + qsim_sim = qsimcirq.QSimSimulator() |
| 146 | + with pytest.raises( |
| 147 | + NotImplementedError, match="only up to 6-qubit gates are supported" |
| 148 | + ): |
| 149 | + qsim_sim.compute_amplitudes(circuit, bitstrings=[0b0, 0b1]) |
| 150 | + |
| 151 | + |
131 | 152 | def test_cirq_giant_identity(): |
132 | 153 | # Pick qubits. |
133 | 154 | a, b, c, d, e, f, g, h = [ |
@@ -180,6 +201,61 @@ def _decompose_(self, qubits): |
180 | 201 | assert result_hist[1] > 0 |
181 | 202 |
|
182 | 203 |
|
| 204 | +def test_translate_cirq_to_qtrajectory(): |
| 205 | + q0, q1 = cirq.LineQubit.range(2) |
| 206 | + |
| 207 | + # General circuit with unitary, mixture, and channel. |
| 208 | + circuit = cirq.Circuit( |
| 209 | + cirq.H(q0), |
| 210 | + cirq.CNOT(q0, q1), |
| 211 | + cirq.bit_flip(0.1)(q0), |
| 212 | + cirq.depolarize(0.1)(q1), |
| 213 | + ) |
| 214 | + qsim_circuit = qsimcirq.QSimCircuit(circuit) |
| 215 | + qsim_ncircuit, moment_indices = qsim_circuit.translate_cirq_to_qtrajectory() |
| 216 | + |
| 217 | + assert isinstance(qsim_ncircuit, qsimcirq.qsim.NoisyCircuit) |
| 218 | + assert qsim_ncircuit.num_qubits == 2 |
| 219 | + # The circuit has 3 moments, and 4 gates are translated in total. |
| 220 | + assert moment_indices == [1, 2, 4] |
| 221 | + |
| 222 | + # Edge case: empty circuit. |
| 223 | + circuit_empty = cirq.Circuit() |
| 224 | + qsim_circuit_empty = qsimcirq.QSimCircuit(circuit_empty) |
| 225 | + qsim_ncircuit_empty, moment_indices_empty = ( |
| 226 | + qsim_circuit_empty.translate_cirq_to_qtrajectory() |
| 227 | + ) |
| 228 | + |
| 229 | + assert isinstance(qsim_ncircuit_empty, qsimcirq.qsim.NoisyCircuit) |
| 230 | + assert qsim_ncircuit_empty.num_qubits == 0 |
| 231 | + assert moment_indices_empty == [] |
| 232 | + |
| 233 | + # Edge case: circuit with only unitary gates. |
| 234 | + circuit_unitary = cirq.Circuit(cirq.X(q0), cirq.H(q1)) |
| 235 | + qsim_circuit_unitary = qsimcirq.QSimCircuit(circuit_unitary) |
| 236 | + qsim_ncircuit_unitary, moment_indices_unitary = ( |
| 237 | + qsim_circuit_unitary.translate_cirq_to_qtrajectory() |
| 238 | + ) |
| 239 | + |
| 240 | + assert isinstance(qsim_ncircuit_unitary, qsimcirq.qsim.NoisyCircuit) |
| 241 | + assert qsim_ncircuit_unitary.num_qubits == 2 |
| 242 | + assert moment_indices_unitary == [2] |
| 243 | + |
| 244 | + # Edge case: unparseable operation. |
| 245 | + class UnparseableOp(cirq.Operation): |
| 246 | + @property |
| 247 | + def qubits(self): |
| 248 | + return (q0,) |
| 249 | + |
| 250 | + def with_qubits(self, *new_qubits): |
| 251 | + return self |
| 252 | + |
| 253 | + circuit_unparseable = cirq.Circuit(UnparseableOp()) |
| 254 | + qsim_circuit_unparseable = qsimcirq.QSimCircuit(circuit_unparseable) |
| 255 | + with pytest.raises(ValueError, match="Encountered unparseable op"): |
| 256 | + qsim_circuit_unparseable.translate_cirq_to_qtrajectory() |
| 257 | + |
| 258 | + |
183 | 259 | @pytest.mark.parametrize("mode", ["noiseless", "noisy"]) |
184 | 260 | def test_cirq_qsim_simulate(mode: str): |
185 | 261 | # Pick qubits. |
@@ -2196,3 +2272,21 @@ def test_1d_representation(): |
2196 | 2272 | want = np.array([0.0 - 0.5j, 0.0 + 0.5j, 0.0 - 0.5j, 0.0 + 0.5j]) |
2197 | 2273 | _, res, _ = qsim_sim.simulate_into_1d_array(c) |
2198 | 2274 | np.testing.assert_allclose(res, np.array(want, dtype=np.complex64)) |
| 2275 | + |
| 2276 | + |
| 2277 | +def test_get_seed(): |
| 2278 | + # Test range. |
| 2279 | + qsim_sim = qsimcirq.QSimSimulator(seed=42) |
| 2280 | + for _ in range(100): |
| 2281 | + seed = qsim_sim.get_seed() |
| 2282 | + assert 0 <= seed < 2**31 - 1 |
| 2283 | + |
| 2284 | + # Test determinism. |
| 2285 | + sim1 = qsimcirq.QSimSimulator(seed=42) |
| 2286 | + sim2 = qsimcirq.QSimSimulator(seed=42) |
| 2287 | + assert sim1.get_seed() == sim2.get_seed() |
| 2288 | + |
| 2289 | + # Test subsequent calls. |
| 2290 | + sim = qsimcirq.QSimSimulator(seed=42) |
| 2291 | + seeds = {sim.get_seed() for _ in range(10)} |
| 2292 | + assert len(seeds) > 1 |
0 commit comments