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
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
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
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()
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()
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)
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()