def _create_target_circuit_type(ops: ops.OP_TREE, target_circuit: CIRCUIT_TYPE) -> CIRCUIT_TYPE: return cast( CIRCUIT_TYPE, circuits.Circuit(ops) if isinstance(target_circuit, circuits.Circuit) else circuits.FrozenCircuit(ops), )
def map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE': op_untagged = op.untagged if ( deep and isinstance(op_untagged, circuits.CircuitOperation) and merged_circuit_op_tag not in op.tags ): return op_untagged.replace( circuit=_rewrite_merged_k_qubit_unitaries( op_untagged.circuit, context=context, k=k, rewriter=rewriter, merged_circuit_op_tag=merged_circuit_op_tag, ).freeze() ).with_tags(*op.tags) if not (protocols.num_qubits(op) <= k and protocols.has_unitary(op)): return op if rewriter: return rewriter( cast(circuits.CircuitOperation, op_untagged) if merged_circuit_op_tag in op.tags else circuits.CircuitOperation(circuits.FrozenCircuit(op)) ) return ops.MatrixGate(protocols.unitary(op)).on(*op.qubits)
def map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE': if not (protocols.num_qubits(op) <= k and protocols.has_unitary(op)): return op if rewriter: return rewriter( cast(circuits.CircuitOperation, op.untagged ) if merged_circuit_op_tag in op.tags else circuits. CircuitOperation(circuits.FrozenCircuit(op))) return ops.MatrixGate(protocols.unitary(op)).on(*op.qubits)
def apply_map(op: ops.Operation, idx: int) -> ops.OP_TREE: c = circuits.FrozenCircuit(map_func(op, idx)) if not c.all_qubits().issubset(op.qubits): raise ValueError( f"Mapped operations {c.all_operations()} should act on a subset " f"of qubits of the original operation {op}" ) if len(c) == 1: # All operations act in the same moment; so we don't need to wrap them in a circuit_op. return c[0].operations circuit_op = circuits.CircuitOperation(c).with_tags(MAPPED_CIRCUIT_OP_TAG) return circuit_op
def merge_func(op1: 'cirq.Operation', op2: 'cirq.Operation') -> Optional['cirq.Operation']: def get_ops(op: 'cirq.Operation'): op_untagged = op.untagged return ([*op_untagged.circuit.all_operations()] if isinstance(op_untagged, circuits.CircuitOperation) and merged_circuit_op_tag in op.tags else [op]) left_ops, right_ops = get_ops(op1), get_ops(op2) if not can_merge(left_ops, right_ops): return None return circuits.CircuitOperation( circuits.FrozenCircuit(left_ops, right_ops)).with_tags(merged_circuit_op_tag)
def apply_map(op: ops.Operation, idx: int) -> ops.OP_TREE: if not set(op.tags).isdisjoint(tags_to_ignore): return op c = circuits.FrozenCircuit(map_func(op, idx)) if raise_if_add_qubits and not c.all_qubits().issubset(op.qubits): raise ValueError( f"Mapped operations {c.all_operations()} should act on a subset " f"of qubits of the original operation {op}") if len(c) <= 1: # Either empty circuit or all operations act in the same moment; # So, we don't need to wrap them in a circuit_op. return c[0].operations if c else [] circuit_op = circuits.CircuitOperation(c).with_tags( MAPPED_CIRCUIT_OP_TAG) return circuit_op