def control_gate(control: Qubit, gate: Gate) -> Gate:
    """Return a controlled unitary gate. Given a gate acting on K qubits,
    return a new gate on K+1 qubits prepended with a control bit. """

    if control in gate.qubits:
        raise ValueError('Gate and control qubits overlap')

    qubits = [control, *gate.qubits]
    gate_tensor = join_gates(P0(control), identity_gate(gate.qubits)).tensor \
        + join_gates(P1(control), gate).tensor
    controlled_gate = Gate(qubits=qubits, tensor=gate_tensor)

    return controlled_gate
def control_gate ( control : Qubit , gate : Gate ) -> Gate : if control in gate . qubits : raise ValueError ( 'Gate and control qubits overlap' ) qubits = [ control , * gate . qubits ] gate_tensor = join_gates ( P0 ( control ) , identity_gate ( gate . qubits ) ) . tensor + join_gates ( P1 ( control ) , gate ) . tensor controlled_gate = Gate ( qubits = qubits , tensor = gate_tensor ) return controlled_gate
Return a controlled unitary gate. Given a gate acting on K qubits,
    return a new gate on K+1 qubits prepended with a control bit.