def _base_iterator( self, circuit: circuits.Circuit, qubit_order: ops.QubitOrderOrList, initial_state: Union[int, np.ndarray], perform_measurements: bool = True, ) -> Iterator[simulator.StepResult]: 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)} state = wave_function.to_valid_state_vector(initial_state, num_qubits, self._dtype) def on_stuck(bad_op: ops.Operation): return TypeError( "Can't simulate unknown operations that don't specify a " "_unitary_ method, a _decompose_ method, or " "(_has_unitary_ + _apply_unitary_) methods" ": {!r}".format(bad_op)) def keep(potential_op: ops.Operation) -> bool: return (protocols.has_unitary(potential_op) or ops.MeasurementGate.is_measurement(potential_op)) state = np.reshape(state, (2, ) * num_qubits) buffer = np.empty((2, ) * num_qubits, dtype=self._dtype) for moment in circuit: measurements = collections.defaultdict( list) # type: Dict[str, List[bool]] unitary_ops_and_measurements = protocols.decompose( moment.operations, keep=keep, on_stuck_raise=on_stuck) for op in unitary_ops_and_measurements: indices = [qubit_map[qubit] for qubit in op.qubits] if ops.MeasurementGate.is_measurement(op): gate = cast(ops.MeasurementGate, cast(ops.GateOperation, op).gate) if perform_measurements: invert_mask = gate.invert_mask or num_qubits * ( False, ) # Measure updates inline. bits, _ = wave_function.measure_state_vector( state, indices, state) corrected = [ bit ^ mask for bit, mask in zip(bits, invert_mask) ] measurements[cast(str, gate.key)].extend(corrected) else: result = protocols.apply_unitary( op, args=protocols.ApplyUnitaryArgs( state, buffer, indices)) if result is buffer: buffer = state state = result yield SimulatorStep(state, measurements, qubit_map, self._dtype)
def _simulate_reset(self, op: ops.Operation, data: _StateAndBuffer, indices: List[int]) -> None: """Simulate an op that is a reset to the |0> state.""" if isinstance(op.gate, ops.ResetChannel): reset = op.gate # Do a silent measurement. bits, _ = wave_function.measure_state_vector( data.state, indices, out=data.state, qid_shape=data.state.shape) # Apply bit flip(s) to change the reset the bits to 0. for b, i, d in zip(bits, indices, protocols.qid_shape(reset)): if b == 0: continue # Already zero, no reset needed reset_unitary = _FlipGate(d, reset_value=b)(*op.qubits) self._simulate_unitary(reset_unitary, data, [i])
def _simulate_measurement(self, op: ops.Operation, data: _StateAndBuffer, indices: List[int], measurements: Dict[str, List[bool]], num_qubits: int) -> None: """Simulate an op that is a measurement in the computataional basis.""" meas = ops.op_gate_of_type(op, ops.MeasurementGate) # TODO: support measurement outside computational basis. if meas: invert_mask = meas.invert_mask or num_qubits * (False, ) # Measure updates inline. bits, _ = wave_function.measure_state_vector( data.state, indices, data.state) corrected = [bit ^ mask for bit, mask in zip(bits, invert_mask)] key = protocols.measurement_key(meas) measurements[key].extend(corrected)
def _simulate_measurement(self, op: ops.Operation, data: _StateAndBuffer, indices: List[int], measurements: Dict[str, List[int]], num_qubits: int) -> None: """Simulate an op that is a measurement in the computational basis.""" # TODO: support measurement outside computational basis. if isinstance(op.gate, ops.MeasurementGate): meas = op.gate invert_mask = meas.full_invert_mask() # Measure updates inline. bits, _ = wave_function.measure_state_vector( data.state, indices, out=data.state, qid_shape=data.state.shape, 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)
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)} state = wave_function.to_valid_state_vector(initial_state, num_qubits, self._dtype) if len(circuit) == 0: yield SparseSimulatorStep(state, {}, qubit_map, self._dtype) def on_stuck(bad_op: ops.Operation): return TypeError( "Can't simulate unknown operations that don't specify a " "_unitary_ method, a _decompose_ method, or " "(_has_unitary_ + _apply_unitary_) methods" ": {!r}".format(bad_op)) def keep(potential_op: ops.Operation) -> bool: return (protocols.has_unitary(potential_op) or protocols.is_measurement(potential_op)) state = np.reshape(state, (2, ) * num_qubits) buffer = np.empty((2, ) * num_qubits, dtype=self._dtype) for moment in circuit: measurements = collections.defaultdict( list) # type: Dict[str, List[bool]] non_display_ops = (op for op in moment if not isinstance(op, ( ops.SamplesDisplay, ops.WaveFunctionDisplay, ops.DensityMatrixDisplay))) unitary_ops_and_measurements = protocols.decompose( non_display_ops, keep=keep, on_stuck_raise=on_stuck) for op in unitary_ops_and_measurements: indices = [qubit_map[qubit] for qubit in op.qubits] # TODO: Support measurements outside of computational basis. # TODO: Support mixtures. 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, _ = wave_function.measure_state_vector( state, indices, state) corrected = [ bit ^ mask for bit, mask in zip(bits, invert_mask) ] key = protocols.measurement_key(meas) measurements[key].extend(corrected) else: result = protocols.apply_unitary( op, args=protocols.ApplyUnitaryArgs( state, buffer, indices)) if result is buffer: buffer = state state = result yield SparseSimulatorStep(state_vector=state, measurements=measurements, qubit_map=qubit_map, dtype=self._dtype)