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