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
|