Example #1
0
    def measure(self, qubits: Sequence['cirq.Qid'], key: str, invert_mask: Sequence[bool]):
        """Measures the qubits and records to `log_of_measurement_results`.

        Any bitmasks will be applied to the measurement record. If
        `self._ignore_measurement_results` is set, it dephases instead of
        measuring, and no measurement result will be logged.

        Args:
            qubits: The qubits to measure.
            key: The key the measurement result should be logged under. Note
                that operations should only store results under keys they have
                declared in a `_measurement_key_names_` method.
            invert_mask: The invert mask for the measurement.

        Raises:
            ValueError: If a measurement key has already been logged to a key.
        """
        if self.ignore_measurement_results:
            self._act_on_fallback_(ops.phase_damp(1), qubits)
            return
        bits = self._perform_measurement(qubits)
        corrected = [bit ^ (bit < 2 and mask) for bit, mask in zip(bits, invert_mask)]
        if key in self._log_of_measurement_results:
            raise ValueError(f"Measurement already logged to key {key!r}")
        self._log_of_measurement_results[key] = corrected
Example #2
0
 def dephase(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
     gate = op.gate
     if isinstance(gate, ops.MeasurementGate):
         key = value.MeasurementKey.parse_serialized(gate.key)
         return ops.KrausChannel.from_channel(ops.phase_damp(1), key=key).on_each(op.qubits)
     elif isinstance(op, ops.ClassicallyControlledOperation):
         raise ValueError('Use cirq.defer_measurements first to remove classical controls.')
     return op
Example #3
0
    def _core_iterator(
        self,
        circuit: circuits.AbstractCircuit,
        sim_state: OperationTarget[TActOnArgs],
        all_measurements_are_terminal: bool = False,
    ) -> Iterator[TStepResultBase]:
        """Standard iterator over StepResult from Moments of a Circuit.

        Args:
            circuit: The circuit to simulate.
            sim_state: The initial args for the simulation. The form of
                this state depends on the simulation implementation. See
                documentation of the implementing class for details.
            all_measurements_are_terminal: Whether all measurements in the
                given circuit are terminal.

        Yields:
            StepResults from simulating a Moment of the Circuit.

        Raises:
            TypeError: The simulator encounters an op it does not support.
        """

        if len(circuit) == 0:
            yield self._create_step_result(sim_state)
            return

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))
        measured: Dict[Tuple['cirq.Qid', ...],
                       bool] = collections.defaultdict(bool)
        for moment in noisy_moments:
            for op in ops.flatten_to_ops(moment):
                try:
                    # TODO: support more general measurements.
                    # Github issue: https://github.com/quantumlib/Cirq/issues/3566

                    # Preprocess measurements
                    if all_measurements_are_terminal and measured[op.qubits]:
                        continue
                    if isinstance(op.gate, ops.MeasurementGate):
                        measured[op.qubits] = True
                        if all_measurements_are_terminal:
                            continue
                        if self._ignore_measurement_results:
                            op = ops.phase_damp(1).on(*op.qubits)

                    # Simulate the operation
                    protocols.act_on(op, sim_state)
                except TypeError:
                    raise TypeError(
                        f"{self.__class__.__name__} doesn't support {op!r}")

            step_result = self._create_step_result(sim_state)
            yield step_result
            sim_state = step_result._sim_state
Example #4
0
    def _core_iterator(
        self,
        circuit: circuits.Circuit,
        sim_state: act_on_density_matrix_args.ActOnDensityMatrixArgs,
        all_measurements_are_terminal: bool = False,
    ):
        """Iterator over DensityMatrixStepResult from Moments of a Circuit

        Args:
            circuit: The circuit to simulate.
            sim_state: The initial state args for the simulation in the
                computational basis.
            all_measurements_are_terminal: Indicator that all measurements
                are terminal, allowing optimization.

        Yields:
            DensityMatrixStepResult from simulating a Moment of the Circuit.
        """
        if len(circuit) == 0:
            yield DensityMatrixStepResult(
                density_matrix=sim_state.target_tensor,
                measurements=dict(sim_state.log_of_measurement_results),
                qubit_map=sim_state.qubit_map,
                dtype=self._dtype,
            )
            return

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))
        measured = collections.defaultdict(
            bool)  # type: Dict[Tuple[cirq.Qid, ...], bool]
        for moment in noisy_moments:
            for op in flatten_to_ops(moment):
                # TODO: support more general measurements.
                # Github issue: https://github.com/quantumlib/Cirq/issues/3566
                if all_measurements_are_terminal and measured[op.qubits]:
                    continue
                if protocols.is_measurement(op):
                    measured[op.qubits] = True
                    if all_measurements_are_terminal:
                        continue
                    if self._ignore_measurement_results:
                        op = ops.phase_damp(1).on(*op.qubits)
                sim_state.axes = tuple(sim_state.qubit_map[qubit]
                                       for qubit in op.qubits)
                protocols.act_on(op, sim_state)

            yield DensityMatrixStepResult(
                density_matrix=sim_state.target_tensor,
                measurements=dict(sim_state.log_of_measurement_results),
                qubit_map=sim_state.qubit_map,
                dtype=self._dtype,
            )
            sim_state.log_of_measurement_results.clear()
Example #5
0
    def _core_iterator(
        self,
        circuit: circuits.Circuit,
        sim_state: TActOnArgs,
        all_measurements_are_terminal: bool = False,
    ) -> Iterator[TStepResult]:
        """Standard iterator over StepResult from Moments of a Circuit.

        Args:
            circuit: The circuit to simulate.
            sim_state: The initial args for the simulation. The form of
                this state depends on the simulation implementation. See
                documentation of the implementing class for details.

        Yields:
            StepResults from simulating a Moment of the Circuit.
        """
        if len(circuit) == 0:
            yield self._create_step_result(sim_state, sim_state.qubit_map)
            return

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))
        measured: Dict[Tuple[cirq.Qid, ...],
                       bool] = collections.defaultdict(bool)
        for moment in noisy_moments:
            for op in ops.flatten_to_ops(moment):
                try:
                    # TODO: support more general measurements.
                    # Github issue: https://github.com/quantumlib/Cirq/issues/3566
                    if all_measurements_are_terminal and measured[op.qubits]:
                        continue
                    if isinstance(op.gate, ops.MeasurementGate):
                        measured[op.qubits] = True
                        if all_measurements_are_terminal:
                            continue
                        if self._ignore_measurement_results:
                            op = ops.phase_damp(1).on(*op.qubits)
                    sim_state.axes = tuple(sim_state.qubit_map[qubit]
                                           for qubit in op.qubits)
                    protocols.act_on(op, sim_state)
                except TypeError:
                    raise TypeError(
                        f"{self.__class__.__name__} doesn't support {op!r}")

            yield self._create_step_result(sim_state, sim_state.qubit_map)
            sim_state.log_of_measurement_results.clear()
Example #6
0
    def _base_iterator(self,
                       circuit: circuits.Circuit,
                       qubit_order: ops.QubitOrderOrList,
                       initial_state: Union[int, np.ndarray],
                       all_measurements_are_terminal=False) -> Iterator:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        initial_matrix = density_matrix_utils.to_valid_density_matrix(
            initial_state,
            len(qid_shape),
            qid_shape=qid_shape,
            dtype=self._dtype)
        measured = collections.defaultdict(
            bool)  # type: Dict[Tuple[cirq.Qid, ...], bool]
        if len(circuit) == 0:
            yield DensityMatrixStepResult(initial_matrix, {}, qubit_map,
                                          self._dtype)
            return

        state = _StateAndBuffers(len(qid_shape),
                                 initial_matrix.reshape(qid_shape * 2))

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate operations that don't implement "
                "SupportsUnitary, SupportsConsistentApplyUnitary, "
                "SupportsMixture, SupportsChannel or is a measurement: {!r}".
                format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_channel(potential_op)
                    or isinstance(potential_op.gate, ops.MeasurementGate))

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))

        for moment in noisy_moments:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[int]]

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

            for op in channel_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                # TODO: support more general measurements.
                if all_measurements_are_terminal and measured[op.qubits]:
                    continue
                if isinstance(op.gate, ops.MeasurementGate):
                    measured[op.qubits] = True
                    meas = op.gate
                    if all_measurements_are_terminal:
                        continue
                    if self._ignore_measurement_results:
                        for i, q in enumerate(op.qubits):
                            self._apply_op_channel(
                                ops.phase_damp(1).on(q), state, [indices[i]])
                    else:
                        invert_mask = meas.full_invert_mask()
                        # Measure updates inline.
                        bits, _ = (density_matrix_utils.measure_density_matrix(
                            state.tensor,
                            indices,
                            qid_shape=qid_shape,
                            out=state.tensor,
                            seed=self._prng))
                        corrected = [
                            bit ^ (bit < 2 and mask)
                            for bit, mask in zip(bits, invert_mask)
                        ]
                        key = protocols.measurement_key(meas)
                        measurements[key].extend(corrected)
                else:
                    # TODO: Use apply_channel similar to apply_unitary.
                    self._apply_op_channel(op, state, indices)
            yield DensityMatrixStepResult(density_matrix=state.tensor,
                                          measurements=measurements,
                                          qubit_map=qubit_map,
                                          dtype=self._dtype)
Example #7
0
    def _base_iterator(
        self,
        circuit: circuits.Circuit,
        qubit_order: ops.QubitOrderOrList,
        initial_state: Union[np.ndarray, 'cirq.STATE_VECTOR_LIKE'],
        all_measurements_are_terminal=False,
        is_raw_state=False,
    ) -> Iterator['DensityMatrixStepResult']:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        initial_matrix = (qis.to_valid_density_matrix(initial_state,
                                                      len(qid_shape),
                                                      qid_shape=qid_shape,
                                                      dtype=self._dtype)
                          if not is_raw_state else initial_state)
        if np.may_share_memory(initial_matrix, initial_state):
            initial_matrix = initial_matrix.copy()

        if len(circuit) == 0:
            yield DensityMatrixStepResult(initial_matrix, {}, qubit_map,
                                          self._dtype)
            return

        tensor = initial_matrix.reshape(qid_shape * 2)
        sim_state = act_on_density_matrix_args.ActOnDensityMatrixArgs(
            target_tensor=tensor,
            available_buffer=[np.empty_like(tensor) for _ in range(3)],
            axes=[],
            qid_shape=qid_shape,
            prng=self._prng,
            log_of_measurement_results={},
        )

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))
        measured = collections.defaultdict(
            bool)  # type: Dict[Tuple[cirq.Qid, ...], bool]
        for moment in noisy_moments:
            for op in flatten_to_ops(moment):
                # TODO: support more general measurements.
                # Github issue: https://github.com/quantumlib/Cirq/issues/3566
                if all_measurements_are_terminal and measured[op.qubits]:
                    continue
                if protocols.is_measurement(op):
                    measured[op.qubits] = True
                    if all_measurements_are_terminal:
                        continue
                    if self._ignore_measurement_results:
                        op = ops.phase_damp(1).on(*op.qubits)
                sim_state.axes = tuple(qubit_map[qubit] for qubit in op.qubits)
                protocols.act_on(op, sim_state)

            yield DensityMatrixStepResult(
                density_matrix=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()