File size: 5,039 Bytes
b7d9967
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Helper function for converting a circuit to an instruction."""

from qiskit.exceptions import QiskitError
from qiskit.circuit.instruction import Instruction
from qiskit.circuit.quantumregister import QuantumRegister
from qiskit.circuit.classicalregister import ClassicalRegister, Clbit


def circuit_to_instruction(circuit, parameter_map=None, equivalence_library=None, label=None):
    """Build an :class:`~.circuit.Instruction` object from a :class:`.QuantumCircuit`.



    The instruction is anonymous (not tied to a named quantum register),

    and so can be inserted into another circuit. The instruction will

    have the same string name as the circuit.



    Args:

        circuit (QuantumCircuit): the input circuit.

        parameter_map (dict): For parameterized circuits, a mapping from

           parameters in the circuit to parameters to be used in the instruction.

           If None, existing circuit parameters will also parameterize the

           instruction.

        equivalence_library (EquivalenceLibrary): Optional equivalence library

           where the converted instruction will be registered.

        label (str): Optional instruction label.



    Raises:

        QiskitError: if parameter_map is not compatible with circuit



    Return:

        qiskit.circuit.Instruction: an instruction equivalent to the action of the

        input circuit. Upon decomposition, this instruction will

        yield the components comprising the original circuit.



    Example:

        .. code-block::



            from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

            from qiskit.converters import circuit_to_instruction



            q = QuantumRegister(3, 'q')

            c = ClassicalRegister(3, 'c')

            circ = QuantumCircuit(q, c)

            circ.h(q[0])

            circ.cx(q[0], q[1])

            circ.measure(q[0], c[0])

            circ.rz(0.5, q[1]).c_if(c, 2)

            circuit_to_instruction(circ)

    """
    # pylint: disable=cyclic-import
    from qiskit.circuit.quantumcircuit import QuantumCircuit

    if parameter_map is None:
        parameter_dict = {p: p for p in circuit.parameters}
    else:
        parameter_dict = circuit._unroll_param_dict(parameter_map)

    if parameter_dict.keys() != circuit.parameters:
        raise QiskitError(
            (
                "parameter_map should map all circuit parameters. "
                "Circuit parameters: {}, parameter_map: {}"
            ).format(circuit.parameters, parameter_dict)
        )

    out_instruction = Instruction(
        name=circuit.name,
        num_qubits=circuit.num_qubits,
        num_clbits=circuit.num_clbits,
        params=[*parameter_dict.values()],
        label=label,
    )
    out_instruction.condition = None

    target = circuit.assign_parameters(parameter_dict, inplace=False)

    if equivalence_library is not None:
        equivalence_library.add_equivalence(out_instruction, target)

    regs = []
    if out_instruction.num_qubits > 0:
        q = QuantumRegister(out_instruction.num_qubits, "q")
        regs.append(q)

    if out_instruction.num_clbits > 0:
        c = ClassicalRegister(out_instruction.num_clbits, "c")
        regs.append(c)

    qubit_map = {bit: q[idx] for idx, bit in enumerate(circuit.qubits)}
    clbit_map = {bit: c[idx] for idx, bit in enumerate(circuit.clbits)}

    definition = [
        instruction.replace(
            qubits=[qubit_map[y] for y in instruction.qubits],
            clbits=[clbit_map[y] for y in instruction.clbits],
        )
        for instruction in target.data
    ]

    # fix condition
    for rule in definition:
        condition = getattr(rule.operation, "condition", None)
        if condition:
            reg, val = condition
            if isinstance(reg, Clbit):
                rule.operation.condition = (clbit_map[reg], val)
            elif reg.size == c.size:
                rule.operation.condition = (c, val)
            else:
                raise QiskitError(
                    "Cannot convert condition in circuit with "
                    "multiple classical registers to instruction"
                )

    qc = QuantumCircuit(*regs, name=out_instruction.name)
    for instruction in definition:
        qc._append(instruction)
    if circuit.global_phase:
        qc.global_phase = circuit.global_phase

    out_instruction.definition = qc

    return out_instruction