def _base_iterator( self, circuit: circuits.Circuit, qubit_order: ops.QubitOrderOrList, initial_state: Union[int, np.ndarray], perform_measurements: bool = True) -> Iterator: qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for( circuit.all_qubits()) num_qubits = len(qubits) qubit_map = {q: i for i, q in enumerate(qubits)} matrix = density_matrix_utils.to_valid_density_matrix( initial_state, num_qubits, self._dtype) if len(circuit) == 0: yield DensityMatrixStepResult(matrix, {}, qubit_map, self._dtype) matrix = np.reshape(matrix, (2,) * num_qubits * 2) def on_stuck(bad_op: ops.Operation): return TypeError( "Can't simulate operations that don't implement " "SupportsUnitary, SupportsApplyUnitary, SupportsMixture, " "SupportsChannel or is a measurement: {!r}".format(bad_op)) def keep(potential_op: ops.Operation) -> bool: return (protocols.has_channel(potential_op) or (ops.op_gate_of_type(potential_op, ops.MeasurementGate) is not None) or isinstance(potential_op, (ops.SamplesDisplay, ops.WaveFunctionDisplay, ops.DensityMatrixDisplay)) ) matrix = np.reshape(matrix, (2,) * num_qubits * 2) noisy_moments = self.noise.noisy_moments(circuit, sorted(circuit.all_qubits())) for moment in noisy_moments: measurements = collections.defaultdict( list) # type: Dict[str, List[bool]] 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] if isinstance(op, (ops.SamplesDisplay, ops.WaveFunctionDisplay, ops.DensityMatrixDisplay)): continue # TODO: support more general measurements. meas = ops.op_gate_of_type(op, ops.MeasurementGate) if meas: if perform_measurements: invert_mask = meas.invert_mask or num_qubits * (False,) # Measure updates inline. bits, _ = density_matrix_utils.measure_density_matrix( matrix, indices, matrix) corrected = [bit ^ 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. gate = cast(ops.GateOperation, op).gate channel = protocols.channel(gate) sum_buffer = np.zeros((2,) * 2 * num_qubits, dtype=self._dtype) buffer = np.empty((2,) * 2 * num_qubits, dtype=self._dtype) out = np.empty((2,) * 2 * num_qubits, dtype=self._dtype) for krauss in channel: krauss_tensor = np.reshape(krauss.astype(self._dtype), (2,) * gate.num_qubits() * 2) result = linalg.targeted_conjugate_about(krauss_tensor, matrix, indices, buffer=buffer, out=out) sum_buffer += result np.copyto(dst=matrix, src=sum_buffer) yield DensityMatrixStepResult( density_matrix=matrix, measurements=measurements, qubit_map=qubit_map, dtype=self._dtype)
def _base_iterator(self, circuit: circuits.Circuit, qubit_order: ops.QubitOrderOrList, initial_state: Union[int, np.ndarray], perform_measurements: bool = True) -> 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) 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 (ops.op_gate_of_type(potential_op, ops.MeasurementGate) is not None) or isinstance(potential_op, (ops.SamplesDisplay, ops.WaveFunctionDisplay, ops.DensityMatrixDisplay))) 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] if isinstance(op, (ops.SamplesDisplay, ops.WaveFunctionDisplay, ops.DensityMatrixDisplay)): continue # TODO: support more general measurements. meas = ops.op_gate_of_type(op, ops.MeasurementGate) if meas: if perform_measurements: 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) 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: 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() 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) if not is_raw_state else initial_matrix, ) 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, allow_decompose=False) 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. # Github issue: https://github.com/quantumlib/Cirq/issues/1357 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: self._apply_op_channel(op, state, indices) yield DensityMatrixStepResult( density_matrix=state.tensor, measurements=measurements, qubit_map=qubit_map, dtype=self._dtype, )