Exemple #1
0
def test_rowsum():
    # Note: rowsum should not apply on two rows that anti-commute each other.
    t = cirq.CliffordTableau(num_qubits=2)
    # XI * IX ==> XX
    t._rowsum(0, 1)
    assert t.destabilizers()[0] == cirq.DensePauliString('XX', coefficient=1)

    # IX * ZI ==> ZX
    t._rowsum(1, 2)
    assert t.destabilizers()[1] == cirq.DensePauliString('ZX', coefficient=1)

    # ZI * IZ ==> ZZ
    t._rowsum(2, 3)
    assert t.stabilizers()[0] == cirq.DensePauliString('ZZ', coefficient=1)

    t = cirq.CliffordTableau(num_qubits=2)
    _S(t, 0)  # Table now are [YI, IX, ZI, IZ]
    _CNOT(t, 0, 1)  # Table now are [YX, IX, ZI, ZZ]

    # YX * ZZ ==> XY
    t._rowsum(0, 3)
    assert t.destabilizers()[0] == cirq.DensePauliString('XY', coefficient=1)

    # ZZ * XY ==> YX
    t._rowsum(3, 0)
    assert t.stabilizers()[1] == cirq.DensePauliString('YX', coefficient=1)
def test_clifford_decompose_two_qubits():
    """Two random instance for two qubits decomposition."""
    qubits = cirq.LineQubit.range(2)
    args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=2), qubits=qubits, prng=np.random.RandomState()
    )
    cirq.act_on(cirq.H, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.CNOT, args, qubits=[qubits[0], qubits[1]], allow_decompose=False)
    expect_circ = cirq.Circuit(cirq.H(qubits[0]), cirq.CNOT(qubits[0], qubits[1]))
    ops = cirq.decompose_clifford_tableau_to_operations(qubits, args.tableau)
    circ = cirq.Circuit(ops)
    assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)

    qubits = cirq.LineQubit.range(2)
    args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=2), qubits=qubits, prng=np.random.RandomState()
    )
    cirq.act_on(cirq.H, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.CNOT, args, qubits=[qubits[0], qubits[1]], allow_decompose=False)
    cirq.act_on(cirq.H, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.S, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.X, args, qubits=[qubits[1]], allow_decompose=False)
    expect_circ = cirq.Circuit(
        cirq.H(qubits[0]),
        cirq.CNOT(qubits[0], qubits[1]),
        cirq.H(qubits[0]),
        cirq.S(qubits[0]),
        cirq.X(qubits[1]),
    )

    ops = cirq.decompose_clifford_tableau_to_operations(qubits, args.tableau)
    circ = cirq.Circuit(ops)
    assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
def test_x_act_on_tableau():
    with pytest.raises(TypeError, match="Failed to act"):
        cirq.act_on(cirq.X, DummySimulationState(), qubits=())
    original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
    flipped_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=23)

    state = cirq.CliffordTableauSimulationState(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(5),
        prng=np.random.RandomState(),
    )

    cirq.act_on(cirq.X**0.5, state, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.X**0.5, state, [cirq.LineQubit(1)], allow_decompose=False)
    assert state.log_of_measurement_results == {}
    assert state.tableau == flipped_tableau

    cirq.act_on(cirq.X, state, [cirq.LineQubit(1)], allow_decompose=False)
    assert state.log_of_measurement_results == {}
    assert state.tableau == original_tableau

    cirq.act_on(cirq.X**3.5, state, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.X**3.5, state, [cirq.LineQubit(1)], allow_decompose=False)
    assert state.log_of_measurement_results == {}
    assert state.tableau == flipped_tableau

    cirq.act_on(cirq.X**2, state, [cirq.LineQubit(1)], allow_decompose=False)
    assert state.log_of_measurement_results == {}
    assert state.tableau == flipped_tableau

    foo = sympy.Symbol('foo')
    with pytest.raises(TypeError, match="Failed to act action on state"):
        cirq.act_on(cirq.X**foo, state, [cirq.LineQubit(1)])
Exemple #4
0
def test_to_clifford_tableau_util_function():

    tableau = cirq.ops.clifford_gate._to_clifford_tableau(
        x_to=cirq.PauliTransform(to=cirq.X, flip=False),
        z_to=cirq.PauliTransform(to=cirq.Z, flip=False),
    )
    assert tableau == cirq.CliffordTableau(num_qubits=1, initial_state=0)

    tableau = cirq.ops.clifford_gate._to_clifford_tableau(
        x_to=cirq.PauliTransform(to=cirq.X, flip=False),
        z_to=cirq.PauliTransform(to=cirq.Z, flip=True),
    )
    assert tableau == cirq.CliffordTableau(num_qubits=1, initial_state=1)

    tableau = cirq.ops.clifford_gate._to_clifford_tableau(
        rotation_map={
            cirq.X: cirq.PauliTransform(to=cirq.X, flip=False),
            cirq.Z: cirq.PauliTransform(to=cirq.Z, flip=False),
        }
    )
    assert tableau == cirq.CliffordTableau(num_qubits=1, initial_state=0)

    tableau = cirq.ops.clifford_gate._to_clifford_tableau(
        rotation_map={
            cirq.X: cirq.PauliTransform(to=cirq.X, flip=False),
            cirq.Z: cirq.PauliTransform(to=cirq.Z, flip=True),
        }
    )
    assert tableau == cirq.CliffordTableau(num_qubits=1, initial_state=1)

    with pytest.raises(ValueError):
        cirq.ops.clifford_gate._to_clifford_tableau()
Exemple #5
0
def test_stabilizers():
    # Note: the stabilizers are not unique for one state. We just use the one
    # produced by the tableau algorithm.
    # 1. Final state is |1>: Stabalized by -Z.
    t = cirq.CliffordTableau(num_qubits=1, initial_state=1)
    stabilizers = t.stabilizers()
    assert len(stabilizers) == 1
    assert stabilizers[0] == cirq.DensePauliString('Z', coefficient=-1)

    # 2. EPR pair -- Final state is |00> + |11>: Stabalized by XX and ZZ.
    t = cirq.CliffordTableau(num_qubits=2)
    _H(t, 0)
    _CNOT(t, 0, 1)
    stabilizers = t.stabilizers()
    assert len(stabilizers) == 2
    assert stabilizers[0] == cirq.DensePauliString('XX', coefficient=1)
    assert stabilizers[1] == cirq.DensePauliString('ZZ', coefficient=1)

    # 3. Uniform distribution: Stablized by XI and IX.
    t = cirq.CliffordTableau(num_qubits=2)
    _H(t, 0)
    _H(t, 1)
    stabilizers = t.stabilizers()
    assert len(stabilizers) == 2
    assert stabilizers[0] == cirq.DensePauliString('XI', coefficient=1)
    assert stabilizers[1] == cirq.DensePauliString('IX', coefficient=1)
def test_clifford_gate_from_tableau():
    t = cirq.CliffordGate.X.clifford_tableau
    assert cirq.CliffordGate.from_clifford_tableau(t) == cirq.CliffordGate.X

    t = cirq.CliffordGate.H.clifford_tableau
    assert cirq.CliffordGate.from_clifford_tableau(t) == cirq.CliffordGate.H

    t = cirq.CliffordGate.CNOT.clifford_tableau
    assert cirq.CliffordGate.from_clifford_tableau(t) == cirq.CliffordGate.CNOT

    with pytest.raises(
            ValueError,
            match='Input argument has to be a CliffordTableau instance.'):
        cirq.SingleQubitCliffordGate.from_clifford_tableau(123)

    with pytest.raises(
            ValueError,
            match="The number of qubit of input tableau should be 1"):
        t = cirq.CliffordTableau(num_qubits=2)
        cirq.SingleQubitCliffordGate.from_clifford_tableau(t)

    with pytest.raises(ValueError):
        t = cirq.CliffordTableau(num_qubits=1)
        t.xs = np.array([1, 1]).reshape(2, 1)
        t.zs = np.array([1, 1
                         ]).reshape(2,
                                    1)  # This violates the sympletic property.
        cirq.CliffordGate.from_clifford_tableau(t)

    with pytest.raises(
            ValueError,
            match="Input argument has to be a CliffordTableau instance."):
        cirq.CliffordGate.from_clifford_tableau(1)
Exemple #7
0
def test_clifford_gate_act_on_large_case():
    n, num_ops = 50, 1000  # because we don't need unitary, it is fast.
    gate_candidate = [
        cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.S, cirq.CNOT, cirq.CZ
    ]
    for seed in range(10):
        prng = np.random.RandomState(seed)
        t1 = cirq.CliffordTableau(num_qubits=n)
        t2 = cirq.CliffordTableau(num_qubits=n)
        qubits = cirq.LineQubit.range(n)
        args1 = cirq.ActOnCliffordTableauArgs(tableau=t1,
                                              qubits=qubits,
                                              prng=prng,
                                              log_of_measurement_results={})
        args2 = cirq.ActOnCliffordTableauArgs(tableau=t2,
                                              qubits=qubits,
                                              prng=prng,
                                              log_of_measurement_results={})
        ops = []
        for _ in range(num_ops):
            g = prng.randint(len(gate_candidate))
            indices = (prng.randint(n), ) if g < 5 else prng.choice(
                n, 2, replace=False)
            cirq.act_on(gate_candidate[g],
                        args1,
                        qubits=[qubits[i] for i in indices],
                        allow_decompose=False)
            ops.append(gate_candidate[g].on(*[qubits[i] for i in indices]))
        compiled_gate = cirq.CliffordGate.from_op_list(ops, qubits)
        cirq.act_on(compiled_gate, args2, qubits)

        assert args1.tableau == args2.tableau
def test_pad_tableau():
    tableau = cirq.CliffordTableau(num_qubits=1)
    padded_tableau = cirq.ops.clifford_gate._pad_tableau(
        tableau, num_qubits_after_padding=2, axes=[0])
    assert padded_tableau == cirq.CliffordTableau(num_qubits=2)

    tableau = cirq.CliffordTableau(num_qubits=1, initial_state=1)
    padded_tableau = cirq.ops.clifford_gate._pad_tableau(
        tableau, num_qubits_after_padding=1, axes=[0])
    assert padded_tableau == cirq.CliffordGate.X.clifford_tableau

    # Tableau for H
    # [0 1 0]
    # [1 0 0]
    tableau = cirq.CliffordGate.H.clifford_tableau
    padded_tableau = cirq.ops.clifford_gate._pad_tableau(
        tableau, num_qubits_after_padding=2, axes=[0])
    # fmt: off
    np.testing.assert_equal(
        padded_tableau.matrix().astype(np.int64),
        np.array([[0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]]),
    )
    # fmt: on
    np.testing.assert_equal(padded_tableau.rs.astype(np.int64), np.zeros(4))
    # The tableau of H again but pad for another ax
    tableau = cirq.CliffordGate.H.clifford_tableau
    padded_tableau = cirq.ops.clifford_gate._pad_tableau(
        tableau, num_qubits_after_padding=2, axes=[1])
    # fmt: off
    np.testing.assert_equal(
        padded_tableau.matrix().astype(np.int64),
        np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]]),
    )
    # fmt: on
    np.testing.assert_equal(padded_tableau.rs.astype(np.int64), np.zeros(4))
Exemple #9
0
def test_destabilizers():
    # Note: Like stablizers, the destabilizers are not unique for one state, too.
    # We just use the one produced by the tableau algorithm.
    # Under the clifford tableau algorithm, there are several properties that the
    # destablizers have to satisfy:
    #    1. destablizers[i] anti-commutes with stablizers[i]
    #    2. destablizers[i] commutes with destablizers[j] for j!= i
    #    3. destablizers[i] commutes with stablizers[j] for j!= i

    # 1. Final state is |1>: Stabalized by -Z.
    t = cirq.CliffordTableau(num_qubits=1, initial_state=1)
    destabilizers = t.destabilizers()
    assert len(destabilizers) == 1
    assert destabilizers[0] == cirq.DensePauliString('X', coefficient=1)

    # 2. EPR pair -- Final state is |00> + |11>: Stabalized by XX and ZZ.
    t = cirq.CliffordTableau(num_qubits=2)
    _H(t, 0)
    _CNOT(t, 0, 1)
    destabilizers = t.destabilizers()
    assert len(destabilizers) == 2
    assert destabilizers[0] == cirq.DensePauliString('ZI', coefficient=1)
    assert destabilizers[1] == cirq.DensePauliString('IX', coefficient=1)

    # 3. Uniform distribution: Stablized by XI and IX.
    t = cirq.CliffordTableau(num_qubits=2)
    _H(t, 0)
    _H(t, 1)
    destabilizers = t.destabilizers()
    assert len(destabilizers) == 2
    assert destabilizers[0] == cirq.DensePauliString('ZI', coefficient=1)
    assert destabilizers[1] == cirq.DensePauliString('IZ', coefficient=1)
Exemple #10
0
def test_x_act_on_tableau():
    with pytest.raises(TypeError, match="Failed to act"):
        cirq.act_on(cirq.X, object())
    original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
    flipped_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=23)

    args = cirq.ActOnCliffordTableauArgs(
        tableau=original_tableau.copy(),
        axes=[1],
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )

    cirq.act_on(cirq.X**0.5, args, allow_decompose=False)
    cirq.act_on(cirq.X**0.5, args, allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    cirq.act_on(cirq.X, args, allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == original_tableau

    cirq.act_on(cirq.X**3.5, args, allow_decompose=False)
    cirq.act_on(cirq.X**3.5, args, allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    cirq.act_on(cirq.X**2, args, allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    foo = sympy.Symbol('foo')
    with pytest.raises(TypeError, match="Failed to act action on state"):
        cirq.act_on(cirq.X**foo, args)
Exemple #11
0
def test_unitary_fallback():
    class UnitaryXGate(cirq.testing.SingleQubitGate):
        def _unitary_(self):
            return np.array([[0, 1], [1, 0]])

    class UnitaryYGate(cirq.Gate):
        def _qid_shape_(self) -> Tuple[int, ...]:
            return (2, )

        def _unitary_(self):
            return np.array([[0, -1j], [1j, 0]])

    original_tableau = cirq.CliffordTableau(num_qubits=3)
    args = cirq.CliffordTableauSimulationState(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(3),
        prng=np.random.RandomState(),
    )

    cirq.act_on(UnitaryXGate(), args, [cirq.LineQubit(1)])
    assert args.tableau == cirq.CliffordTableau(num_qubits=3, initial_state=2)

    args = cirq.CliffordTableauSimulationState(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(3),
        prng=np.random.RandomState(),
    )
    cirq.act_on(UnitaryYGate(), args, [cirq.LineQubit(1)])
    expected_args = cirq.CliffordTableauSimulationState(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(3),
        prng=np.random.RandomState(),
    )
    cirq.act_on(cirq.Y, expected_args, [cirq.LineQubit(1)])
    assert args.tableau == expected_args.tableau
Exemple #12
0
def test_clifford_gate_act_on_small_case():
    # Note this is also covered by the `from_op_list` one, etc.

    qubits = cirq.LineQubit.range(5)
    args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=5), qubits=qubits, prng=np.random.RandomState()
    )
    expected_args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=5), qubits=qubits, prng=np.random.RandomState()
    )
    cirq.act_on(cirq.H, expected_args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.CliffordGate.H, args, qubits=[qubits[0]], allow_decompose=False)
    assert args.tableau == expected_args.tableau

    cirq.act_on(cirq.CNOT, expected_args, qubits=[qubits[0], qubits[1]], allow_decompose=False)
    cirq.act_on(cirq.CliffordGate.CNOT, args, qubits=[qubits[0], qubits[1]], allow_decompose=False)
    assert args.tableau == expected_args.tableau

    cirq.act_on(cirq.H, expected_args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.CliffordGate.H, args, qubits=[qubits[0]], allow_decompose=False)
    assert args.tableau == expected_args.tableau

    cirq.act_on(cirq.S, expected_args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.CliffordGate.S, args, qubits=[qubits[0]], allow_decompose=False)
    assert args.tableau == expected_args.tableau

    cirq.act_on(cirq.X, expected_args, qubits=[qubits[2]], allow_decompose=False)
    cirq.act_on(cirq.CliffordGate.X, args, qubits=[qubits[2]], allow_decompose=False)
    assert args.tableau == expected_args.tableau
def test_clifford_decompose_by_reconstruction():
    """Validate the decomposition of random Clifford Tableau by reconstruction.

    This approach can validate large number of qubits compared with the unitary one.
    """
    n, num_ops = 100, 500
    gate_candidate = [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.S, cirq.CNOT, cirq.CZ]
    for seed in range(10):
        prng = np.random.RandomState(seed)
        t = cirq.CliffordTableau(num_qubits=n)
        qubits = cirq.LineQubit.range(n)
        expect_circ = cirq.Circuit()
        args = cirq.CliffordTableauSimulationState(tableau=t, qubits=qubits, prng=prng)
        for _ in range(num_ops):
            g = prng.randint(len(gate_candidate))
            indices = (prng.randint(n),) if g < 5 else prng.choice(n, 2, replace=False)
            cirq.act_on(
                gate_candidate[g], args, qubits=[qubits[i] for i in indices], allow_decompose=False
            )
            expect_circ.append(gate_candidate[g].on(*[qubits[i] for i in indices]))
        ops = cirq.decompose_clifford_tableau_to_operations(qubits, args.tableau)

        reconstruct_t = cirq.CliffordTableau(num_qubits=n)
        reconstruct_args = cirq.CliffordTableauSimulationState(
            tableau=reconstruct_t, qubits=qubits, prng=prng
        )
        for op in ops:
            cirq.act_on(op.gate, reconstruct_args, qubits=op.qubits, allow_decompose=False)

        assert t == reconstruct_t
Exemple #14
0
def test_tableau_then_with_bad_input():
    t1 = cirq.CliffordTableau(1)
    t2 = cirq.CliffordTableau(2)
    with pytest.raises(ValueError, match="Mismatched number of qubits of two tableaux: 1 vs 2."):
        t1.then(t2)

    with pytest.raises(TypeError):
        t1.then(cirq.X)
Exemple #15
0
def test_measurement():
    repetitions = 500
    prng = np.random.RandomState(seed=123456)

    # 1. The final state is |0>
    res = []
    for _ in range(repetitions):
        t = cirq.CliffordTableau(num_qubits=1)
        res.append(t._measure(q=0, prng=prng))
    assert all(res) == 0

    # 2. The final state is |1>
    res = []
    for _ in range(repetitions):
        t = cirq.CliffordTableau(num_qubits=1, initial_state=1)
        res.append(t._measure(q=0, prng=prng))
    assert all(res) == 1

    # 3. EPR pair -- The final state is |00> + |11>
    res = []
    for _ in range(repetitions):
        t = cirq.CliffordTableau(num_qubits=2)
        _H(t, 0)
        _CNOT(t, 0, 1)
        res.append(2 * t._measure(q=0, prng=prng) + t._measure(q=1, prng=prng))
    assert set(res) == set([0, 3])
    assert sum(np.asarray(res) == 0) >= (repetitions / 2 * 0.9)
    assert sum(np.asarray(res) == 3) >= (repetitions / 2 * 0.9)

    # 4. Uniform distribution -- The final state is |00> + |01> + |10> + |11>
    res = []
    for _ in range(repetitions):
        t = cirq.CliffordTableau(num_qubits=2)
        _H(t, 0)
        _H(t, 1)
        res.append(2 * t._measure(q=0, prng=prng) + t._measure(q=1, prng=prng))
    assert set(res) == set([0, 1, 2, 3])
    assert sum(np.asarray(res) == 0) >= (repetitions / 4 * 0.9)
    assert sum(np.asarray(res) == 1) >= (repetitions / 4 * 0.9)
    assert sum(np.asarray(res) == 2) >= (repetitions / 4 * 0.9)
    assert sum(np.asarray(res) == 3) >= (repetitions / 4 * 0.9)

    # 5. To cover usage of YY case. The final state is:
    #      0.5|00⟩ + 0.5j|01⟩ + 0.5j|10⟩ - 0.5|11⟩
    res = []
    for _ in range(repetitions):
        t = cirq.CliffordTableau(num_qubits=2)
        _H(t, 0)
        _H(t, 1)  # [ZI, IZ, XI, IX]
        _CNOT(t, 0, 1)  # [ZI, ZZ, XX, IX]
        _S(t, 0)  # [ZI, ZZ, YX, IX]
        _S(t, 1)  # [ZI, ZZ, YY, IY]
        res.append(2 * t._measure(q=0, prng=prng) + t._measure(q=1, prng=prng))
    assert set(res) == set([0, 1, 2, 3])
    assert sum(np.asarray(res) == 0) >= (repetitions / 4 * 0.9)
    assert sum(np.asarray(res) == 1) >= (repetitions / 4 * 0.9)
    assert sum(np.asarray(res) == 2) >= (repetitions / 4 * 0.9)
    assert sum(np.asarray(res) == 3) >= (repetitions / 4 * 0.9)
Exemple #16
0
def test_pad_tableau_bad_input():
    with pytest.raises(
        ValueError, match="Input axes of padding should match with the number of qubits"
    ):
        tableau = cirq.CliffordTableau(num_qubits=3)
        cirq.ops.clifford_gate._pad_tableau(tableau, num_qubits_after_padding=4, axes=[1, 2])

    with pytest.raises(
        ValueError, match='The number of qubits in the input tableau should not be larger than'
    ):
        tableau = cirq.CliffordTableau(num_qubits=3)
        cirq.ops.clifford_gate._pad_tableau(tableau, num_qubits_after_padding=2, axes=[0, 1, 2])
Exemple #17
0
def test_z_h_act_on_tableau():
    with pytest.raises(TypeError, match="Failed to act"):
        cirq.act_on(cirq.Z, DummyActOnArgs(), qubits=())
    with pytest.raises(TypeError, match="Failed to act"):
        cirq.act_on(cirq.H, DummyActOnArgs(), qubits=())
    original_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=31)
    flipped_tableau = cirq.CliffordTableau(num_qubits=5, initial_state=23)

    args = cirq.ActOnCliffordTableauArgs(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(5),
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )

    cirq.act_on(cirq.H, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.Z ** 0.5, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.Z ** 0.5, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.H, args, [cirq.LineQubit(1)], allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    cirq.act_on(cirq.H, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.Z, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.H, args, [cirq.LineQubit(1)], allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == original_tableau

    cirq.act_on(cirq.H, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.Z ** 3.5, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.Z ** 3.5, args, [cirq.LineQubit(1)], allow_decompose=False)
    cirq.act_on(cirq.H, args, [cirq.LineQubit(1)], allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    cirq.act_on(cirq.Z ** 2, args, [cirq.LineQubit(1)], allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    cirq.act_on(cirq.H ** 2, args, [cirq.LineQubit(1)], allow_decompose=False)
    assert args.log_of_measurement_results == {}
    assert args.tableau == flipped_tableau

    foo = sympy.Symbol('foo')
    with pytest.raises(TypeError, match="Failed to act action on state"):
        cirq.act_on(cirq.Z ** foo, args, [cirq.LineQubit(1)])

    with pytest.raises(TypeError, match="Failed to act action on state"):
        cirq.act_on(cirq.H ** foo, args, [cirq.LineQubit(1)])

    with pytest.raises(TypeError, match="Failed to act action on state"):
        cirq.act_on(cirq.H ** 1.5, args, [cirq.LineQubit(1)])
def test_clifford_decompose_by_unitary():
    """Validate the decomposition of random Clifford Tableau by unitary matrix.

    Due to the exponential growth in dimension, it cannot validate very large number of qubits.
    """
    n, num_ops = 5, 20
    gate_candidate = [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.S, cirq.CNOT, cirq.CZ]
    for seed in range(100):
        prng = np.random.RandomState(seed)
        t = cirq.CliffordTableau(num_qubits=n)
        qubits = cirq.LineQubit.range(n)
        expect_circ = cirq.Circuit()
        args = cirq.CliffordTableauSimulationState(tableau=t, qubits=qubits, prng=prng)
        for _ in range(num_ops):
            g = prng.randint(len(gate_candidate))
            indices = (prng.randint(n),) if g < 5 else prng.choice(n, 2, replace=False)
            cirq.act_on(
                gate_candidate[g], args, qubits=[qubits[i] for i in indices], allow_decompose=False
            )
            expect_circ.append(gate_candidate[g].on(*[qubits[i] for i in indices]))
        ops = cirq.decompose_clifford_tableau_to_operations(qubits, args.tableau)
        circ = cirq.Circuit(ops)
        circ.append(cirq.I.on_each(qubits))
        expect_circ.append(cirq.I.on_each(qubits))
        assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
Exemple #19
0
def test_act_on_tableau(phase):
    original_tableau = cirq.CliffordTableau(0)
    args = cirq.ActOnCliffordTableauArgs(original_tableau.copy(),
                                         np.random.RandomState(), {})
    cirq.act_on(cirq.global_phase_operation(phase),
                args,
                allow_decompose=False)
    assert args.tableau == original_tableau
Exemple #20
0
def test_gate_act_on_tableau(phase):
    original_tableau = cirq.CliffordTableau(0)
    args = cirq.ActOnCliffordTableauArgs(original_tableau.copy(),
                                         np.random.RandomState(), {})
    cirq.act_on(cirq.GlobalPhaseGate(phase),
                args,
                qubits=(),
                allow_decompose=False)
    assert args.tableau == original_tableau
Exemple #21
0
def test_tableau_initial_state_string(num_qubits):
    for i in range(2 ** num_qubits):
        t = cirq.CliffordTableau(initial_state=i, num_qubits=num_qubits)
        splitted_represent_string = str(t).split('\n')
        assert len(splitted_represent_string) == num_qubits
        for n in range(num_qubits):
            sign = '- ' if i >> (num_qubits - n - 1) & 1 else '+ '
            expected_string = sign + 'I ' * n + 'Z ' + 'I ' * (num_qubits - n - 1)
            assert splitted_represent_string[n] == expected_string
Exemple #22
0
def test_clifford_decompose_one_qubit():
    """Two random instance for one qubit decomposition."""
    qubits = cirq.LineQubit.range(1)
    args = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=1),
        qubits=qubits,
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(cirq.X, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.H, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.S, args, qubits=[qubits[0]], allow_decompose=False)
    expect_circ = cirq.Circuit(cirq.X(qubits[0]), cirq.H(qubits[0]),
                               cirq.S(qubits[0]))
    ops = cirq.decompose_clifford_tableau_to_operations(qubits, args.tableau)
    circ = cirq.Circuit(ops)
    assert_allclose_up_to_global_phase(cirq.unitary(expect_circ),
                                       cirq.unitary(circ),
                                       atol=1e-7)

    qubits = cirq.LineQubit.range(1)
    args = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=1),
        qubits=qubits,
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(cirq.Z, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.H, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.S, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.H, args, qubits=[qubits[0]], allow_decompose=False)
    cirq.act_on(cirq.X, args, qubits=[qubits[0]], allow_decompose=False)
    expect_circ = cirq.Circuit(
        cirq.Z(qubits[0]),
        cirq.H(qubits[0]),
        cirq.S(qubits[0]),
        cirq.H(qubits[0]),
        cirq.X(qubits[0]),
    )
    ops = cirq.decompose_clifford_tableau_to_operations(qubits, args.tableau)
    circ = cirq.Circuit(ops)
    assert_allclose_up_to_global_phase(cirq.unitary(expect_circ),
                                       cirq.unitary(circ),
                                       atol=1e-7)
Exemple #23
0
def test_cz_act_on_equivalent_to_h_cx_h_tableau():
    args1 = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=2),
        qubits=cirq.LineQubit.range(2),
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    args2 = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=2),
        qubits=cirq.LineQubit.range(2),
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(cirq.S,
                args=args1,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)
    cirq.act_on(cirq.S,
                args=args2,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)

    # Args1 uses H*CNOT*H
    cirq.act_on(cirq.H,
                args=args1,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)
    cirq.act_on(cirq.CNOT,
                args=args1,
                qubits=cirq.LineQubit.range(2),
                allow_decompose=False)
    cirq.act_on(cirq.H,
                args=args1,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)
    # Args2 uses CZ
    cirq.act_on(cirq.CZ,
                args=args2,
                qubits=cirq.LineQubit.range(2),
                allow_decompose=False)

    assert args1.tableau == args2.tableau
Exemple #24
0
def test_unitary_fallback():
    class UnitaryXGate(cirq.Gate):
        def _num_qubits_(self) -> int:
            return 1

        def _unitary_(self):
            return np.array([[0, 1], [1, 0]])

    class UnitaryYGate(cirq.Gate):
        def _qid_shape_(self) -> Tuple[int, ...]:
            return (2, )

        def _unitary_(self):
            return np.array([[0, -1j], [1j, 0]])

    original_tableau = cirq.CliffordTableau(num_qubits=3)
    args = cirq.ActOnCliffordTableauArgs(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(3),
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )

    cirq.act_on(UnitaryXGate(), args, [cirq.LineQubit(1)])
    assert args.tableau == cirq.CliffordTableau(num_qubits=3, initial_state=2)

    args = cirq.ActOnCliffordTableauArgs(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(3),
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(UnitaryYGate(), args, [cirq.LineQubit(1)])
    expected_args = cirq.ActOnCliffordTableauArgs(
        tableau=original_tableau.copy(),
        qubits=cirq.LineQubit.range(3),
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(cirq.Y, expected_args, [cirq.LineQubit(1)])
    assert args.tableau == expected_args.tableau
Exemple #25
0
def test_validate_tableau():
    num_qubits = 4
    for i in range(2 ** num_qubits):
        t = cirq.CliffordTableau(initial_state=i, num_qubits=num_qubits)
        assert t._validate()

    t = cirq.CliffordTableau(num_qubits=2)
    assert t._validate()
    _H(t, 0)
    assert t._validate()
    _X(t, 0)
    assert t._validate()
    _Z(t, 1)
    assert t._validate()
    _CNOT(t, 0, 1)
    assert t._validate()
    _CNOT(t, 1, 0)
    assert t._validate()

    t.xs = np.zeros((4, 2))
    assert t._validate() == False
Exemple #26
0
def test_act_on_clifford_tableau():
    a, b = [cirq.LineQubit(3), cirq.LineQubit(1)]
    m = cirq.measure(a,
                     b,
                     key='out',
                     invert_mask=(True, ),
                     confusion_map={(1, ): np.array([[0, 1], [1, 0]])})
    # The below assertion does not fail since it ignores non-unitary operations
    cirq.testing.assert_all_implemented_act_on_effects_match_unitary(m)

    args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=5, initial_state=0),
        qubits=cirq.LineQubit.range(5),
        prng=np.random.RandomState(),
    )
    cirq.act_on(m, args)
    assert args.log_of_measurement_results == {'out': [1, 1]}

    args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=5, initial_state=8),
        qubits=cirq.LineQubit.range(5),
        prng=np.random.RandomState(),
    )

    cirq.act_on(m, args)
    assert args.log_of_measurement_results == {'out': [1, 0]}

    args = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=5, initial_state=10),
        qubits=cirq.LineQubit.range(5),
        prng=np.random.RandomState(),
    )
    cirq.act_on(m, args)
    datastore = cast(cirq.ClassicalDataDictionaryStore, args.classical_data)
    out = cirq.MeasurementKey('out')
    assert args.log_of_measurement_results == {'out': [0, 0]}
    assert datastore.records[out] == [(0, 0)]
    cirq.act_on(m, args)
    assert args.log_of_measurement_results == {'out': [0, 0]}
    assert datastore.records[out] == [(0, 0), (0, 0)]
def test_cz_act_on_equivalent_to_h_cx_h_tableau():
    state1 = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=2),
        qubits=cirq.LineQubit.range(2),
        prng=np.random.RandomState(),
    )
    state2 = cirq.CliffordTableauSimulationState(
        tableau=cirq.CliffordTableau(num_qubits=2),
        qubits=cirq.LineQubit.range(2),
        prng=np.random.RandomState(),
    )
    cirq.act_on(cirq.S,
                sim_state=state1,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)
    cirq.act_on(cirq.S,
                sim_state=state2,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)

    # state1 uses H*CNOT*H
    cirq.act_on(cirq.H,
                sim_state=state1,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)
    cirq.act_on(cirq.CNOT,
                sim_state=state1,
                qubits=cirq.LineQubit.range(2),
                allow_decompose=False)
    cirq.act_on(cirq.H,
                sim_state=state1,
                qubits=[cirq.LineQubit(1)],
                allow_decompose=False)
    # state2 uses CZ
    cirq.act_on(cirq.CZ,
                sim_state=state2,
                qubits=cirq.LineQubit.range(2),
                allow_decompose=False)

    assert state1.tableau == state2.tableau
Exemple #28
0
def test_cannot_act():

    class NoDetails:
        pass

    args = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=3),
        axes=[1],
        prng=np.random.RandomState(),
        log_of_measurement_results={})

    with pytest.raises(TypeError, match="Failed to act"):
        cirq.act_on(NoDetails(), args)
Exemple #29
0
def test_unitary_fallback():

    class UnitaryXGate(cirq.Gate):

        def num_qubits(self) -> int:
            return 1

        def _unitary_(self):
            return np.array([[0, 1], [1, 0]])

    class UnitaryYGate(cirq.Gate):

        def num_qubits(self) -> int:
            return 1

        def _unitary_(self):
            return np.array([[0, -1j], [1j, 0]])

    original_tableau = cirq.CliffordTableau(num_qubits=3)
    args = cirq.ActOnCliffordTableauArgs(tableau=original_tableau.copy(),
                                         axes=[1],
                                         prng=np.random.RandomState(),
                                         log_of_measurement_results={})

    cirq.act_on(UnitaryXGate(), args)
    assert args.tableau == cirq.CliffordTableau(num_qubits=3, initial_state=2)

    args = cirq.ActOnCliffordTableauArgs(tableau=original_tableau.copy(),
                                         axes=[1],
                                         prng=np.random.RandomState(),
                                         log_of_measurement_results={})
    cirq.act_on(UnitaryYGate(), args)
    expected_args = cirq.ActOnCliffordTableauArgs(
        tableau=original_tableau.copy(),
        axes=[1],
        prng=np.random.RandomState(),
        log_of_measurement_results={})
    cirq.act_on(cirq.Y, expected_args)
    assert args.tableau == expected_args.tableau
def test_act_on_clifford_tableau():
    a, b = cirq.LineQubit.range(2)
    m = cirq.measure(a, b, key='out', invert_mask=(True, ))
    # The below assertion does not fail since it ignores non-unitary operations
    cirq.testing.assert_all_implemented_act_on_effects_match_unitary(m)

    with pytest.raises(TypeError, match="Failed to act"):
        cirq.act_on(m, object())

    args = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=5, initial_state=0),
        axes=[3, 1],
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(m, args)
    assert args.log_of_measurement_results == {'out': [1, 0]}

    args = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=5, initial_state=8),
        axes=[3, 1],
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )

    cirq.act_on(m, args)
    assert args.log_of_measurement_results == {'out': [1, 1]}

    args = cirq.ActOnCliffordTableauArgs(
        tableau=cirq.CliffordTableau(num_qubits=5, initial_state=10),
        axes=[3, 1],
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    cirq.act_on(m, args)
    assert args.log_of_measurement_results == {'out': [0, 1]}

    with pytest.raises(ValueError, match="already logged to key"):
        cirq.act_on(m, args)