Esempio n. 1
0
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),
    ]
Esempio n. 2
0
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
        )
Esempio n. 3
0
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
        }), )
Esempio n. 4
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)'
Esempio n. 5
0
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
Esempio n. 6
0
def test_to_json():
    assert cirq.NamedQubit('c')._json_dict_() == {'name': 'c'}

    assert cirq.NamedQid('c', dimension=3)._json_dict_() == {
        'name': 'c',
        'dimension': 3
    }
Esempio n. 7
0
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"
Esempio n. 8
0
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)
Esempio n. 9
0
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)))
Esempio n. 10
0
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,
    }
Esempio n. 11
0
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),
    )
Esempio n. 12
0
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)"
Esempio n. 13
0
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)
Esempio n. 14
0
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
Esempio n. 16
0
        (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,