Exemplo n.º 1
0
    def _create_act_on_args(
        self,
        initial_state: Union['cirq.STATE_VECTOR_LIKE', 'cirq.ActOnStateVectorArgs'],
        qubits: Sequence['cirq.Qid'],
    ):
        """Creates the ActOnStateVectorArgs for a circuit.

        Args:
            initial_state: The initial state for the simulation in the
                computational basis.
            qubits: Determines the canonical ordering of the qubits. This
                is often used in specifying the initial state, i.e. the
                ordering of the computational basis states.

        Returns:
            ActOnStateVectorArgs for the circuit.
        """
        if isinstance(initial_state, act_on_state_vector_args.ActOnStateVectorArgs):
            return initial_state

        num_qubits = len(qubits)
        qid_shape = protocols.qid_shape(qubits)
        state = qis.to_valid_state_vector(
            initial_state, num_qubits, qid_shape=qid_shape, dtype=self._dtype
        )

        return act_on_state_vector_args.ActOnStateVectorArgs(
            target_tensor=np.reshape(state, qid_shape),
            available_buffer=np.empty(qid_shape, dtype=self._dtype),
            qubits=qubits,
            axes=[],
            prng=self._prng,
            log_of_measurement_results={},
        )
Exemplo n.º 2
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)
Exemplo n.º 3
0
def prepare_two_qubit_state_using_cz(
        q0: 'cirq.Qid', q1: 'cirq.Qid',
        state: 'cirq.STATE_VECTOR_LIKE') -> List['cirq.Operation']:
    """Prepares the given 2q state from |00> using at-most 1 CZ gate + single qubit rotations.

    Entangled states are prepared using exactly 1 CZ gate while product states are prepared
    using only single qubit rotations (0 CZ gates)

    Args:
        q0: The first qubit being operated on.
        q1: The other qubit being operated on.
        state: 4x1 matrix representing two qubit state vector, ordered as 00, 01, 10, 11.

    Returns:
        List of operations (at-most 1 CZ + single qubit rotations) preparing `state` from |00>.
    """
    state = qis.to_valid_state_vector(state, num_qubits=2)
    state = state / np.linalg.norm(state)
    u, s, vh = np.linalg.svd(state.reshape(2, 2))
    if np.isclose(s[0], 1):
        # Product state can be prepare with just single qubit unitaries.
        return _1q_matrices_to_ops(u, vh.T, q0, q1, True)
    alpha = np.arccos(np.clip(s[0], 0, 1))
    op_list = [ops.ry(2 * alpha).on(q0), ops.H.on(q1), ops.CZ.on(q0, q1)]
    intermediate_state = circuits.Circuit(op_list).final_state_vector(
        ignore_terminal_measurements=False, dtype=np.complex64)
    u_CZ, _, vh_CZ = np.linalg.svd(intermediate_state.reshape(2, 2))
    return op_list + _1q_matrices_to_ops(np.dot(
        u, np.linalg.inv(u_CZ)), np.dot(vh.T, np.linalg.inv(vh_CZ.T)), q0, q1)
Exemplo n.º 4
0
def prepare_two_qubit_state_using_sqrt_iswap(
    q0: 'cirq.Qid',
    q1: 'cirq.Qid',
    state: 'cirq.STATE_VECTOR_LIKE',
    *,
    use_sqrt_iswap_inv: bool = True,
) -> List['cirq.Operation']:
    """Prepares the given 2q state from |00> using at-most 1 √iSWAP gate + single qubit rotations.

    Entangled states are prepared using exactly 1 √iSWAP gate while product states are prepared
    using only single qubit rotations (0 √iSWAP gates)

    Args:
        q0: The first qubit being operated on.
        q1: The other qubit being operated on.
        state: 4x1 matrix representing two qubit state vector, ordered as 00, 01, 10, 11.
        use_sqrt_iswap_inv: If True, uses `cirq.SQRT_ISWAP_INV` instead of `cirq.SQRT_ISWAP`.

    Returns:
        List of operations (at-most 1 √iSWAP + single qubit rotations) preparing `state` from |00>.
    """
    state = qis.to_valid_state_vector(state, num_qubits=2)
    state = state / np.linalg.norm(state)
    u, s, vh = np.linalg.svd(state.reshape(2, 2))
    if np.isclose(s[0], 1):
        # Product state can be prepare with just single qubit unitaries.
        return _1q_matrices_to_ops(u, vh.T, q0, q1, True)
    alpha = np.arccos(np.sqrt(np.clip(1 - s[0] * 2 * s[1], 0, 1)))
    sqrt_iswap_gate = ops.SQRT_ISWAP_INV if use_sqrt_iswap_inv else ops.SQRT_ISWAP
    op_list = [ops.ry(2 * alpha).on(q0), sqrt_iswap_gate.on(q0, q1)]
    intermediate_state = circuits.Circuit(op_list).final_state_vector()
    u_iSWAP, _, vh_iSWAP = np.linalg.svd(intermediate_state.reshape(2, 2))
    return op_list + _1q_matrices_to_ops(
        np.dot(u, np.linalg.inv(u_iSWAP)),
        np.dot(vh.T, np.linalg.inv(vh_iSWAP.T)), q0, q1)
Exemplo n.º 5
0
    def __init__(
        self,
        target_tensor: Optional[np.ndarray] = None,
        available_buffer: Optional[np.ndarray] = None,
        prng: Optional[np.random.RandomState] = None,
        log_of_measurement_results: Optional[Dict[str, List[int]]] = None,
        qubits: Optional[Sequence['cirq.Qid']] = None,
        initial_state: Union[np.ndarray, 'cirq.STATE_VECTOR_LIKE'] = 0,
        dtype: Type[np.number] = np.complex64,
        classical_data: Optional['cirq.ClassicalDataStore'] = None,
    ):
        """Inits ActOnStateVectorArgs.

        Args:
            target_tensor: The state vector to act on, stored as a numpy array
                with one dimension for each qubit in the system. Operations are
                expected to perform inplace edits of this object.
            available_buffer: A workspace with the same shape and dtype as
                `target_tensor`. Used by operations that cannot be applied to
                `target_tensor` inline, in order to avoid unnecessary
                allocations. Passing `available_buffer` into
                `swap_target_tensor_for` will swap it for `target_tensor`.
            qubits: Determines the canonical ordering of the qubits. This
                is often used in specifying the initial state, i.e. the
                ordering of the computational basis states.
            prng: The pseudo random number generator to use for probabilistic
                effects.
            log_of_measurement_results: A mutable object that measurements are
                being recorded into.
            initial_state: The initial state for the simulation in the
                computational basis.
            dtype: The `numpy.dtype` of the inferred state vector. One of
                `numpy.complex64` or `numpy.complex128`. Only used when
                `target_tenson` is None.
            classical_data: The shared classical data container for this
                simulation.
        """
        super().__init__(
            prng=prng,
            qubits=qubits,
            log_of_measurement_results=log_of_measurement_results,
            classical_data=classical_data,
        )
        if target_tensor is None:
            qid_shape = protocols.qid_shape(self.qubits)
            state = qis.to_valid_state_vector(initial_state,
                                              len(self.qubits),
                                              qid_shape=qid_shape,
                                              dtype=dtype)
            target_tensor = np.reshape(state, qid_shape)
        self.target_tensor = target_tensor

        if available_buffer is None:
            available_buffer = np.empty_like(target_tensor)
        self.available_buffer = available_buffer
Exemplo n.º 6
0
def test_bloch_sphere_default_client_code():
    state_vector = to_valid_state_vector([math.sqrt(2) / 2, math.sqrt(2) / 2])
    bloch_sphere = cirq_web.BlochSphere(state_vector=state_vector)

    expected_client_code = f"""
        <script>
        renderBlochSphere('{bloch_sphere.id}', 5)
            .addVector(1.0, 0.0, 0.0);
        </script>
        """

    assert expected_client_code == bloch_sphere.get_client_code()
Exemplo n.º 7
0
    def set_state_vector(self, state: 'cirq.STATE_VECTOR_LIKE'):
        """Set the state vector.

        One can pass a valid full state to this method by passing a numpy
        array. Or, alternatively, one can pass an integer, and then the state
        will be set to lie entirely in the computation basis state for the
        binary expansion of the passed integer.

        Args:
            state: If an int, the state vector set is the state vector
                corresponding to a computational basis state. If a numpy
                array this is the full state vector.
        """
        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)
Exemplo n.º 8
0
    def _base_iterator(
        self,
        circuit: circuits.Circuit,
        qubit_order: ops.QubitOrderOrList,
        initial_state: 'cirq.STATE_VECTOR_LIKE',
        perform_measurements: bool = True,
    ) -> Iterator['SparseSimulatorStep']:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = qis.to_valid_state_vector(initial_state,
                                          num_qubits,
                                          qid_shape=qid_shape,
                                          dtype=self._dtype)
        if len(circuit) == 0:
            yield SparseSimulatorStep(state, {}, qubit_map, self._dtype)

        sim_state = act_on_state_vector_args.ActOnStateVectorArgs(
            target_tensor=np.reshape(state, qid_shape),
            available_buffer=np.empty(qid_shape, dtype=self._dtype),
            axes=[],
            prng=self._prng,
            log_of_measurement_results={},
        )

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))
        for op_tree in noisy_moments:
            for op in flatten_to_ops(op_tree):
                if perform_measurements or not isinstance(
                        op.gate, ops.MeasurementGate):
                    sim_state.axes = tuple(qubit_map[qubit]
                                           for qubit in op.qubits)
                    protocols.act_on(op, sim_state)

            yield SparseSimulatorStep(
                state_vector=sim_state.target_tensor,
                measurements=dict(sim_state.log_of_measurement_results),
                qubit_map=qubit_map,
                dtype=self._dtype,
            )
            sim_state.log_of_measurement_results.clear()
    def create(
        cls,
        *,
        initial_state: Union[np.ndarray, 'cirq.STATE_VECTOR_LIKE'] = 0,
        qid_shape: Optional[Tuple[int, ...]] = None,
        dtype: Optional[Type[np.complexfloating]] = None,
        buffer: Optional[List[np.ndarray]] = None,
    ):
        """Initializes the object with the inputs.

        This initializer creates the buffer if necessary.

        Args:
            initial_state: The density matrix, must be correctly formatted. The data is not
                checked for validity here due to performance concerns.
            qid_shape: The shape of the density matrix, if the initial state is provided as an int.
            dtype: The dtype of the density matrix, if the initial state is provided as an int.
            buffer: Optional, must be length 3 and same shape as the density matrix. If not
                provided, a buffer will be created automatically.
        Raises:
            ValueError: If initial state is provided as integer, but qid_shape is not provided.
        """
        if not isinstance(initial_state, np.ndarray):
            if qid_shape is None:
                raise ValueError(
                    'qid_shape must be provided if initial_state is not ndarray'
                )
            state_vector = qis.to_valid_state_vector(
                initial_state,
                len(qid_shape),
                qid_shape=qid_shape,
                dtype=dtype).reshape(qid_shape)
        else:
            if qid_shape is not None:
                state_vector = initial_state.reshape(qid_shape)
            else:
                state_vector = initial_state
            if np.may_share_memory(state_vector, initial_state):
                state_vector = state_vector.copy()
        state_vector = state_vector.astype(dtype, copy=False)
        return cls(state_vector, buffer)
Exemplo n.º 10
0
def state_vector_to_probabilities(
        state_vector: 'cirq.STATE_VECTOR_LIKE') -> np.ndarray:
    valid_state_vector = to_valid_state_vector(state_vector)
    return np.abs(valid_state_vector)**2
Exemplo n.º 11
0
def to_valid_state_vector(*args, **kwargs):
    return qis.to_valid_state_vector(*args, **kwargs)
Exemplo n.º 12
0
def test_bloch_sphere_default_bundle_name():
    state_vector = to_valid_state_vector([math.sqrt(2) / 2, math.sqrt(2) / 2])
    bloch_sphere = cirq_web.BlochSphere(state_vector=state_vector)

    assert bloch_sphere.get_widget_bundle_name() == 'bloch_sphere.bundle.js'
Exemplo n.º 13
0
def test_valid_bloch_sphere_radius(sphere_radius):
    state_vector = to_valid_state_vector([math.sqrt(2) / 2, math.sqrt(2) / 2])
    bloch_sphere = cirq_web.BlochSphere(sphere_radius, state_vector)
    assert sphere_radius == bloch_sphere.sphere_radius
Exemplo n.º 14
0
def test_init_bloch_sphere_type():
    state_vector = to_valid_state_vector([math.sqrt(2) / 2, math.sqrt(2) / 2])
    bloch_sphere = cirq_web.BlochSphere(state_vector=state_vector)
    assert isinstance(bloch_sphere, cirq_web.BlochSphere)
Exemplo n.º 15
0
@pytest.mark.parametrize('sphere_radius', [5, 0.2, 100])
def test_valid_bloch_sphere_radius(sphere_radius):
    state_vector = to_valid_state_vector([math.sqrt(2) / 2, math.sqrt(2) / 2])
    bloch_sphere = cirq_web.BlochSphere(sphere_radius, state_vector)
    assert sphere_radius == bloch_sphere.sphere_radius


@pytest.mark.parametrize('sphere_radius', [0, -1])
def test_invalid_bloch_sphere_radius(sphere_radius):
    with pytest.raises(ValueError):
        cirq_web.BlochSphere(sphere_radius=sphere_radius)


@pytest.mark.parametrize(
    'state_vector',
    [to_valid_state_vector([math.sqrt(2) / 2,
                            math.sqrt(2) / 2])])
def test_valid_bloch_sphere_vector(state_vector):
    bloch_sphere = cirq_web.BlochSphere(state_vector=state_vector)
    bloch_vector = bloch_vector_from_state_vector(state_vector, 0)
    assert np.array_equal(bloch_vector, bloch_sphere.bloch_vector)


def test_no_state_vector_given():
    with pytest.raises(ValueError):
        cirq_web.BlochSphere()


def test_bloch_sphere_default_client_code():
    state_vector = to_valid_state_vector([math.sqrt(2) / 2, math.sqrt(2) / 2])
    bloch_sphere = cirq_web.BlochSphere(state_vector=state_vector)
Exemplo n.º 16
0
def state_vector_to_probabilities(
        state_vector: 'cirq.STATE_VECTOR_LIKE') -> np.ndarray:
    """Function to transform a state vector like object into a numpy array of probabilities."""
    valid_state_vector = to_valid_state_vector(state_vector)
    return np.abs(valid_state_vector)**2
Exemplo n.º 17
0
    def _base_iterator(
        self,
        circuit: circuits.Circuit,
        qubit_order: ops.QubitOrderOrList,
        initial_state: 'cirq.STATE_VECTOR_LIKE',
        perform_measurements: bool = True,
    ) -> Iterator:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = qis.to_valid_state_vector(initial_state,
                                          num_qubits,
                                          qid_shape=qid_shape,
                                          dtype=self._dtype)
        if len(circuit) == 0:
            yield SparseSimulatorStep(state, {}, qubit_map, self._dtype)

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate unknown operations that don't specify a "
                "_unitary_ method, a _decompose_ method, "
                "(_has_unitary_ + _apply_unitary_) methods,"
                "(_has_mixture_ + _mixture_) methods, or are measurements."
                ": {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            # The order of this is optimized to call has_xxx methods first.
            return (protocols.has_unitary(potential_op)
                    or protocols.has_mixture(potential_op)
                    or protocols.is_measurement(potential_op)
                    or isinstance(potential_op.gate, ops.ResetChannel))

        data = _StateAndBuffer(state=np.reshape(state, qid_shape),
                               buffer=np.empty(qid_shape, dtype=self._dtype))
        for moment in circuit:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[int]]

            unitary_ops_and_measurements = protocols.decompose(
                moment, keep=keep, on_stuck_raise=on_stuck)

            for op in unitary_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                if isinstance(op.gate, ops.ResetChannel):
                    self._simulate_reset(op, data, indices)
                elif protocols.has_unitary(op):
                    self._simulate_unitary(op, data, indices)
                elif protocols.is_measurement(op):
                    # Do measurements second, since there may be mixtures that
                    # operate as measurements.
                    # TODO: support measurement outside the computational basis.
                    if perform_measurements:
                        self._simulate_measurement(op, data, indices,
                                                   measurements, num_qubits)
                elif protocols.has_mixture(op):
                    self._simulate_mixture(op, data, indices)

            yield SparseSimulatorStep(state_vector=data.state,
                                      measurements=measurements,
                                      qubit_map=qubit_map,
                                      dtype=self._dtype)