def test_diagram(): s = """ -----AB----- ----ABCD---- ---ABCDEF--- --ABCDEFGH-- -ABCDEFGHIJ- ABCDEFGHIJKL -CDEFGHIJKL- --EFGHIJKL-- ---GHIJKL--- ----IJKL---- -----KL----- """ assert len(cirq.GridQubit.from_diagram(s)) == 72 assert len(cirq.GridQid.from_diagram(s, dimension=3)) == 72 s2 = """ AB BA""" assert cirq.GridQubit.from_diagram(s2) == [ cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0), cirq.GridQubit(1, 1) ] assert cirq.GridQid.from_diagram(s2, dimension=3) == [ cirq.GridQid(0, 0, dimension=3), cirq.GridQid(0, 1, dimension=3), cirq.GridQid(1, 0, dimension=3), cirq.GridQid(1, 1, dimension=3) ] with pytest.raises(ValueError, match="Input string has invalid character"): cirq.GridQubit.from_diagram('@')
def test_eq(): eq = cirq.testing.EqualsTester() eq.make_equality_group(lambda: cirq.GridQubit(0, 0), lambda: cirq.GridQid(0, 0, dimension=2)) eq.make_equality_group(lambda: cirq.GridQubit(1, 0), lambda: cirq.GridQid(1, 0, dimension=2)) eq.make_equality_group(lambda: cirq.GridQubit(0, 1), lambda: cirq.GridQid(0, 1, dimension=2)) eq.make_equality_group(lambda: cirq.GridQid(0, 0, dimension=3))
def test_cmp_failure(): with pytest.raises(TypeError, match='not supported between instances'): _ = 0 < cirq.GridQubit(0, 0) with pytest.raises(TypeError, match='not supported between instances'): _ = cirq.GridQubit(0, 0) < 0 with pytest.raises(TypeError, match='not supported between instances'): _ = 0 < cirq.GridQid(1, 1, dimension=3) with pytest.raises(TypeError, match='not supported between instances'): _ = cirq.GridQid(1, 1, dimension=3) < 0
def test_square(): assert cirq.GridQubit.square(2, top=1, left=1) == [ cirq.GridQubit(1, 1), cirq.GridQubit(1, 2), cirq.GridQubit(2, 1), cirq.GridQubit(2, 2) ] assert cirq.GridQubit.square(2) == [ cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0), cirq.GridQubit(1, 1) ] assert cirq.GridQid.square(2, top=1, left=1, dimension=3) == [ cirq.GridQid(1, 1, dimension=3), cirq.GridQid(1, 2, dimension=3), cirq.GridQid(2, 1, dimension=3), cirq.GridQid(2, 2, dimension=3) ] assert cirq.GridQid.square(2, dimension=3) == [ cirq.GridQid(0, 0, dimension=3), cirq.GridQid(0, 1, dimension=3), cirq.GridQid(1, 0, dimension=3), cirq.GridQid(1, 1, dimension=3) ]
def test_json(): q0, q1 = cirq.GridQubit.rect(1, 2) qtrit = cirq.GridQid(1, 2, dimension=3) cirq.testing.assert_json_roundtrip_works(cirq.wait(q0, nanos=10)) cirq.testing.assert_json_roundtrip_works(cirq.wait(q0, q1, nanos=10)) cirq.testing.assert_json_roundtrip_works(cirq.wait(qtrit, nanos=10)) cirq.testing.assert_json_roundtrip_works(cirq.wait(qtrit, q1, nanos=10))
def test_to_json(): assert cirq.GridQubit(5, 6)._json_dict_() == {'row': 5, 'col': 6} assert cirq.GridQid(5, 6, dimension=3)._json_dict_() == { 'row': 5, 'col': 6, 'dimension': 3 }
def test_init(): q = cirq.GridQubit(3, 4) assert q.row == 3 assert q.col == 4 q = cirq.GridQid(1, 2, dimension=3) assert q.row == 1 assert q.col == 2 assert q.dimension == 3
def test_immutable(): with pytest.raises(AttributeError, match="can't set attribute"): q = cirq.GridQubit(1, 2) q.col = 3 with pytest.raises(AttributeError, match="can't set attribute"): q = cirq.GridQubit(1, 2) q.row = 3 with pytest.raises(AttributeError, match="can't set attribute"): q = cirq.GridQid(1, 2, dimension=3) q.col = 3 with pytest.raises(AttributeError, match="can't set attribute"): q = cirq.GridQid(1, 2, dimension=3) q.row = 3 with pytest.raises(AttributeError, match="can't set attribute"): q = cirq.GridQid(1, 2, dimension=3) q.dimension = 3
def test_to_json(): assert cirq.GridQubit(5, 6)._json_dict_() == { 'cirq_type': 'GridQubit', 'row': 5, 'col': 6, } assert cirq.GridQid(5, 6, dimension=3)._json_dict_() == { 'cirq_type': 'GridQid', 'row': 5, 'col': 6, 'dimension': 3, }
def test_cmp(): order = cirq.testing.OrderTester() order.add_ascending_equivalence_group(cirq.GridQubit(0, 0), cirq.GridQid(0, 0, dimension=2)) order.add_ascending( cirq.GridQid(0, 0, dimension=3), cirq.GridQid(0, 1, dimension=1), cirq.GridQubit(0, 1), cirq.GridQid(0, 1, dimension=3), cirq.GridQid(1, 0, dimension=1), cirq.GridQubit(1, 0), cirq.GridQid(1, 0, dimension=3), cirq.GridQid(1, 1, dimension=1), cirq.GridQubit(1, 1), cirq.GridQid(1, 1, dimension=3), )
def test_addition_subtraction_type_error(): with pytest.raises(TypeError, match="bort"): _ = cirq.GridQubit(5, 3) + "bort" with pytest.raises(TypeError, match="bort"): _ = cirq.GridQubit(5, 3) - "bort" with pytest.raises(TypeError, match="bort"): _ = cirq.GridQid(5, 3, dimension=3) + "bort" with pytest.raises(TypeError, match="bort"): _ = cirq.GridQid(5, 3, dimension=3) - "bort" with pytest.raises(TypeError, match="Can only add GridQids with identical dimension."): _ = cirq.GridQid(5, 3, dimension=3) + cirq.GridQid(3, 5, dimension=4) with pytest.raises(TypeError, match="Can only subtract GridQids with identical dimension."): _ = cirq.GridQid(5, 3, dimension=3) - cirq.GridQid(3, 5, dimension=4)
def test_rect(): assert cirq.GridQubit.rect(1, 2, top=5, left=6) == [cirq.GridQubit(5, 6), cirq.GridQubit(5, 7)] assert cirq.GridQubit.rect(2, 2) == [ cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0), cirq.GridQubit(1, 1), ] assert cirq.GridQid.rect(1, 2, top=5, left=6, dimension=3) == [ cirq.GridQid(5, 6, dimension=3), cirq.GridQid(5, 7, dimension=3), ] assert cirq.GridQid.rect(2, 2, dimension=3) == [ cirq.GridQid(0, 0, dimension=3), cirq.GridQid(0, 1, dimension=3), cirq.GridQid(1, 0, dimension=3), cirq.GridQid(1, 1, 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') ] 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)
def test_repr(): cirq.testing.assert_equivalent_repr(cirq.GridQubit(5, 2)) cirq.testing.assert_equivalent_repr(cirq.GridQid(5, 2, dimension=3))
def test_str(): assert str(cirq.GridQubit(5, 2)) == '(5, 2)' assert str(cirq.GridQid(5, 2, dimension=3)) == '(5, 2) (d=3)'
def test_neg(): assert -cirq.GridQubit(1, 2) == cirq.GridQubit(-1, -2) assert -cirq.GridQid(1, 2, dimension=3) == cirq.GridQid(-1, -2, dimension=3)
def test_addition_subtraction(): # GridQubits assert cirq.GridQubit(1, 2) + (2, 5) == cirq.GridQubit(3, 7) assert cirq.GridQubit(1, 2) + (0, 0) == cirq.GridQubit(1, 2) assert cirq.GridQubit(1, 2) + (-1, 0) == cirq.GridQubit(0, 2) assert cirq.GridQubit(1, 2) - (2, 5) == cirq.GridQubit(-1, -3) assert cirq.GridQubit(1, 2) - (0, 0) == cirq.GridQubit(1, 2) assert cirq.GridQubit(1, 2) - (-1, 0) == cirq.GridQubit(2, 2) assert (2, 5) + cirq.GridQubit(1, 2) == cirq.GridQubit(3, 7) assert (2, 5) - cirq.GridQubit(1, 2) == cirq.GridQubit(1, 3) assert cirq.GridQubit(1, 2) + cirq.GridQubit(3, 5) == cirq.GridQubit(4, 7) assert cirq.GridQubit(3, 5) - cirq.GridQubit(2, 1) == cirq.GridQubit(1, 4) assert cirq.GridQubit(1, -2) + cirq.GridQubit(3, 5) == cirq.GridQubit(4, 3) # GridQids assert cirq.GridQid(1, 2, dimension=3) + (2, 5) == cirq.GridQid( 3, 7, dimension=3) assert cirq.GridQid(1, 2, dimension=3) + (0, 0) == cirq.GridQid( 1, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) + (-1, 0) == cirq.GridQid( 0, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) - (2, 5) == cirq.GridQid( -1, -3, dimension=3) assert cirq.GridQid(1, 2, dimension=3) - (0, 0) == cirq.GridQid( 1, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) - (-1, 0) == cirq.GridQid( 2, 2, dimension=3) assert (2, 5) + cirq.GridQid(1, 2, dimension=3) == cirq.GridQid( 3, 7, dimension=3) assert (2, 5) - cirq.GridQid(1, 2, dimension=3) == cirq.GridQid( 1, 3, dimension=3) assert cirq.GridQid(1, 2, dimension=3) + cirq.GridQid( 3, 5, dimension=3) == cirq.GridQid(4, 7, dimension=3) assert cirq.GridQid(3, 5, dimension=3) - cirq.GridQid( 2, 1, dimension=3) == cirq.GridQid(1, 4, dimension=3) assert cirq.GridQid(1, -2, dimension=3) + cirq.GridQid( 3, 5, dimension=3) == cirq.GridQid(4, 3, 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)
def test_addition_subtraction_numpy_array(dtype): assert cirq.GridQubit(1, 2) + np.array( [1, 2], dtype=dtype) == cirq.GridQubit(2, 4) assert cirq.GridQubit(1, 2) + np.array( [0, 0], dtype=dtype) == cirq.GridQubit(1, 2) assert cirq.GridQubit(1, 2) + np.array( [-1, 0], dtype=dtype) == cirq.GridQubit(0, 2) assert cirq.GridQubit(1, 2) - np.array( [1, 2], dtype=dtype) == cirq.GridQubit(0, 0) assert cirq.GridQubit(1, 2) - np.array( [0, 0], dtype=dtype) == cirq.GridQubit(1, 2) assert cirq.GridQid(1, 2, dimension=3) - np.array( [-1, 0], dtype=dtype) == cirq.GridQid(2, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) + np.array( [1, 2], dtype=dtype) == cirq.GridQid(2, 4, dimension=3) assert cirq.GridQid(1, 2, dimension=3) + np.array( [0, 0], dtype=dtype) == cirq.GridQid(1, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) + np.array( [-1, 0], dtype=dtype) == cirq.GridQid(0, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) - np.array( [1, 2], dtype=dtype) == cirq.GridQid(0, 0, dimension=3) assert cirq.GridQid(1, 2, dimension=3) - np.array( [0, 0], dtype=dtype) == cirq.GridQid(1, 2, dimension=3) assert cirq.GridQid(1, 2, dimension=3) - np.array( [-1, 0], dtype=dtype) == cirq.GridQid(2, 2, dimension=3)
def test_circuit_info(): assert cirq.circuit_diagram_info(cirq.GridQubit( 5, 2)) == cirq.CircuitDiagramInfo(wire_symbols=('(5, 2)', )) assert cirq.circuit_diagram_info(cirq.GridQid( 5, 2, dimension=3)) == cirq.CircuitDiagramInfo( wire_symbols=('(5, 2) (d=3)', ))