code: 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
docs: 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.