def __init__(self, num_qubits: int, initial_state: int = 0) -> None:
        """Initializes StabilizerStateChForm
        Args:
            num_qubits: The number of qubits in the system.
            initial_state: The computational basis representation of the
                state as a big endian int.
        """
        self.n = num_qubits

        # The state is represented by a set of binary matrices and vectors.
        # See Section IVa of Bravyi et al
        self.G = np.eye(self.n, dtype=bool)

        self.F = np.eye(self.n, dtype=bool)
        self.M = np.zeros((self.n, self.n), dtype=bool)
        self.gamma = np.zeros(self.n, dtype=int)

        self.v = np.zeros(self.n, dtype=bool)
        self.s = np.zeros(self.n, dtype=bool)

        self.omega = 1  # type: complex

        # Apply X for every non-zero element of initial_state
        for (i, val) in enumerate(
                big_endian_int_to_digits(initial_state,
                                         digit_count=num_qubits,
                                         base=2)):
            if val:
                protocols.act_on(
                    pauli_gates.X,
                    clifford.ActOnStabilizerCHFormArgs(self, [i],
                                                       np.random.RandomState(),
                                                       {}),
                )
Esempio n. 2
0
    def _create_partial_act_on_args(
        self,
        initial_state: Union[int, 'cirq.ActOnStabilizerCHFormArgs'],
        qubits: Sequence['cirq.Qid'],
        classical_data: 'cirq.ClassicalDataStore',
    ) -> 'cirq.ActOnStabilizerCHFormArgs':
        """Creates the ActOnStabilizerChFormArgs for a circuit.

        Args:
            initial_state: The initial state for the simulation in the
                computational basis. Represented as a big endian int.
            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.
            logs: A log of the results of measurement that is added to.
            classical_data: The shared classical data container for this
                simulation.

        Returns:
            ActOnStabilizerChFormArgs for the circuit.
        """
        if isinstance(initial_state, clifford.ActOnStabilizerCHFormArgs):
            return initial_state

        return clifford.ActOnStabilizerCHFormArgs(
            prng=self._prng,
            classical_data=classical_data,
            qubits=qubits,
            initial_state=initial_state,
        )
Esempio n. 3
0
    def _create_partial_act_on_args(
        self,
        initial_state: Union[int, clifford.ActOnStabilizerCHFormArgs],
        qubits: Sequence['cirq.Qid'],
        logs: Dict[str, Any],
    ) -> clifford.ActOnStabilizerCHFormArgs:
        """Creates the ActOnStabilizerChFormArgs for a circuit.

        Args:
            initial_state: The initial state for the simulation in the
                computational basis. Represented as a big endian int.
            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.
            logs: A log of the results of measurement that is added to.

        Returns:
            ActOnStabilizerChFormArgs for the circuit.
        """
        if isinstance(initial_state, clifford.ActOnStabilizerCHFormArgs):
            return initial_state

        qubit_map = {q: i for i, q in enumerate(qubits)}

        state = CliffordState(qubit_map, initial_state=initial_state)
        return clifford.ActOnStabilizerCHFormArgs(
            state=state.ch_form,
            prng=self._prng,
            log_of_measurement_results=logs,
            qubits=qubits,
        )
Esempio n. 4
0
    def apply_measurement(
        self,
        op: 'cirq.Operation',
        measurements: Dict[str, List[np.ndarray]],
        prng: np.random.RandomState,
        collapse_state_vector=True,
    ):
        if not isinstance(op.gate, cirq.MeasurementGate):
            raise TypeError(
                'apply_measurement only supports cirq.MeasurementGate operations. Found %s instead.'
                % str(op.gate))

        if collapse_state_vector:
            state = self
        else:
            state = self.copy()

        classical_data = value.ClassicalDataDictionaryStore()
        ch_form_args = clifford.ActOnStabilizerCHFormArgs(
            prng=prng,
            classical_data=classical_data,
            qubits=self.qubit_map.keys(),
            initial_state=state.ch_form,
        )
        act_on(op, ch_form_args)
        measurements.update(
            {str(k): list(v[-1])
             for k, v in classical_data.records.items()})
Esempio n. 5
0
 def apply_unitary(self, op: 'cirq.Operation'):
     ch_form_args = clifford.ActOnStabilizerCHFormArgs(
         self.ch_form, np.random.RandomState(), {}, self.qubit_map.keys())
     try:
         act_on(op, ch_form_args)
     except TypeError:
         raise ValueError(
             f'{str(op.gate)} cannot be run with Clifford simulator.'
         )  # type: ignore
     return
Esempio n. 6
0
    def _base_iterator(
            self, circuit: circuits.Circuit, qubit_order: ops.QubitOrderOrList,
            initial_state: int
    ) -> Iterator['cirq.CliffordSimulatorStepResult']:
        """Iterator over CliffordSimulatorStepResult from Moments of a Circuit

        Args:
            circuit: The circuit to simulate.
            qubit_order: 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.
            initial_state: The initial state for the simulation in the
                computational basis. Represented as a big endian int.


        Yields:
            CliffordStepResult from simulating a Moment of the Circuit.
        """
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())

        qubit_map = {q: i for i, q in enumerate(qubits)}

        if len(circuit) == 0:
            yield CliffordSimulatorStepResult(measurements={},
                                              state=CliffordState(
                                                  qubit_map,
                                                  initial_state=initial_state))
            return

        state = CliffordState(qubit_map, initial_state=initial_state)
        ch_form_args = clifford.ActOnStabilizerCHFormArgs(
            state.ch_form,
            [],
            self._prng,
            {},
        )

        for moment in circuit:
            ch_form_args.log_of_measurement_results = {}

            for op in moment:
                try:
                    ch_form_args.axes = tuple(state.qubit_map[i]
                                              for i in op.qubits)
                    act_on(op, ch_form_args)
                except TypeError:
                    raise NotImplementedError(
                        f"CliffordSimulator doesn't support {op!r}"
                    )  # type: ignore

            yield CliffordSimulatorStepResult(
                measurements=ch_form_args.log_of_measurement_results,
                state=state)
Esempio n. 7
0
 def apply_unitary(self, op: 'cirq.Operation'):
     tableau_args = clifford.ActOnCliffordTableauArgs(
         self.tableau, [self.qubit_map[i] for i in op.qubits],
         np.random.RandomState(), {})
     ch_form_args = clifford.ActOnStabilizerCHFormArgs(
         self.ch_form, [self.qubit_map[i] for i in op.qubits])
     try:
         act_on(op, tableau_args)
         act_on(op, ch_form_args)
     except TypeError:
         raise ValueError('%s cannot be run with Clifford simulator.' %
                          str(op.gate))  # type: ignore
     return
Esempio n. 8
0
    def apply_measurement(
        self,
        op: 'cirq.Operation',
        measurements: Dict[str, List[np.ndarray]],
        prng: np.random.RandomState,
        collapse_state_vector=True,
    ):
        if not isinstance(op.gate, cirq.MeasurementGate):
            raise TypeError(
                'apply_measurement only supports cirq.MeasurementGate operations. Found %s instead.'
                % str(op.gate))

        if collapse_state_vector:
            state = self
        else:
            state = self.copy()

        ch_form_args = clifford.ActOnStabilizerCHFormArgs(
            state.ch_form, prng, measurements, self.qubit_map.keys())
        act_on(op, ch_form_args)