def acquaint_insides( swap_gate: 'cirq.Gate', acquaintance_gate: 'cirq.Operation', qubits: Sequence['cirq.Qid'], before: bool, layers: Layers, mapping: Dict[ops.Qid, int], ) -> None: """Acquaints each of the qubits with another set specified by an acquaintance gate. Args: qubits: The list of qubits of which half are individually acquainted with another list of qubits. layers: The layers to put gates into. acquaintance_gate: The acquaintance gate that acquaints the end qubit with another list of qubits. before: Whether the acquainting is done before the shift. swap_gate: The gate used to swap logical indices. mapping: The mapping from qubits to logical indices. Used to keep track of the effect of inside-acquainting swaps. """ max_reach = _get_max_reach(len(qubits), round_up=before) reaches = itertools.chain(range(1, max_reach + 1), range(max_reach, -1, -1)) offsets = (0, 1) * max_reach swap_gate = SwapPermutationGate(swap_gate) ops = [] for offset, reach in zip(offsets, reaches): if offset == before: ops.append(acquaintance_gate) for dr in range(offset, reach, 2): ops.append(swap_gate(*qubits[dr:dr + 2])) intrastitial_layer = getattr(layers, 'pre' if before else 'post') intrastitial_layer += ops # add interstitial gate interstitial_layer = getattr(layers, ('prior' if before else 'posterior') + '_interstitial') interstitial_layer.append(acquaintance_gate) # update mapping reached_qubits = qubits[:max_reach + 1] positions = list(mapping[q] for q in reached_qubits) mapping.update(zip(reached_qubits, reversed(positions)))
def param_H(w_half_turns, w_axis_half_turns, z_half_turns, target): """Returns a parametrized Hadamard gate composed of gates in Cirq's native gate set.""" op = [] op.append(param_Winv(w_half_turns, w_axis_half_turns)(target)) op.append(param_Z(z_half_turns)(target)) op.append(param_W(w_half_turns, w_axis_half_turns)(target)) return op
def param_CNOT(w_half_turns, w_axis_half_turns, proj11_half_turns, z_half_turns, control, target): """Returns a parametrized Hadamard gate composed of gates in Cirq's native gate set.""" op = [] op.append(param_H(w_half_turns, w_axis_half_turns, z_half_turns, target)) op.append(param_11(proj11_half_turns)(control, target)) op.append(param_H(w_half_turns, w_axis_half_turns, z_half_turns, target)) out = np.asarray(op) out.flatten() out.tolist() return out
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