def test_named_qid_range(): qids = cirq.NamedQid.range(2, prefix='a', dimension=3) assert qids == [ cirq.NamedQid('a0', dimension=3), cirq.NamedQid('a1', dimension=3) ] qids = cirq.NamedQid.range(-1, 4, 2, prefix='a', dimension=3) assert qids == [ cirq.NamedQid('a-1', dimension=3), cirq.NamedQid('a1', dimension=3), cirq.NamedQid('a3', dimension=3), ] qids = cirq.NamedQid.range(2, prefix='a', dimension=4) assert qids == [ cirq.NamedQid('a0', dimension=4), cirq.NamedQid('a1', dimension=4) ] qids = cirq.NamedQid.range(-1, 4, 2, prefix='a', dimension=4) assert qids == [ cirq.NamedQid('a-1', dimension=4), cirq.NamedQid('a1', dimension=4), cirq.NamedQid('a3', dimension=4), ]
def test_empty(): q0 = cirq.NamedQid('q0', dimension=2) q1 = cirq.NamedQid('q1', dimension=3) q2 = cirq.NamedQid('q2', dimension=5) circuit = cirq.Circuit() for initial_state in range(2 * 3 * 5): assert_same_output_as_dense( circuit=circuit, qubit_order=[q0, q1, q2], initial_state=initial_state )
def test_expectation_higher_dims(): qubit = cirq.NamedQid('q0', dimension=2) qutrit = cirq.NamedQid('q1', dimension=3) with pytest.raises(ValueError, match="Only qubits are supported"): cirq.ProjectorString({qutrit: 0}) d = cirq.ProjectorString({qubit: 0}) with pytest.raises(ValueError, match="Only qubits are supported"): _ = (d.expectation_from_state_vector(np.zeros(2 * 3), { qubit: 0, qutrit: 0 }), )
def test_named_qubit_str(): q = cirq.NamedQubit('a') assert q.name == 'a' assert str(q) == 'a' qid = cirq.NamedQid('a', dimension=3) assert qid.name == 'a' assert str(qid) == 'a (d=3)'
def test_init(): q = cirq.NamedQubit('a') assert q.name == 'a' q = cirq.NamedQid('a', dimension=3) assert q.name == 'a' assert q.dimension == 3
def test_to_json(): assert cirq.NamedQubit('c')._json_dict_() == {'name': 'c'} assert cirq.NamedQid('c', dimension=3)._json_dict_() == { 'name': 'c', 'dimension': 3 }
def test_measurement_str(): q0 = cirq.NamedQid('q0', dimension=3) circuit = cirq.Circuit(cirq.measure(q0)) simulator = ccq.mps_simulator.MPSSimulator() result = simulator.run(circuit, repetitions=7) assert str(result) == "q0 (d=3)=0000000"
def test_probs_dont_sum_up_to_one(): q0 = cirq.NamedQid('q0', dimension=2) circuit = cirq.Circuit(cirq.measure(q0)) simulator = ccq.mps_simulator.MPSSimulator(sum_prob_atol=-0.5) with pytest.raises(ValueError, match="Sum of probabilities exceeds tolerance"): simulator.run(circuit, repetitions=1)
def test_repr(): def test_repr(qid: _MeasurementQid): cirq.testing.assert_equivalent_repr(qid, global_vals={'_MeasurementQid': _MeasurementQid}) test_repr(_MeasurementQid('a', cirq.LineQubit(0))) test_repr(_MeasurementQid('a', cirq.NamedQubit('x'))) test_repr(_MeasurementQid('a', cirq.NamedQid('x', 4))) test_repr(_MeasurementQid('a', cirq.GridQubit(2, 3))) test_repr(_MeasurementQid('0:1:a', cirq.LineQid(9, 4)))
def test_to_json(): assert cirq.NamedQubit('c')._json_dict_() == { 'cirq_type': 'NamedQubit', 'name': 'c', } assert cirq.NamedQid('c', dimension=3)._json_dict_() == { 'cirq_type': 'NamedQid', 'name': 'c', 'dimension': 3, }
def test_named_qubit_order(): order = cirq.testing.OrderTester() order.add_ascending( cirq.NamedQid('', dimension=1), cirq.NamedQubit(''), cirq.NamedQid('', dimension=3), cirq.NamedQid('1', dimension=1), cirq.NamedQubit('1'), cirq.NamedQid('1', dimension=3), cirq.NamedQid('a', dimension=1), cirq.NamedQubit('a'), cirq.NamedQid('a', dimension=3), cirq.NamedQid('a00000000', dimension=1), cirq.NamedQubit('a00000000'), cirq.NamedQid('a00000000', dimension=3), cirq.NamedQid('a00000000:8', dimension=1), cirq.NamedQubit('a00000000:8'), cirq.NamedQid('a00000000:8', dimension=3), cirq.NamedQid('a9', dimension=1), cirq.NamedQubit('a9'), cirq.NamedQid('a9', dimension=3), cirq.NamedQid('a09', dimension=1), cirq.NamedQubit('a09'), cirq.NamedQid('a09', dimension=3), cirq.NamedQid('a10', dimension=1), cirq.NamedQubit('a10'), cirq.NamedQid('a10', dimension=3), cirq.NamedQid('a11', dimension=1), cirq.NamedQubit('a11'), cirq.NamedQid('a11', dimension=3), cirq.NamedQid('aa', dimension=1), cirq.NamedQubit('aa'), cirq.NamedQid('aa', dimension=3), cirq.NamedQid('ab', dimension=1), cirq.NamedQubit('ab'), cirq.NamedQid('ab', dimension=3), cirq.NamedQid('b', dimension=1), cirq.NamedQubit('b'), cirq.NamedQid('b', dimension=3), ) order.add_ascending_equivalence_group( cirq.NamedQubit('c'), cirq.NamedQubit('c'), cirq.NamedQid('c', dimension=2), cirq.NamedQid('c', dimension=2), )
def test_named_qubit_repr(): q = cirq.NamedQubit('a') assert repr(q) == "cirq.NamedQubit('a')" qid = cirq.NamedQid('a', dimension=3) assert repr(qid) == "cirq.NamedQid('a', dimension=3)"
class TestCircuitRouting: @pytest.fixture(scope='class') def qubits(self): return [ cirq.NamedQubit('Alice'), cirq.NamedQubit('Bob'), cirq.NamedQubit('Charlie'), cirq.NamedQubit('Dan'), cirq.NamedQubit('Eve'), cirq.NamedQubit('Faythe'), cirq.NamedQubit('Grace'), cirq.NamedQubit('Heidi'), cirq.NamedQubit('Ivan'), cirq.NamedQubit('Judy'), cirq.NamedQubit('Kiuas'), cirq.NamedQubit('Leon'), cirq.NamedQubit('Mallory'), cirq.NamedQubit('Niaj'), cirq.NamedQubit('Olivia'), cirq.NamedQubit('Peggy'), cirq.NamedQubit('Quant'), cirq.NamedQubit('Rupert'), cirq.NamedQubit('Sybil'), cirq.NamedQubit('Trent') ] def test_routing_circuit_too_large(self, apollo): """The circuit must fit on the device. """ qubits = cirq.NamedQubit.range(0, 21, prefix='qubit_') circuit = cirq.Circuit([cirq.X(q) for q in qubits]) with pytest.raises( ValueError, match= 'Number of logical qubits is greater than number of physical qubits' ): apollo.route_circuit(circuit) def test_routing_without_SWAPs(self, apollo, qubits): """Circuit graph can be embedded in the Apollo connectivity graph, no SWAPs needed. """ circuit = cirq.Circuit(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[2:4])) new = apollo.route_circuit(circuit) assert len(new.all_qubits()) == 4 assert new.all_qubits() <= set(apollo.qubits) # assert len(new) == len(circuit) # TODO at the moment the routing algo may add unnecessary SWAPs def test_routing_needs_SWAPs(self, apollo, qubits): """Circuit has direct cyclic connectivity with 3 qubits, Apollo doesn't, so SWAPs are needed. """ circuit = cirq.Circuit(cirq.CZ(qubits[0], qubits[1]), cirq.CZ(qubits[0], qubits[2]), cirq.CZ(qubits[1], qubits[2])) new = apollo.route_circuit(circuit) assert len(new.all_qubits()) >= 3 # routing algo may use more qubits assert new.all_qubits() <= set(apollo.qubits) assert len(new) == 4 # a SWAP gate was added # SWAPs added by routing can be decomposed with pytest.raises( ValueError, match= 'Unsupported gate type: cirq.contrib.acquaintance.SwapPermutationGate()' ): apollo.validate_circuit(new) decomposed = apollo.decompose_circuit(new) apollo.validate_circuit(decomposed) def test_valid_routed_circuit(self, apollo, qubits): """A valid routed circuit should pass validation.""" circuit = cirq.Circuit(cirq.CZ(qubits[0], qubits[1]), cirq.CZ(qubits[0], qubits[2]), cirq.CZ(qubits[0], qubits[3]), cirq.CZ(qubits[0], qubits[4]), cirq.CZ(qubits[0], qubits[5])) routed_circuit = apollo.route_circuit(circuit) valid_circuit = apollo.decompose_circuit(routed_circuit) apollo.validate_circuit(valid_circuit) @pytest.mark.parametrize('qid', [ cirq.LineQubit(4), cirq.GridQubit(5, 6), cirq.NamedQid('Quentin', dimension=2), cirq.LineQid(4, dimension=2), cirq.GridQid(5, 6, dimension=2), ]) def test_routing_with_qids(self, apollo, qid): """Routing can handle all kinds of Qid types, not just NamedQubit. """ q = cirq.NamedQubit('Alice') circuit = cirq.Circuit( cirq.X(q), cirq.Y(qid), cirq.CZ(q, qid), ) new = apollo.route_circuit(circuit) assert len(new.all_qubits()) == 2 assert new.all_qubits() <= set(apollo.qubits) def test_routed_measurements(self, apollo, qubits): circuit = cirq.Circuit( cirq.CZ(qubits[0], qubits[2]), cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[1:3]), cirq.measure(qubits[0], key='mk0'), cirq.measure(qubits[1], key='mk1'), cirq.measure(qubits[2], key='mk2'), ) swap_network = apollo.route_circuit(circuit, return_swap_network=True) circuit_routed = swap_network.circuit mapping = { k.name: v.name for k, v in swap_network.final_mapping().items() } # physical name to logical name assert circuit_routed.are_all_measurements_terminal() assert circuit_routed.all_measurement_key_names() == { 'mk0', 'mk1', 'mk2' } # Check that measurements in the routed circuit are mapped to correct qubits measurements = [ op for _, op, _ in circuit_routed.findall_operations_with_gate_type( cirq.MeasurementGate) ] mk_to_physical_name = { op.gate.key: op.qubits[0].name for op in measurements } assert all(len(op.qubits) == 1 for op in measurements) assert mapping[mk_to_physical_name['mk0']] == 'Alice' assert mapping[mk_to_physical_name['mk1']] == 'Bob' assert mapping[mk_to_physical_name['mk2']] == 'Charlie' def test_routing_with_multi_qubit_measurements(self, apollo, qubits): circuit = cirq.Circuit( cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[1:3]), cirq.CZ(*qubits[2:4]), cirq.CZ(*qubits[3:5]), cirq.CZ(*qubits[4:6]), cirq.CZ(*qubits[5:7]), cirq.CZ(*qubits[6:8]), cirq.CZ(*qubits[7:9]), cirq.CZ(*qubits[8:10]), cirq.CZ(*qubits[9:11]), cirq.CZ(*qubits[10:12]), cirq.CZ(*qubits[11:13]), cirq.CZ(*qubits[12:14]), cirq.CZ(*qubits[13:15]), cirq.CZ(*qubits[14:16]), cirq.CZ(*qubits[15:17]), cirq.CZ(*qubits[16:18]), cirq.CZ(*qubits[17:19]), cirq.CZ(*qubits[18:20]), cirq.X(qubits[4]), cirq.CZ(qubits[0], qubits[2]), cirq.CZ(qubits[1], qubits[3]), cirq.CZ(qubits[2], qubits[4]), cirq.CZ(qubits[3], qubits[5]), cirq.CZ(qubits[4], qubits[6]), cirq.CZ(qubits[5], qubits[7]), cirq.CZ(qubits[6], qubits[8]), cirq.CZ(qubits[7], qubits[9]), cirq.CZ(qubits[8], qubits[10]), cirq.CZ(qubits[9], qubits[11]), cirq.CZ(qubits[10], qubits[12]), cirq.measure(*qubits[0:2], key='m1'), cirq.measure(*qubits[2:20], key='m2')) new = apollo.route_circuit(circuit) assert new.all_qubits() == set(apollo.qubits) # Test that all measurements exist. assert new.all_measurement_key_names() == {'m1', 'm2'} # Test that temporary identity gates have been removed assert not list(new.findall_operations_with_gate_type(IdentityGate)) def test_routing_with_nonterminal_measurements_raises_error(self, apollo): q = cirq.NamedQubit('q1') circuit = cirq.Circuit(cirq.measure(q, key='m'), cirq.Y(q)) with pytest.raises( ValueError, match='Non-terminal measurements are not supported'): apollo.route_circuit(circuit)
class TestCircuitRouting: @pytest.fixture(scope='class') def qubits(self): return [ cirq.NamedQubit('Alice'), cirq.NamedQubit('Bob'), cirq.NamedQubit('Charlie'), cirq.NamedQubit('Dan'), cirq.NamedQubit('Eve') ] def test_routing_circuit_too_large(self, adonis): """The circuit must fit on the device. """ qubits = cirq.NamedQubit.range(0, 6, prefix='qubit_') circuit = cirq.Circuit([cirq.X(q) for q in qubits]) with pytest.raises( ValueError, match= 'Number of logical qubits is greater than number of physical qubits' ): adonis.route_circuit(circuit) def test_routing_without_SWAPs(self, adonis, qubits): """Circuit graph can be embedded in the Adonis connectivity graph, no SWAPs needed. """ circuit = cirq.Circuit( cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[1:3]), ) new = adonis.route_circuit(circuit) assert len(new.all_qubits()) == 3 assert new.all_qubits() <= set(adonis.qubits) # assert len(new) == len(circuit) # TODO at the moment the routing algo may add unnecessary SWAPs def test_routing_needs_SWAPs(self, adonis, qubits): """Circuit has cyclic connectivity, Adonis doesn't, so SWAPs are needed. """ circuit = cirq.Circuit( cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[1:3]), cirq.CZ(qubits[0], qubits[2]), ) new = adonis.route_circuit(circuit) assert len(new.all_qubits()) == 3 assert new.all_qubits() <= set(adonis.qubits) assert len(new) == 4 # a SWAP gate was added # SWAPs added by routing can be decomposed with pytest.raises( ValueError, match= 'Unsupported gate type: cirq.contrib.acquaintance.SwapPermutationGate()' ): adonis.validate_circuit(new) decomposed = adonis.decompose_circuit(new) adonis.validate_circuit(decomposed) @pytest.mark.parametrize('qid', [ cirq.LineQubit(4), cirq.GridQubit(5, 6), cirq.NamedQid('Quentin', dimension=2), cirq.LineQid(4, dimension=2), cirq.GridQid(5, 6, dimension=2), ]) def test_routing_with_qids(self, adonis, qid): """Routing can handle all kinds of Qid types, not just NamedQubit. """ q = cirq.NamedQubit('Alice') circuit = cirq.Circuit( cirq.X(q), cirq.Y(qid), cirq.CZ(q, qid), ) new = adonis.route_circuit(circuit) assert len(new.all_qubits()) == 2 assert new.all_qubits() <= set(adonis.qubits) def test_routed_measurements(self, adonis, qubits): circuit = cirq.Circuit( cirq.CZ(qubits[0], qubits[2]), cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[1:3]), cirq.measure(qubits[0], key='mk0'), cirq.measure(qubits[1], key='mk1'), cirq.measure(qubits[2], key='mk2'), ) swap_network = adonis.route_circuit(circuit, return_swap_network=True) circuit_routed = swap_network.circuit mapping = { k.name: v.name for k, v in swap_network.final_mapping().items() } # physical name to logical name assert circuit_routed.are_all_measurements_terminal() assert circuit_routed.all_measurement_key_names() == { 'mk0', 'mk1', 'mk2' } # Check that measurements in the routed circuit are mapped to correct qubits measurements = [ op for _, op, _ in circuit_routed.findall_operations_with_gate_type( cirq.MeasurementGate) ] mk_to_physical_name = { op.gate.key: op.qubits[0].name for op in measurements } assert all(len(op.qubits) == 1 for op in measurements) assert mapping[mk_to_physical_name['mk0']] == 'Alice' assert mapping[mk_to_physical_name['mk1']] == 'Bob' assert mapping[mk_to_physical_name['mk2']] == 'Charlie' def test_routing_with_multi_qubit_measurements(self, adonis, qubits): circuit = cirq.Circuit(cirq.CZ(*qubits[0:2]), cirq.CZ(*qubits[1:3]), cirq.X(qubits[4]), cirq.CZ(qubits[0], qubits[2]), cirq.measure(*qubits[0:2], key='m1'), cirq.measure(*qubits[2:5], key='m2')) new = adonis.route_circuit(circuit) assert new.all_qubits() == set(adonis.qubits) # Test that all measurements exist. assert new.all_measurement_key_names() == {'m1', 'm2'} # Test that temporary identity gates have been removed assert not list(new.findall_operations_with_gate_type(IdentityGate)) def test_routing_with_nonterminal_measurements_raises_error(self, adonis): q = cirq.NamedQubit('q1') circuit = cirq.Circuit(cirq.measure(q, key='m'), cirq.Y(q)) with pytest.raises( ValueError, match='Non-terminal measurements are not supported'): adonis.route_circuit(circuit)
[ (cirq.X(cirq.NamedQubit('q1')), True), (cirq.X(cirq.NamedQubit('q1')) ** 0.5, True), (cirq.rx(np.pi)(cirq.NamedQubit('q1')), True), (cirq.rx(np.pi / 2)(cirq.NamedQubit('q1')), True), (cirq.Z(cirq.NamedQubit('q1')), True), (cirq.H(cirq.NamedQubit('q1')), True), (cirq.CNOT(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')), True), (cirq.SWAP(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')), True), (cirq.CCZ(cirq.NamedQubit('q1'), cirq.NamedQubit('q2'), cirq.NamedQubit('q3')), True), (cirq.ControlledGate(cirq.ControlledGate(cirq.CCZ))(*cirq.LineQubit.range(5)), True), (GateUsingWorkspaceForApplyUnitary()(cirq.NamedQubit('q1')), True), (GateAllocatingNewSpaceForResult()(cirq.NamedQubit('q1')), True), ( cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H),) * 2), qid_shape=(4,)).on( cirq.NamedQid("q", 4) ), False, ), ( cirq.MatrixGate(cirq.testing.random_unitary(4, random_state=1234)).on( cirq.NamedQubit('q1'), cirq.NamedQubit('q2') ), False, ), (cirq.XX(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')) ** sympy.Symbol("s"), True), (cirq.DiagonalGate(sympy.symbols("s1, s2")).on(cirq.NamedQubit("q")), False), ], ) def test_controlled_operation_is_consistent( gate: cirq.GateOperation, should_decompose_to_target: bool
(cirq.X(cirq.NamedQubit('q1'))**0.5, True), (cirq.rx(np.pi)(cirq.NamedQubit('q1')), True), (cirq.rx(np.pi / 2)(cirq.NamedQubit('q1')), True), (cirq.Z(cirq.NamedQubit('q1')), True), (cirq.H(cirq.NamedQubit('q1')), True), (cirq.CNOT(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')), True), (cirq.SWAP(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')), True), (cirq.CCZ(cirq.NamedQubit('q1'), cirq.NamedQubit('q2'), cirq.NamedQubit('q3')), True), (cirq.ControlledGate(cirq.ControlledGate( cirq.CCZ))(*cirq.LineQubit.range(5)), True), (GateUsingWorkspaceForApplyUnitary()(cirq.NamedQubit('q1')), True), (GateAllocatingNewSpaceForResult()(cirq.NamedQubit('q1')), True), ( cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H), ) * 2), qid_shape=(4, )).on(cirq.NamedQid("q", 4)), False, ), ( cirq.MatrixGate(cirq.testing.random_unitary( 4, random_state=1234)).on(cirq.NamedQubit('q1'), cirq.NamedQubit('q2')), False, ), (cirq.XX(cirq.NamedQubit('q1'), cirq.NamedQubit('q2'))** sympy.Symbol("s"), True), (cirq.DiagonalGate(sympy.symbols("s1, s2")).on( cirq.NamedQubit("q")), False), ], ) def test_controlled_operation_is_consistent(gate: cirq.GateOperation,