mirror of https://github.com/Qiskit/qiskit.git
add QuantumCircuit.from_instructions (#9006)
* add QuantumCircuit.from_instructions * simplify loop * handle both cases in just one method * delete stray import * fix type annotation * address comments Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
351da447f7
commit
8b58a8f41e
|
@ -14,6 +14,7 @@
|
|||
|
||||
"""Quantum circuit object."""
|
||||
|
||||
from __future__ import annotations
|
||||
import copy
|
||||
import itertools
|
||||
import functools
|
||||
|
@ -285,6 +286,45 @@ class QuantumCircuit:
|
|||
raise TypeError("Only a dictionary or None is accepted for circuit metadata")
|
||||
self._metadata = metadata
|
||||
|
||||
@staticmethod
|
||||
def from_instructions(
|
||||
instructions: Iterable[
|
||||
CircuitInstruction
|
||||
| tuple[qiskit.circuit.Instruction]
|
||||
| tuple[qiskit.circuit.Instruction, Iterable[Qubit]]
|
||||
| tuple[qiskit.circuit.Instruction, Iterable[Qubit], Iterable[Clbit]]
|
||||
],
|
||||
*,
|
||||
name: Optional[str] = None,
|
||||
global_phase: ParameterValueType = 0,
|
||||
metadata: Optional[dict] = None,
|
||||
) -> "QuantumCircuit":
|
||||
"""Construct a circuit from an iterable of CircuitInstructions.
|
||||
|
||||
Args:
|
||||
instructions: The instructions to add to the circuit.
|
||||
name: The name of the circuit.
|
||||
global_phase: The global phase of the circuit in radians.
|
||||
metadata: Arbitrary key value metadata to associate with the circuit.
|
||||
|
||||
Returns:
|
||||
The quantum circuit.
|
||||
"""
|
||||
circuit = QuantumCircuit(name=name, global_phase=global_phase, metadata=metadata)
|
||||
added_qubits = set()
|
||||
added_clbits = set()
|
||||
for instruction in instructions:
|
||||
if not isinstance(instruction, CircuitInstruction):
|
||||
instruction = CircuitInstruction(*instruction)
|
||||
qubits = [qubit for qubit in instruction.qubits if qubit not in added_qubits]
|
||||
clbits = [clbit for clbit in instruction.clbits if clbit not in added_clbits]
|
||||
circuit.add_bits(qubits)
|
||||
circuit.add_bits(clbits)
|
||||
added_qubits.update(qubits)
|
||||
added_clbits.update(clbits)
|
||||
circuit._append(instruction)
|
||||
return circuit
|
||||
|
||||
@property
|
||||
def data(self) -> QuantumCircuitData:
|
||||
"""Return the circuit data (instructions and context).
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Added the method :meth:`.QuantumCircuit.from_instructions`
|
||||
for constructing a quantum circuit from an iterable of instructions.
|
|
@ -13,21 +13,23 @@
|
|||
|
||||
"""Test Qiskit's QuantumCircuit class."""
|
||||
|
||||
from ddt import ddt, data
|
||||
import numpy as np
|
||||
from qiskit import BasicAer
|
||||
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
|
||||
from qiskit import execute
|
||||
from qiskit.circuit import Gate, Instruction, Parameter, Measure
|
||||
from ddt import data, ddt
|
||||
|
||||
from qiskit import BasicAer, ClassicalRegister, QuantumCircuit, QuantumRegister, execute
|
||||
from qiskit.circuit import Gate, Instruction, Measure, Parameter
|
||||
from qiskit.circuit.bit import Bit
|
||||
from qiskit.circuit.classicalregister import Clbit
|
||||
from qiskit.circuit.exceptions import CircuitError
|
||||
from qiskit.circuit.quantumcircuit import BitLocations
|
||||
from qiskit.circuit.quantumregister import AncillaQubit, AncillaRegister, Qubit
|
||||
from qiskit.test import QiskitTestCase
|
||||
from qiskit.circuit.controlflow import IfElseOp
|
||||
from qiskit.circuit.library import CXGate, HGate
|
||||
from qiskit.circuit.library.standard_gates import SGate
|
||||
from qiskit.circuit.quantumcircuit import BitLocations
|
||||
from qiskit.circuit.quantumcircuitdata import CircuitInstruction
|
||||
from qiskit.circuit.quantumregister import AncillaQubit, AncillaRegister, Qubit
|
||||
from qiskit.pulse import DriveChannel, Gaussian, Play, Schedule
|
||||
from qiskit.quantum_info import Operator
|
||||
from qiskit.pulse import Schedule, Play, Gaussian, DriveChannel
|
||||
from qiskit.test import QiskitTestCase
|
||||
|
||||
|
||||
@ddt
|
||||
|
@ -1262,6 +1264,71 @@ class TestCircuitOperations(QiskitTestCase):
|
|||
|
||||
self.assertEqual(test, expected)
|
||||
|
||||
def test_from_instructions(self):
|
||||
"""Test from_instructions method."""
|
||||
|
||||
qreg = QuantumRegister(4)
|
||||
creg = ClassicalRegister(3)
|
||||
|
||||
a, b, c, d = qreg
|
||||
x, y, z = creg
|
||||
|
||||
circuit_1 = QuantumCircuit(2)
|
||||
circuit_1.x(0)
|
||||
circuit_2 = QuantumCircuit(2)
|
||||
circuit_2.y(0)
|
||||
|
||||
def instructions():
|
||||
yield CircuitInstruction(HGate(), [a], [])
|
||||
yield CircuitInstruction(CXGate(), [a, b], [])
|
||||
yield CircuitInstruction(Measure(), [a], [x])
|
||||
yield CircuitInstruction(Measure(), [b], [y])
|
||||
yield CircuitInstruction(IfElseOp((z, 1), circuit_1, circuit_2), [c, d], [z])
|
||||
|
||||
def instruction_tuples():
|
||||
yield HGate(), [a], []
|
||||
yield CXGate(), [a, b], []
|
||||
yield CircuitInstruction(Measure(), [a], [x])
|
||||
yield Measure(), [b], [y]
|
||||
yield IfElseOp((z, 1), circuit_1, circuit_2), [c, d], [z]
|
||||
|
||||
def instruction_tuples_partial():
|
||||
yield HGate(), [a]
|
||||
yield CXGate(), [a, b], []
|
||||
yield CircuitInstruction(Measure(), [a], [x])
|
||||
yield Measure(), [b], [y]
|
||||
yield IfElseOp((z, 1), circuit_1, circuit_2), [c, d], [z]
|
||||
|
||||
circuit = QuantumCircuit.from_instructions(instructions())
|
||||
circuit_tuples = QuantumCircuit.from_instructions(instruction_tuples())
|
||||
circuit_tuples_partial = QuantumCircuit.from_instructions(instruction_tuples_partial())
|
||||
|
||||
expected = QuantumCircuit([a, b, c, d], [x, y, z])
|
||||
for instruction in instructions():
|
||||
expected.append(*instruction)
|
||||
|
||||
self.assertEqual(circuit, expected)
|
||||
self.assertEqual(circuit_tuples, expected)
|
||||
self.assertEqual(circuit_tuples_partial, expected)
|
||||
|
||||
def test_from_instructions_metadata(self):
|
||||
"""Test from_instructions method passes metadata."""
|
||||
qreg = QuantumRegister(2)
|
||||
a, b = qreg
|
||||
|
||||
def instructions():
|
||||
yield CircuitInstruction(HGate(), [a], [])
|
||||
yield CircuitInstruction(CXGate(), [a, b], [])
|
||||
|
||||
circuit = QuantumCircuit.from_instructions(instructions(), name="test", global_phase=0.1)
|
||||
|
||||
expected = QuantumCircuit([a, b], global_phase=0.1)
|
||||
for instruction in instructions():
|
||||
expected.append(*instruction)
|
||||
|
||||
self.assertEqual(circuit, expected)
|
||||
self.assertEqual(circuit.name, "test")
|
||||
|
||||
|
||||
class TestCircuitPrivateOperations(QiskitTestCase):
|
||||
"""Direct tests of some of the private methods of QuantumCircuit. These do not represent
|
||||
|
|
Loading…
Reference in New Issue