def _brute_force_samples( self, initial_state: np.ndarray, circuit: circuits.Circuit, qubit_order: 'cirq.QubitOrderOrList', repetitions: int, ) -> Dict[str, np.ndarray]: """Repeatedly simulate a circuit in order to produce samples.""" if repetitions == 0: return { key: np.empty(shape=[0, 1]) for key in protocols.measurement_keys(circuit) } measurements: DefaultDict[ str, List[np.ndarray]] = collections.defaultdict(list) for _ in range(repetitions): all_step_results = self._base_iterator(circuit, initial_state=initial_state, qubit_order=qubit_order) for step_result in all_step_results: for k, v in step_result.measurements.items(): measurements[k].append(np.array(v, dtype=np.uint8)) return {k: np.array(v) for k, v in measurements.items()}
def _verify_unique_measurement_keys(circuit: circuits.Circuit): result = collections.Counter( key for op in ops.flatten_op_tree(iter(circuit)) for key in protocols.measurement_keys(op) ) if result: duplicates = [k for k, v in result.most_common() if v > 1] if duplicates: raise ValueError('Measurement key {} repeated'.format(",".join(duplicates)))
def __post_init__(self): if not isinstance(self.circuit, circuits.FrozenCircuit): raise TypeError( f'Expected circuit of type FrozenCircuit, got: {type(self.circuit)!r}' ) # Ensure that the circuit is invertible if the repetitions are negative. if self.repetitions < 0: try: protocols.inverse(self.circuit.unfreeze()) except TypeError: raise ValueError( f'repetitions are negative but the circuit is not invertible' ) # Initialize repetition_ids to default, if unspecified. Else, validate their length. loop_size = abs(self.repetitions) if not self.repetition_ids: object.__setattr__(self, 'repetition_ids', self._default_repetition_ids()) elif len(self.repetition_ids) != loop_size: raise ValueError( f'Expected repetition_ids to be a list of length {loop_size}, ' f'got: {self.repetition_ids}') # Disallow mapping to keys containing the `MEASUREMENT_KEY_SEPARATOR` for mapped_key in self.measurement_key_map.values(): if MEASUREMENT_KEY_SEPARATOR in mapped_key: raise ValueError( f'Mapping to invalid key: {mapped_key}. "{MEASUREMENT_KEY_SEPARATOR}" ' 'is not allowed for measurement keys in a CircuitOperation' ) # Validate the keys for all direct child measurements. They are not allowed to contain # `MEASUREMENT_KEY_SEPARATOR` for _, op in self.circuit.findall_operations(lambda op: not isinstance( op, CircuitOperation) and protocols.is_measurement(op)): for key in protocols.measurement_keys(op): key = self.measurement_key_map.get(key, key) if MEASUREMENT_KEY_SEPARATOR in key: raise ValueError( f'Measurement {op} found to have invalid key: {key}. ' f'"{MEASUREMENT_KEY_SEPARATOR}" is not allowed for measurement keys ' 'in a CircuitOperation. Consider remapping the key using ' '`measurement_key_map` in the CircuitOperation constructor.' ) # Disallow qid mapping dimension conflicts. for q, q_new in self.qubit_map.items(): if q_new.dimension != q.dimension: raise ValueError( f'Qid dimension conflict.\nFrom qid: {q}\nTo qid: {q_new}') # Ensure that param_resolver is converted to an actual ParamResolver. object.__setattr__(self, 'param_resolver', study.ParamResolver(self.param_resolver))
def _run_sweep_repeat(self, circuit: circuits.Circuit, repetitions: int) -> Dict[str, np.ndarray]: if repetitions == 0: return { key: np.empty(shape=[0, 1]) for key in protocols.measurement_keys(circuit) } measurements: DefaultDict[ str, List[np.ndarray]] = collections.defaultdict(list) for _ in range(repetitions): all_step_results = self._base_iterator( circuit, qubit_order=ops.QubitOrder.DEFAULT, initial_state=0) for step_result in all_step_results: for k, v in step_result.measurements.items(): measurements[k].append(np.array(v, dtype=np.uint8)) return {k: np.array(v) for k, v in measurements.items()}
def _decompose_(self) -> 'cirq.OP_TREE': result = self.circuit.unfreeze() result = result.transform_qubits(lambda q: self.qubit_map.get(q, q)) if self.repetitions < 0: result = result**-1 result = protocols.with_measurement_key_mapping( result, self.measurement_key_map) result = protocols.resolve_parameters(result, self.param_resolver, recursive=False) # repetition_ids don't need to be taken into account if the circuit has no measurements # or if repetition_ids are unset. if self.repetition_ids is None or not protocols.is_measurement(result): return list(result.all_operations()) * abs(self.repetitions) # If it's a measurement circuit with repetitions/repetition_ids, prefix the repetition_ids # to measurements. Details at https://tinyurl.com/measurement-repeated-circuitop. ops = [] # type: List[cirq.Operation] for parent_id in self.repetition_ids: for op in result.all_operations(): if isinstance(op, CircuitOperation): # For a CircuitOperation, prefix the current repetition_id to the children # repetition_ids. ops.append( op.with_repetition_ids( # If `op.repetition_ids` is None, this will return `[parent_id]`. cartesian_product_of_string_lists( [parent_id], op.repetition_ids))) elif protocols.is_measurement(op): # For a non-CircuitOperation measurement, prefix the current repetition_id # to the children measurement keys. Implemented by creating a mapping and # using the with_measurement_key_mapping protocol. ops.append( protocols.with_measurement_key_mapping( op, key_map={ key: f'{MEASUREMENT_KEY_SEPARATOR.join([parent_id, key])}' for key in protocols.measurement_keys(op) }, )) else: ops.append(op) return ops
def _run(self, circuit: circuits.Circuit, repetitions: int) -> Dict[str, np.ndarray]: measurements: Dict[str, List[int]] = { key: [] for key in protocols.measurement_keys(circuit) } qubits = circuit.all_qubits() for _ in range(repetitions): state = ActOnCliffordTableauArgs( CliffordTableau(num_qubits=len(qubits)), qubits=list(qubits), prng=self._prng, log_of_measurement_results={}, ) for op in circuit.all_operations(): protocols.act_on(op, state) for k, v in state.log_of_measurement_results.items(): measurements[k].append(v) return {k: np.array(v) for k, v in measurements.items()}
def _run(self, circuit: circuits.Circuit, repetitions: int) -> Dict[str, np.ndarray]: measurements: Dict[str, List[int]] = { key: [] for key in protocols.measurement_keys(circuit) } axes_map = {q: i for i, q in enumerate(circuit.all_qubits())} for _ in range(repetitions): state = ActOnCliffordTableauArgs( CliffordTableau(num_qubits=len(axes_map)), axes=(), prng=self._prng, log_of_measurement_results={}, ) for op in circuit.all_operations(): state.axes = tuple(axes_map[q] for q in op.qubits) protocols.act_on(op, state) for k, v in state.log_of_measurement_results.items(): measurements[k].append(v) return {k: np.array(v) for k, v in measurements.items()}