Ejemplo n.º 1
0
def state_vector_has_stabilizer(state_vector: np.ndarray, stabilizer: DensePauliString) -> bool:
    """Checks that the state_vector is stabilized by the given stabilizer.

    The stabilizer should not modify the value of the state_vector, up to the
    global phase.

    Args:
        state_vector: An input state vector. Is not mutated by this function.
        stabilizer: A potential stabilizer of the above state_vector as a
          DensePauliString.

    Returns:
        Whether the stabilizer stabilizes the supplied state.
    """

    qubits = LineQubit.range(protocols.num_qubits(stabilizer))
    args = act_on_state_vector_args.ActOnStateVectorArgs(
        target_tensor=state_vector.copy(),
        available_buffer=np.empty_like(state_vector),
        qubits=qubits,
        prng=np.random.RandomState(),
        log_of_measurement_results={},
    )
    protocols.act_on(stabilizer, args, qubits)
    return np.allclose(args.target_tensor, state_vector)
Ejemplo n.º 2
0
def assert_act_on_clifford_tableau_effect_matches_unitary(val: Any) -> None:
    """Checks that act_on with CliffordTableau generates stabilizers that
    stabilize the final state vector. Does not work with Operations or Gates
    expecting non-qubit Qids."""

    # pylint: disable=unused-variable
    __tracebackhide__ = True
    # pylint: enable=unused-variable

    num_qubits_val = protocols.num_qubits(val)

    if not protocols.has_unitary(val) or \
            protocols.qid_shape(val) != (2,) * num_qubits_val:
        return None

    qubits = LineQubit.range(protocols.num_qubits(val) * 2)
    qubit_map = {qubit: i for i, qubit in enumerate(qubits)}

    circuit = Circuit()
    for i in range(num_qubits_val):
        circuit.append([
            common_gates.H(qubits[i]),
            common_gates.CNOT(qubits[i], qubits[-i - 1])
        ])
    if hasattr(val, "on"):
        circuit.append(val.on(*qubits[:num_qubits_val]))
    else:
        circuit.append(val.with_qubits(*qubits[:num_qubits_val]))

    tableau = _final_clifford_tableau(circuit, qubit_map)
    if tableau is None:
        return None

    state_vector = np.reshape(final_state_vector(circuit, qubit_order=qubits),
                              protocols.qid_shape(qubits))

    assert all(
        state_vector_has_stabilizer(state_vector, stab)
        for stab in tableau.stabilizers()), (
            "act_on clifford tableau is not consistent with "
            "final_state_vector simulation.\n\nval: {!r}".format(val))
Ejemplo n.º 3
0
def assert_all_implemented_act_on_effects_match_unitary(
        val: Any,
        assert_tableau_implemented: bool = False,
        assert_ch_form_implemented: bool = False) -> None:
    """Uses val's effect on final_state_vector to check act_on(val)'s behavior.

    Checks that act_on with CliffordTableau or StabilizerStateCHForm behaves
    consistently with act_on through final state vector. Does not work with
    Operations or Gates expecting non-qubit Qids. If either of the
    assert_*_implmented args is true, fails if the corresponding method is not
    implemented for the test circuit.

    Args:
        val: A gate or operation that may be an input to protocols.act_on.
        assert_tableau_implemented: asserts that protocols.act_on() works with
          val and ActOnCliffordTableauArgs inputs.
        assert_ch_form_implemented: asserts that protocols.act_on() works with
          val and ActOnStabilizerStateChFormArgs inputs.
    """

    # pylint: disable=unused-variable
    __tracebackhide__ = True
    # pylint: enable=unused-variable

    num_qubits_val = protocols.num_qubits(val)

    if (protocols.is_parameterized(val) or not protocols.has_unitary(val)
            or protocols.qid_shape(val) != (2, ) * num_qubits_val):
        if assert_tableau_implemented or assert_ch_form_implemented:
            assert False, ("Could not assert if any act_on methods were "
                           "implemented. Operating on qudits or with a "
                           "non-unitary or parameterized operation is "
                           "unsupported.\n\nval: {!r}".format(val))
        return None

    qubits = LineQubit.range(protocols.num_qubits(val) * 2)
    qubit_map = {qubit: i for i, qubit in enumerate(qubits)}

    circuit = Circuit()
    for i in range(num_qubits_val):
        circuit.append([
            common_gates.H(qubits[i]),
            common_gates.CNOT(qubits[i], qubits[-i - 1])
        ])
    if hasattr(val, "on"):
        circuit.append(val.on(*qubits[:num_qubits_val]))
    else:
        circuit.append(val.with_qubits(*qubits[:num_qubits_val]))

    state_vector = np.reshape(final_state_vector(circuit, qubit_order=qubits),
                              protocols.qid_shape(qubits))

    tableau = _final_clifford_tableau(circuit, qubit_map)
    if tableau is None:
        assert (
            not assert_tableau_implemented
        ), "Failed to generate final tableau for the test circuit.\n\nval: {!r}".format(
            val)
    else:
        assert all(
            state_vector_has_stabilizer(state_vector, stab)
            for stab in tableau.stabilizers()), (
                "act_on clifford tableau is not consistent with "
                "final_state_vector simulation.\n\nval: {!r}".format(val))

    stabilizer_ch_form = _final_stabilizer_state_ch_form(circuit, qubit_map)
    if stabilizer_ch_form is None:
        assert not assert_ch_form_implemented, ("Failed to generate final "
                                                "stabilizer state CH form "
                                                "for the test circuit."
                                                "\n\nval: {!r}".format(val))
    else:
        np.testing.assert_allclose(
            np.reshape(stabilizer_ch_form.state_vector(),
                       protocols.qid_shape(qubits)),
            state_vector,
            atol=1e-07,
            err_msg=
            f"stabilizer_ch_form.state_vector disagrees with state_vector for {val!r}",
            verbose=True,
        )