Example #1
0
 def _qid_shape_(self):
     return protocols.qid_shape(self.to_circuit())
Example #2
0
def _assert_apply_unitary_works_when_axes_transposed(val: Any,
                                                     *,
                                                     atol: float = 1e-8
                                                     ) -> None:
    """Tests whether a value's _apply_unitary_ handles out-of-order axes.

    A common mistake to make when implementing `_apply_unitary_` is to assume
    that the incoming axes will be contiguous, or ascending, or that they can be
    flattened, or that other axes have a length of two, etc, etc ,etc. This
    method checks that `_apply_unitary_` does the same thing to out-of-order
    axes that it does to contiguous in-order axes.

    Args:
        val: The operation, gate, or other unitary object to test.
        atol: Absolute error tolerance.
    """

    # Only test custom apply unitary methods.
    if not hasattr(val, '_apply_unitary_') or not protocols.has_unitary(val):
        return

    # Pick sizes and shapes.
    shape = protocols.qid_shape(val)
    n = len(shape)
    padded_shape = shape + (1, 2, 2, 3)
    padded_n = len(padded_shape)
    size = np.product(padded_shape).item()

    # Shuffle the axes.
    permutation = list(range(padded_n))
    random.shuffle(permutation)
    transposed_shape = [0] * padded_n
    for i in range(padded_n):
        transposed_shape[permutation[i]] = padded_shape[i]

    # Prepare input states.
    in_order_input = lin_alg_utils.random_superposition(size).reshape(
        padded_shape)
    out_of_order_input = np.empty(shape=transposed_shape, dtype=np.complex128)
    out_of_order_input.transpose(permutation)[...] = in_order_input

    # Apply to in-order and out-of-order axes.
    in_order_output = protocols.apply_unitary(
        val,
        protocols.ApplyUnitaryArgs(
            target_tensor=in_order_input,
            available_buffer=np.empty_like(in_order_input),
            axes=range(n),
        ),
    )
    out_of_order_output = protocols.apply_unitary(
        val,
        protocols.ApplyUnitaryArgs(
            target_tensor=out_of_order_input,
            available_buffer=np.empty_like(out_of_order_input),
            axes=permutation[:n],
        ),
    )

    # Put the out of order output back into order, to enable comparison.
    reordered_output = out_of_order_output.transpose(permutation)

    # The results should be identical.
    if not np.allclose(in_order_output, reordered_output, atol=atol):
        raise AssertionError(
            f'The _apply_unitary_ method of {repr(val)} acted differently on '
            f'out-of-order axes than on in-order axes.\n'
            f'\n'
            f'The failing axis order: {repr(permutation[:n])}')
Example #3
0
 def set_state_vector(self, state: 'cirq.STATE_VECTOR_LIKE'):
     update_state = qis.to_valid_state_vector(
         state, len(self.qubit_map), qid_shape=protocols.qid_shape(self, None), dtype=self._dtype
     )
     np.copyto(self._state_vector, update_state)
Example #4
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,
        )
Example #5
0
 def _qid_shape_(self):
     return protocols.qid_shape(self._original)
Example #6
0
 def _qid_shape_(self) -> Tuple[int, ...]:
     return protocols.qid_shape(self.qubits)
Example #7
0
 def _qid_shape_(self) -> Tuple[int, ...]:
     return protocols.qid_shape(self.sub_gate)
Example #8
0
 def _qid_shape_(self):
     return protocols.qid_shape(self.gate)