Esempio n. 1
0
 def sample(
     self,
     qubits: Sequence['cirq.Qid'],
     repetitions: int = 1,
     seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
 ) -> np.ndarray:
     indices = [self.qubit_map[q] for q in qubits]
     return sim.sample_state_vector(
         self.target_tensor,
         indices,
         qid_shape=tuple(q.dimension for q in self.qubits),
         repetitions=repetitions,
         seed=seed,
     )
    def sample(
        self,
        axes: Sequence[int],
        repetitions: int = 1,
        seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
    ) -> np.ndarray:
        """Samples the state vector.

        Args:
            axes: The axes to sample.
            repetitions: The number of samples to make.
            seed: The random number seed to use.
        Returns:
            The samples in order.
        """
        return sim.sample_state_vector(
            self._state_vector, axes, qid_shape=self._qid_shape, repetitions=repetitions, seed=seed
        )
Esempio n. 3
0
    def sample_measurements(self,
                            indices: List[int],
                            repetitions: int = 1) -> List[List[bool]]:
        """Samples from measurements in the computational basis.

        Note that this does not collapse the wave function.

        Args:
            indices: Which qubits are measured.

        Returns:
            Measurement results with True corresponding to the |1> state.
            The outer list is for repetitions, and the inner corresponds to
            measurements ordered by the input indices.

        Raises:
            ValueError if repetitions is less than one.
        """
        # Stepper uses little endian while sample_state uses big endian.
        reversed_indices = [self._num_qubits - 1 - index for index in indices]
        return sim.sample_state_vector(self._current_state(), reversed_indices,
                                       repetitions)
Esempio n. 4
0
    def _sample_measure_results(
        self,
        program: circuits.Circuit,
        repetitions: int = 1,
    ) -> Dict[str, np.ndarray]:
        """Samples from measurement gates in the circuit.

    Note that this will execute the circuit 'repetitions' times.

    Args:
        program: The circuit to sample from.
        repetitions: The number of samples to take.

    Returns:
        A dictionary from measurement gate key to measurement
        results. Measurement results are stored in a 2-dimensional
        numpy array, the first dimension corresponding to the repetition
        and the second to the actual boolean measurement results (ordered
        by the qubits being measured.)

    Raises:
        ValueError: If there are multiple MeasurementGates with the same key,
            or if repetitions is negative.
    """
        if not isinstance(program, qsimc.QSimCircuit):
            program = qsimc.QSimCircuit(program, device=program.device)

        # Compute indices of measured qubits
        ordered_qubits = ops.QubitOrder.DEFAULT.order_for(program.all_qubits())
        num_qubits = len(ordered_qubits)

        qubit_map = {
            qubit: index
            for index, qubit in enumerate(ordered_qubits)
        }

        # Computes
        # - the list of qubits to be measured
        # - the start (inclusive) and end (exclusive) indices of each measurement
        # - a mapping from measurement key to measurement gate
        measurement_ops = [
            op for _, op, _ in program.findall_operations_with_gate_type(
                ops.MeasurementGate)
        ]
        measured_qubits = []  # type: List[ops.Qid]
        bounds = {}  # type: Dict[str, Tuple]
        meas_ops = {}  # type: Dict[str, cirq.GateOperation]
        current_index = 0
        for op in measurement_ops:
            gate = op.gate
            key = protocols.measurement_key(gate)
            meas_ops[key] = op
            if key in bounds:
                raise ValueError(
                    "Duplicate MeasurementGate with key {}".format(key))
            bounds[key] = (current_index, current_index + len(op.qubits))
            measured_qubits.extend(op.qubits)
            current_index += len(op.qubits)

        # Set qsim options
        options = {}
        options.update(self.qsim_options)

        results = {}
        for key, bound in bounds.items():
            results[key] = np.ndarray(shape=(repetitions, bound[1] - bound[0]),
                                      dtype=int)

        noisy = _needs_trajectories(program)
        if noisy:
            translator_fn_name = 'translate_cirq_to_qtrajectory'
            sampler_fn = qsim.qtrajectory_sample
        else:
            translator_fn_name = 'translate_cirq_to_qsim'
            sampler_fn = qsim.qsim_sample

        if not noisy and program.are_all_measurements_terminal(
        ) and repetitions > 1:
            print('Provided circuit has no intermediate measurements. ' +
                  'Sampling repeatedly from final state vector.')
            # Measurements must be replaced with identity gates to sample properly.
            # Simply removing them may omit qubits from the circuit.
            for i in range(len(program.moments)):
                program.moments[i] = ops.Moment(
                    op if not isinstance(op.gate, ops.MeasurementGate) else
                    [ops.IdentityGate(1).on(q) for q in op.qubits]
                    for op in program.moments[i])
            options['c'] = program.translate_cirq_to_qsim(
                ops.QubitOrder.DEFAULT)
            options['s'] = self.get_seed()
            final_state = qsim.qsim_simulate_fullstate(options, 0)
            full_results = sim.sample_state_vector(final_state.view(
                np.complex64),
                                                   range(num_qubits),
                                                   repetitions=repetitions,
                                                   seed=self._prng)

            for i in range(repetitions):
                for key, op in meas_ops.items():
                    meas_indices = [qubit_map[qubit] for qubit in op.qubits]
                    for j, q in enumerate(meas_indices):
                        results[key][i][j] = full_results[i][q]
        else:
            translator_fn = getattr(program, translator_fn_name)
            options['c'] = translator_fn(ops.QubitOrder.DEFAULT)
            for i in range(repetitions):
                options['s'] = self.get_seed()
                measurements = sampler_fn(options)
                for key, bound in bounds.items():
                    for j in range(bound[1] - bound[0]):
                        results[key][i][j] = int(measurements[bound[0] + j])

        return results