Пример #1
0
def q_if(operation, num_ctrl_qubits=1, label=None):
    """Return controlled version of gate using controlled rotations

    Args:
        operation (Gate or Controlledgate): gate to create ControlledGate from
        num_ctrl_qubits (int): number of controls to add to gate (default=1)
        label (str): optional gate label
    Returns:
        ControlledGate: controlled version of gate. This default algorithm
            uses num_ctrl_qubits-1 ancillae qubits so returns a gate of size
            num_qubits + 2*num_ctrl_qubits - 1.

    Raises:
        QiskitError: gate contains non-gate in definitionl
    """
    from math import pi
    # pylint: disable=cyclic-import
    import qiskit.circuit.controlledgate as controlledgate
    from qiskit.circuit.quantumregister import QuantumRegister
    from qiskit.circuit.quantumcircuit import QuantumCircuit
    # pylint: disable=unused-import
    import qiskit.extensions.standard.multi_control_rotation_gates
    import qiskit.extensions.standard.multi_control_toffoli_gate
    import qiskit.extensions.standard.multi_control_u1_gate

    q_control = QuantumRegister(num_ctrl_qubits, name='control')
    q_target = QuantumRegister(operation.num_qubits, name='target')
    q_ancillae = None  # TODO: add

    qc = QuantumCircuit(q_control, q_target)

    if operation.name == 'x' or (isinstance(operation,
                                            controlledgate.ControlledGate)
                                 and operation.base_gate_name == 'x'):
        qc.mct(q_control[:] + q_target[:-1],
               q_target[-1],
               None,
               mode='noancilla')
    elif operation.name == 'rx':
        qc.mcrx(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                use_basis_gates=True)
    elif operation.name == 'ry':
        qc.mcry(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                q_ancillae,
                use_basis_gates=True)
    elif operation.name == 'rz':
        qc.mcrz(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                use_basis_gates=True)
    else:
        bgate = _unroll_gate(operation, ['u1', 'u3', 'cx'])
        # now we have a bunch of single qubit rotation gates and cx
        for rule in bgate.definition:
            if rule[0].name == 'u3':
                theta, phi, lamb = rule[0].params
                if phi == -pi / 2 and lamb == pi / 2:
                    qc.mcrx(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                elif phi == 0 and lamb == 0:
                    qc.mcry(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            q_ancillae,
                            mode='noancilla',
                            use_basis_gates=True)
                elif theta == 0 and phi == 0:
                    qc.mcrz(lamb,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                else:
                    qc.mcrz(lamb,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                    qc.mcry(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            q_ancillae,
                            use_basis_gates=True)
                    qc.mcrz(phi,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
            elif rule[0].name == 'u1':
                qc.mcu1(rule[0].params[0], q_control,
                        q_target[rule[1][0].index])
            elif rule[0].name == 'cx':
                qc.mct(q_control[:] + [q_target[rule[1][0].index]],
                       q_target[rule[1][1].index],
                       None,
                       mode='noancilla')
            else:
                raise QiskitError('gate contains non-controllable intructions')
    instr = qc.to_instruction()
    if isinstance(operation, controlledgate.ControlledGate):
        new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits
        base_name = operation.base_gate_name
        base_gate = operation.base_gate
        base_gate_name = operation.base_gate_name
    else:
        new_num_ctrl_qubits = num_ctrl_qubits
        base_name = operation.name
        base_gate = operation.__class__
        base_gate_name = operation.name
    # In order to maintain some backward compatibility with gate names this
    # uses a naming convention where if the number of controls is <=2 the gate
    # is named like "cc<base_gate_name>", else it is named like
    # "c<num_ctrl_qubits><base_name>".
    if new_num_ctrl_qubits > 2:
        ctrl_substr = 'c{0:d}'.format(new_num_ctrl_qubits)
    else:
        ctrl_substr = ('{0}' * new_num_ctrl_qubits).format('c')
    new_name = '{0}{1}'.format(ctrl_substr, base_name)
    cgate = controlledgate.ControlledGate(new_name,
                                          instr.num_qubits,
                                          operation.params,
                                          label=label,
                                          num_ctrl_qubits=new_num_ctrl_qubits,
                                          definition=instr.definition)
    cgate.base_gate = base_gate
    cgate.base_gate_name = base_gate_name
    return cgate
Пример #2
0
def control(
        operation: Union[Gate, ControlledGate],
        num_ctrl_qubits: Optional[int] = 1,
        label: Optional[Union[None, str]] = None,
        ctrl_state: Optional[Union[None, int, str]] = None) -> ControlledGate:
    """Return controlled version of gate using controlled rotations. This function
    first checks the name of the operation to see if it knows of a method from which
    to generate a controlled version. Currently these are `x`, `rx`, `ry`, and `rz`.
    If a method is not directly known, it calls the unroller to convert to `u1`, `u3`,
    and `cx` gates.

    Args:
        operation: The gate used to create the ControlledGate.
        num_ctrl_qubits: The number of controls to add to gate (default=1).
        label: An optional gate label.
        ctrl_state: The control state in decimal or as
            a bitstring (e.g. '111'). If specified as a bitstring the length
            must equal num_ctrl_qubits, MSB on left. If None, use
            2**num_ctrl_qubits-1.

    Returns:
        Controlled version of gate.

    Raises:
        CircuitError: gate contains non-gate in definition
    """
    from math import pi
    # pylint: disable=cyclic-import
    import qiskit.circuit.controlledgate as controlledgate
    # pylint: disable=unused-import
    import qiskit.circuit.library.standard_gates.multi_control_rotation_gates

    # check args
    if num_ctrl_qubits == 0:
        return operation
    elif num_ctrl_qubits < 0:
        raise CircuitError('number of control qubits must be positive integer')

    q_control = QuantumRegister(num_ctrl_qubits, name='control')
    q_target = QuantumRegister(operation.num_qubits, name='target')
    q_ancillae = None  # TODO: add
    qc = QuantumCircuit(q_control, q_target)

    if operation.name == 'x' or (isinstance(operation,
                                            controlledgate.ControlledGate)
                                 and operation.base_gate.name == 'x'):
        qc.mct(q_control[:] + q_target[:-1], q_target[-1], q_ancillae)
    elif operation.name == 'rx':
        qc.mcrx(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                use_basis_gates=True)
    elif operation.name == 'ry':
        qc.mcry(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                q_ancillae,
                mode='noancilla',
                use_basis_gates=True)
    elif operation.name == 'rz':
        qc.mcrz(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                use_basis_gates=True)
    else:
        bgate = _unroll_gate(operation, ['u1', 'u3', 'cx'])
        # now we have a bunch of single qubit rotation gates and cx
        for rule in bgate.definition:
            if rule[0].name == 'u3':
                theta, phi, lamb = rule[0].params
                if phi == -pi / 2 and lamb == pi / 2:
                    qc.mcrx(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                elif phi == 0 and lamb == 0:
                    qc.mcry(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            q_ancillae,
                            use_basis_gates=True)
                elif theta == 0 and phi == 0:
                    qc.mcrz(lamb,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                else:
                    qc.mcrz(lamb,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                    qc.mcry(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            q_ancillae,
                            use_basis_gates=True)
                    qc.mcrz(phi,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
            elif rule[0].name == 'u1':
                qc.mcu1(rule[0].params[0], q_control,
                        q_target[rule[1][0].index])
            elif rule[0].name == 'cx':
                qc.mct(q_control[:] + [q_target[rule[1][0].index]],
                       q_target[rule[1][1].index], q_ancillae)
            else:
                raise CircuitError(
                    'gate contains non-controllable instructions')

    instr = qc.to_instruction()
    if isinstance(operation, controlledgate.ControlledGate):
        new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits
        new_ctrl_state = operation.ctrl_state << num_ctrl_qubits | ctrl_state
        base_name = operation.base_gate.name
        base_gate = operation.base_gate
    else:
        new_num_ctrl_qubits = num_ctrl_qubits
        new_ctrl_state = ctrl_state
        base_name = operation.name
        base_gate = operation
    # In order to maintain some backward compatibility with gate names this
    # uses a naming convention where if the number of controls is <=2 the gate
    # is named like "cc<base_gate.name>", else it is named like
    # "c<num_ctrl_qubits><base_name>".
    if new_num_ctrl_qubits > 2:
        ctrl_substr = 'c{0:d}'.format(new_num_ctrl_qubits)
    else:
        ctrl_substr = ('{0}' * new_num_ctrl_qubits).format('c')
    new_name = '{0}{1}'.format(ctrl_substr, base_name)
    cgate = controlledgate.ControlledGate(new_name,
                                          instr.num_qubits,
                                          operation.params,
                                          label=label,
                                          num_ctrl_qubits=new_num_ctrl_qubits,
                                          definition=instr.definition,
                                          ctrl_state=new_ctrl_state)
    cgate.base_gate = base_gate
    return cgate
Пример #3
0
def control(
    operation: Union[Gate, ControlledGate],
    num_ctrl_qubits: Optional[int] = 1,
    label: Optional[Union[None, str]] = None,
    ctrl_state: Optional[Union[None, int, str]] = None,
) -> ControlledGate:
    """Return controlled version of gate using controlled rotations. This function
    first checks the name of the operation to see if it knows of a method from which
    to generate a controlled version. Currently these are `x`, `rx`, `ry`, and `rz`.
    If a method is not directly known, it calls the unroller to convert to `u1`, `u3`,
    and `cx` gates.

    Args:
        operation: The gate used to create the ControlledGate.
        num_ctrl_qubits: The number of controls to add to gate (default=1).
        label: An optional gate label.
        ctrl_state: The control state in decimal or as
            a bitstring (e.g. '111'). If specified as a bitstring the length
            must equal num_ctrl_qubits, MSB on left. If None, use
            2**num_ctrl_qubits-1.

    Returns:
        Controlled version of gate.

    Raises:
        CircuitError: gate contains non-gate in definition
    """
    from math import pi

    # pylint: disable=cyclic-import
    import qiskit.circuit.controlledgate as controlledgate

    q_control = QuantumRegister(num_ctrl_qubits, name="control")
    q_target = QuantumRegister(operation.num_qubits, name="target")
    q_ancillae = None  # TODO: add
    controlled_circ = QuantumCircuit(q_control,
                                     q_target,
                                     name="c_{}".format(operation.name))
    if isinstance(operation, controlledgate.ControlledGate):
        original_ctrl_state = operation.ctrl_state
    global_phase = 0
    if operation.name == "x" or (isinstance(operation,
                                            controlledgate.ControlledGate)
                                 and operation.base_gate.name == "x"):
        controlled_circ.mct(q_control[:] + q_target[:-1], q_target[-1],
                            q_ancillae)
        if operation.definition is not None and operation.definition.global_phase:
            global_phase += operation.definition.global_phase
    else:
        basis = ["p", "u", "x", "z", "rx", "ry", "rz", "cx"]
        if isinstance(operation, controlledgate.ControlledGate):
            operation.ctrl_state = None
        unrolled_gate = _unroll_gate(operation, basis_gates=basis)
        if unrolled_gate.definition.global_phase:
            global_phase += unrolled_gate.definition.global_phase

        definition = unrolled_gate.definition
        bit_indices = {
            bit: index
            for bits in [definition.qubits, definition.clbits]
            for index, bit in enumerate(bits)
        }

        for gate, qargs, _ in definition.data:
            if gate.name == "x":
                controlled_circ.mct(q_control, q_target[bit_indices[qargs[0]]],
                                    q_ancillae)
            elif gate.name == "rx":
                controlled_circ.mcrx(
                    gate.definition.data[0][0].params[0],
                    q_control,
                    q_target[bit_indices[qargs[0]]],
                    use_basis_gates=True,
                )
            elif gate.name == "ry":
                controlled_circ.mcry(
                    gate.definition.data[0][0].params[0],
                    q_control,
                    q_target[bit_indices[qargs[0]]],
                    q_ancillae,
                    mode="noancilla",
                    use_basis_gates=True,
                )
            elif gate.name == "rz":
                controlled_circ.mcrz(
                    gate.definition.data[0][0].params[0],
                    q_control,
                    q_target[bit_indices[qargs[0]]],
                    use_basis_gates=True,
                )
            elif gate.name == "p":
                from qiskit.circuit.library import MCPhaseGate

                controlled_circ.append(
                    MCPhaseGate(gate.params[0], num_ctrl_qubits),
                    q_control[:] + [q_target[bit_indices[qargs[0]]]],
                )
            elif gate.name == "cx":
                controlled_circ.mct(
                    q_control[:] + [q_target[bit_indices[qargs[0]]]],
                    q_target[bit_indices[qargs[1]]],
                    q_ancillae,
                )
            elif gate.name == "u":
                theta, phi, lamb = gate.params
                if num_ctrl_qubits == 1:
                    if theta == 0 and phi == 0:
                        controlled_circ.cp(lamb, q_control[0],
                                           q_target[bit_indices[qargs[0]]])
                    else:
                        controlled_circ.cu(theta, phi, lamb, 0, q_control[0],
                                           q_target[bit_indices[qargs[0]]])
                else:
                    if phi == -pi / 2 and lamb == pi / 2:
                        controlled_circ.mcrx(theta,
                                             q_control,
                                             q_target[bit_indices[qargs[0]]],
                                             use_basis_gates=True)
                    elif phi == 0 and lamb == 0:
                        controlled_circ.mcry(
                            theta,
                            q_control,
                            q_target[bit_indices[qargs[0]]],
                            q_ancillae,
                            use_basis_gates=True,
                        )
                    elif theta == 0 and phi == 0:
                        controlled_circ.mcrz(lamb,
                                             q_control,
                                             q_target[bit_indices[qargs[0]]],
                                             use_basis_gates=True)
                    else:
                        controlled_circ.mcrz(lamb,
                                             q_control,
                                             q_target[bit_indices[qargs[0]]],
                                             use_basis_gates=True)
                        controlled_circ.mcry(
                            theta,
                            q_control,
                            q_target[bit_indices[qargs[0]]],
                            q_ancillae,
                            use_basis_gates=True,
                        )
                        controlled_circ.mcrz(phi,
                                             q_control,
                                             q_target[bit_indices[qargs[0]]],
                                             use_basis_gates=True)
            elif gate.name == "z":
                controlled_circ.h(q_target[bit_indices[qargs[0]]])
                controlled_circ.mcx(q_control, q_target[bit_indices[qargs[0]]],
                                    q_ancillae)
                controlled_circ.h(q_target[bit_indices[qargs[0]]])
            else:
                raise CircuitError(
                    "gate contains non-controllable instructions: {}".format(
                        gate.name))
            if gate.definition is not None and gate.definition.global_phase:
                global_phase += gate.definition.global_phase
    # apply controlled global phase
    if global_phase:
        if len(q_control) < 2:
            controlled_circ.p(global_phase, q_control)
        else:
            controlled_circ.mcp(global_phase, q_control[:-1], q_control[-1])
    if isinstance(operation, controlledgate.ControlledGate):
        operation.ctrl_state = original_ctrl_state
        new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits
        new_ctrl_state = operation.ctrl_state << num_ctrl_qubits | ctrl_state
        base_name = operation.base_gate.name
        base_gate = operation.base_gate
    else:
        new_num_ctrl_qubits = num_ctrl_qubits
        new_ctrl_state = ctrl_state
        base_name = operation.name
        base_gate = operation
    # In order to maintain some backward compatibility with gate names this
    # uses a naming convention where if the number of controls is <=2 the gate
    # is named like "cc<base_gate.name>", else it is named like
    # "c<num_ctrl_qubits><base_name>".
    if new_num_ctrl_qubits > 2:
        ctrl_substr = "c{:d}".format(new_num_ctrl_qubits)
    else:
        ctrl_substr = ("{0}" * new_num_ctrl_qubits).format("c")
    new_name = "{}{}".format(ctrl_substr, base_name)
    cgate = controlledgate.ControlledGate(
        new_name,
        controlled_circ.num_qubits,
        operation.params,
        label=label,
        num_ctrl_qubits=new_num_ctrl_qubits,
        definition=controlled_circ,
        ctrl_state=new_ctrl_state,
        base_gate=base_gate,
    )
    return cgate
Пример #4
0
def control(
        operation: Union[Gate, ControlledGate],
        num_ctrl_qubits: Optional[int] = 1,
        label: Optional[Union[None, str]] = None,
        ctrl_state: Optional[Union[None, int, str]] = None) -> ControlledGate:
    """Return controlled version of gate using controlled rotations. This function
    first checks the name of the operation to see if it knows of a method from which
    to generate a controlled version. Currently these are `x`, `rx`, `ry`, and `rz`.
    If a method is not directly known, it calls the unroller to convert to `u1`, `u3`,
    and `cx` gates.

    Args:
        operation: The gate used to create the ControlledGate.
        num_ctrl_qubits: The number of controls to add to gate (default=1).
        label: An optional gate label.
        ctrl_state: The control state in decimal or as
            a bitstring (e.g. '111'). If specified as a bitstring the length
            must equal num_ctrl_qubits, MSB on left. If None, use
            2**num_ctrl_qubits-1.

    Returns:
        Controlled version of gate.

    Raises:
        CircuitError: gate contains non-gate in definition
    """
    from math import pi
    # pylint: disable=cyclic-import
    import qiskit.circuit.controlledgate as controlledgate

    q_control = QuantumRegister(num_ctrl_qubits, name='control')
    q_target = QuantumRegister(operation.num_qubits, name='target')
    q_ancillae = None  # TODO: add
    controlled_circ = QuantumCircuit(q_control,
                                     q_target,
                                     name='c_{}'.format(operation.name))
    global_phase = 0
    if operation.name == 'x' or (isinstance(operation,
                                            controlledgate.ControlledGate)
                                 and operation.base_gate.name == 'x'):
        controlled_circ.mct(q_control[:] + q_target[:-1], q_target[-1],
                            q_ancillae)
        if operation.definition is not None and operation.definition.global_phase:
            global_phase += operation.definition.global_phase
    else:
        basis = ['u1', 'u3', 'x', 'rx', 'ry', 'rz', 'cx']
        unrolled_gate = _unroll_gate(operation, basis_gates=basis)
        for gate, qreg, _ in unrolled_gate.definition.data:
            if gate.name == 'x':
                controlled_circ.mct(q_control, q_target[qreg[0].index],
                                    q_ancillae)
            elif gate.name == 'rx':
                controlled_circ.mcrx(gate.definition.data[0][0].params[0],
                                     q_control,
                                     q_target[qreg[0].index],
                                     use_basis_gates=True)
            elif gate.name == 'ry':
                controlled_circ.mcry(gate.definition.data[0][0].params[0],
                                     q_control,
                                     q_target[qreg[0].index],
                                     q_ancillae,
                                     mode='noancilla',
                                     use_basis_gates=True)
            elif gate.name == 'rz':
                controlled_circ.mcrz(gate.definition.data[0][0].params[0],
                                     q_control,
                                     q_target[qreg[0].index],
                                     use_basis_gates=True)
            elif gate.name == 'u1':
                controlled_circ.mcu1(gate.params[0], q_control,
                                     q_target[qreg[0].index])
            elif gate.name == 'cx':
                controlled_circ.mct(q_control[:] + [q_target[qreg[0].index]],
                                    q_target[qreg[1].index], q_ancillae)
            elif gate.name == 'u3':
                theta, phi, lamb = gate.params
                if phi == -pi / 2 and lamb == pi / 2:
                    controlled_circ.mcrx(theta,
                                         q_control,
                                         q_target[qreg[0].index],
                                         use_basis_gates=True)
                elif phi == 0 and lamb == 0:
                    controlled_circ.mcry(theta,
                                         q_control,
                                         q_target[qreg[0].index],
                                         q_ancillae,
                                         use_basis_gates=True)
                elif theta == 0 and phi == 0:
                    controlled_circ.mcrz(lamb,
                                         q_control,
                                         q_target[qreg[0].index],
                                         use_basis_gates=True)
                else:
                    controlled_circ.mcrz(lamb,
                                         q_control,
                                         q_target[qreg[0].index],
                                         use_basis_gates=True)
                    controlled_circ.mcry(theta,
                                         q_control,
                                         q_target[qreg[0].index],
                                         q_ancillae,
                                         use_basis_gates=True)
                    controlled_circ.mcrz(phi,
                                         q_control,
                                         q_target[qreg[0].index],
                                         use_basis_gates=True)
            else:
                raise CircuitError(
                    'gate contains non-controllable instructions: {}'.format(
                        gate.name))
            if gate.definition is not None and gate.definition.global_phase:
                global_phase += gate.definition.global_phase
    # apply controlled global phase
    if ((operation.definition is not None
         and operation.definition.global_phase) or global_phase):
        if len(q_control) < 2:
            controlled_circ.u1(
                operation.definition.global_phase + global_phase, q_control)
        else:
            controlled_circ.mcu1(
                operation.definition.global_phase + global_phase,
                q_control[:-1], q_control[-1])
    if isinstance(operation, controlledgate.ControlledGate):
        new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits
        new_ctrl_state = operation.ctrl_state << num_ctrl_qubits | ctrl_state
        base_name = operation.base_gate.name
        base_gate = operation.base_gate
    else:
        new_num_ctrl_qubits = num_ctrl_qubits
        new_ctrl_state = ctrl_state
        base_name = operation.name
        base_gate = operation
    # In order to maintain some backward compatibility with gate names this
    # uses a naming convention where if the number of controls is <=2 the gate
    # is named like "cc<base_gate.name>", else it is named like
    # "c<num_ctrl_qubits><base_name>".
    if new_num_ctrl_qubits > 2:
        ctrl_substr = 'c{0:d}'.format(new_num_ctrl_qubits)
    else:
        ctrl_substr = ('{0}' * new_num_ctrl_qubits).format('c')
    new_name = '{0}{1}'.format(ctrl_substr, base_name)
    cgate = controlledgate.ControlledGate(new_name,
                                          controlled_circ.num_qubits,
                                          operation.params,
                                          label=label,
                                          num_ctrl_qubits=new_num_ctrl_qubits,
                                          definition=controlled_circ,
                                          ctrl_state=new_ctrl_state)
    cgate.base_gate = base_gate
    return cgate
Пример #5
0
def control(
        operation: Union[Gate, ControlledGate],
        num_ctrl_qubits: Optional[int] = 1,
        label: Optional[Union[None, str]] = None,
        ctrl_state: Optional[Union[None, int, str]] = None) -> ControlledGate:
    """Return controlled version of gate using controlled rotations

    Args:
        operation: gate to create ControlledGate from
        num_ctrl_qubits: number of controls to add to gate (default=1)
        label: optional gate label
        ctrl_state: The control state in decimal or as
            a bitstring (e.g. '111'). If specified as a bitstring the length
            must equal num_ctrl_qubits, MSB on left. If None, use
            2**num_ctrl_qubits-1.

    Returns:
        Controlled version of gate.

    Raises:
        CircuitError: gate contains non-gate in definition
    """
    from math import pi
    # pylint: disable=cyclic-import
    import qiskit.circuit.controlledgate as controlledgate
    # pylint: disable=unused-import
    import qiskit.extensions.standard.multi_control_rotation_gates
    import qiskit.extensions.standard.multi_control_toffoli_gate
    import qiskit.extensions.standard.multi_control_u1_gate

    q_control = QuantumRegister(num_ctrl_qubits, name='control')
    q_target = QuantumRegister(operation.num_qubits, name='target')
    q_ancillae = None  # TODO: add
    qc = QuantumCircuit(q_control, q_target)

    if operation.name == 'x' or (isinstance(operation,
                                            controlledgate.ControlledGate)
                                 and operation.base_gate.name == 'x'):
        qc.mct(q_control[:] + q_target[:-1],
               q_target[-1],
               None,
               mode='noancilla')
    elif operation.name == 'rx':
        qc.mcrx(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                use_basis_gates=True)
    elif operation.name == 'ry':
        qc.mcry(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                q_ancillae,
                use_basis_gates=True)
    elif operation.name == 'rz':
        qc.mcrz(operation.definition[0][0].params[0],
                q_control,
                q_target[0],
                use_basis_gates=True)
    else:
        bgate = _unroll_gate(operation, ['u1', 'u3', 'cx'])
        # now we have a bunch of single qubit rotation gates and cx
        for rule in bgate.definition:
            if rule[0].name == 'u3':
                theta, phi, lamb = rule[0].params
                if phi == -pi / 2 and lamb == pi / 2:
                    qc.mcrx(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                elif phi == 0 and lamb == 0:
                    qc.mcry(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            q_ancillae,
                            mode='noancilla',
                            use_basis_gates=True)
                elif theta == 0 and phi == 0:
                    qc.mcrz(lamb,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                else:
                    qc.mcrz(lamb,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
                    qc.mcry(theta,
                            q_control,
                            q_target[rule[1][0].index],
                            q_ancillae,
                            use_basis_gates=True)
                    qc.mcrz(phi,
                            q_control,
                            q_target[rule[1][0].index],
                            use_basis_gates=True)
            elif rule[0].name == 'u1':
                qc.mcu1(rule[0].params[0], q_control,
                        q_target[rule[1][0].index])
            elif rule[0].name == 'cx':
                qc.mct(q_control[:] + [q_target[rule[1][0].index]],
                       q_target[rule[1][1].index],
                       None,
                       mode='noancilla')
            else:
                raise CircuitError(
                    'gate contains non-controllable instructions')
    instr = qc.to_instruction()
    if isinstance(operation, controlledgate.ControlledGate):
        new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits
        base_name = operation.base_gate.name
        base_gate = operation.base_gate
    else:
        new_num_ctrl_qubits = num_ctrl_qubits
        base_name = operation.name
        base_gate = operation
    # In order to maintain some backward compatibility with gate names this
    # uses a naming convention where if the number of controls is <=2 the gate
    # is named like "cc<base_gate.name>", else it is named like
    # "c<num_ctrl_qubits><base_name>".
    if new_num_ctrl_qubits > 2:
        ctrl_substr = 'c{0:d}'.format(new_num_ctrl_qubits)
    else:
        ctrl_substr = ('{0}' * new_num_ctrl_qubits).format('c')
    new_name = '{0}{1}'.format(ctrl_substr, base_name)
    cgate = controlledgate.ControlledGate(new_name,
                                          instr.num_qubits,
                                          operation.params,
                                          label=label,
                                          num_ctrl_qubits=new_num_ctrl_qubits,
                                          definition=instr.definition,
                                          ctrl_state=ctrl_state)
    cgate.base_gate = base_gate
    return cgate