mirror of https://github.com/Qiskit/qiskit.git
Added classical_predecessors method (#9980)
* Added classical_predecessors method * add accesed method * Added classsical_successor method * Added classical predecessors and successors method * added tol command * successors method * add test classical_successor method * changed DagOutNode * Apply suggestions from code review from @atharva-satpute. Thanks! Co-authored-by: atharva-satpute <55058959+atharva-satpute@users.noreply.github.com> * add assertRaises on test methods * correct typo variable name * change the descrption * change the text on the example * change the format of yaml * new example * new suggestions * fix test * new test example and change the release note * Fixup release note * Fix typo --------- Co-authored-by: Maldoalberto <amaldonador1300@alumno.ipn.mx> Co-authored-by: Maldoalberto <Alberto.Maldonado.Romo@ibm.com> Co-authored-by: Luciano Bello <bel@zurich.ibm.com> Co-authored-by: atharva-satpute <55058959+atharva-satpute@users.noreply.github.com> Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
This commit is contained in:
parent
f9958143eb
commit
2ba298481a
|
@ -1565,6 +1565,15 @@ class DAGCircuit:
|
|||
)
|
||||
)
|
||||
|
||||
def classical_predecessors(self, node):
|
||||
"""Returns iterator of the predecessors of a node that are
|
||||
connected by a classical edge as DAGOpNodes and DAGInNodes."""
|
||||
return iter(
|
||||
self._multi_graph.find_predecessors_by_edge(
|
||||
node._node_id, lambda edge_data: isinstance(edge_data, Clbit)
|
||||
)
|
||||
)
|
||||
|
||||
def ancestors(self, node):
|
||||
"""Returns set of the ancestors of a node as DAGOpNodes and DAGInNodes."""
|
||||
return {self._multi_graph[x] for x in rx.ancestors(self._multi_graph, node._node_id)}
|
||||
|
@ -1589,6 +1598,15 @@ class DAGCircuit:
|
|||
)
|
||||
)
|
||||
|
||||
def classical_successors(self, node):
|
||||
"""Returns iterator of the successors of a node that are
|
||||
connected by a classical edge as DAGOpNodes and DAGInNodes."""
|
||||
return iter(
|
||||
self._multi_graph.find_successors_by_edge(
|
||||
node._node_id, lambda edge_data: isinstance(edge_data, Clbit)
|
||||
)
|
||||
)
|
||||
|
||||
def remove_op_node(self, node):
|
||||
"""Remove an operation node n.
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Added :meth:`.DAGCircuit.classical_predecessors` and
|
||||
:meth:`.DAGCircuit.classical_successors`, an alternative to select the classical
|
||||
wires without having to go to the inner graph object directly of a node in the DAG.
|
||||
The following example illustrates the new functionality::
|
||||
|
||||
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
|
||||
from qiskit.converters import circuit_to_dag
|
||||
from qiskit.circuit.library import RZGate
|
||||
|
||||
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)
|
||||
circ.measure(q[1], c[0])
|
||||
dag = circuit_to_dag(circ)
|
||||
|
||||
rz_node = dag.op_nodes(RZGate)[0]
|
||||
# Contains the "measure" on clbit 0, and the "wire start" nodes for clbits 1 and 2.
|
||||
classical_predecessors = list(dag.classical_predecessors(rz_node))
|
||||
# Contains the "measure" on clbit 0, and the "wire end" nodes for clbits 1 and 2.
|
||||
classical_successors = list(dag.classical_successors(rz_node))
|
|
@ -740,6 +740,73 @@ class TestDagNodeSelection(QiskitTestCase):
|
|||
or (isinstance(predecessor2, DAGInNode) and isinstance(predecessor1.op, Reset))
|
||||
)
|
||||
|
||||
def test_classical_predecessors(self):
|
||||
"""The method dag.classical_predecessors() returns predecessors connected by classical edges"""
|
||||
|
||||
# ┌───┐ ┌───┐
|
||||
# q_0: ┤ H ├──■───────────────────■──┤ H ├
|
||||
# ├───┤┌─┴─┐ ┌─┴─┐├───┤
|
||||
# q_1: ┤ H ├┤ X ├──■─────────■──┤ X ├┤ H ├
|
||||
# └───┘└───┘┌─┴─┐┌───┐┌─┴─┐└───┘└───┘
|
||||
# q_2: ──────────┤ X ├┤ H ├┤ X ├──────────
|
||||
# └───┘└───┘└───┘
|
||||
# c: 5/═══════════════════════════════════
|
||||
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit0], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit1], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit1, self.qubit2], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit2], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit1, self.qubit2], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit0], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit1], [])
|
||||
self.dag.apply_operation_back(Measure(), [self.qubit0, self.clbit0], [])
|
||||
self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [])
|
||||
|
||||
predecessor_measure = self.dag.classical_predecessors(self.dag.named_nodes("measure").pop())
|
||||
|
||||
predecessor1 = next(predecessor_measure)
|
||||
|
||||
with self.assertRaises(StopIteration):
|
||||
next(predecessor_measure)
|
||||
|
||||
self.assertIsInstance(predecessor1, DAGInNode)
|
||||
self.assertIsInstance(predecessor1.wire, Clbit)
|
||||
|
||||
def test_classical_successors(self):
|
||||
"""The method dag.classical_successors() returns successors connected by classical edges"""
|
||||
|
||||
# ┌───┐ ┌───┐
|
||||
# q_0: ┤ H ├──■───────────────────■──┤ H ├
|
||||
# ├───┤┌─┴─┐ ┌─┴─┐├───┤
|
||||
# q_1: ┤ H ├┤ X ├──■─────────■──┤ X ├┤ H ├
|
||||
# └───┘└───┘┌─┴─┐┌───┐┌─┴─┐└───┘└───┘
|
||||
# q_2: ──────────┤ X ├┤ H ├┤ X ├──────────
|
||||
# └───┘└───┘└───┘
|
||||
# c: 5/═══════════════════════════════════
|
||||
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit0], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit1], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit1, self.qubit2], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit2], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit1, self.qubit2], [])
|
||||
self.dag.apply_operation_back(CXGate(), [self.qubit0, self.qubit1], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit0], [])
|
||||
self.dag.apply_operation_back(HGate(), [self.qubit1], [])
|
||||
self.dag.apply_operation_back(Measure(), [self.qubit0, self.clbit0], [])
|
||||
self.dag.apply_operation_back(Measure(), [self.qubit1, self.clbit1], [])
|
||||
|
||||
successors_measure = self.dag.classical_successors(self.dag.named_nodes("measure").pop())
|
||||
|
||||
successors1 = next(successors_measure)
|
||||
with self.assertRaises(StopIteration):
|
||||
next(successors_measure)
|
||||
|
||||
self.assertIsInstance(successors1, DAGOutNode)
|
||||
self.assertIsInstance(successors1.wire, Clbit)
|
||||
|
||||
def test_is_predecessor(self):
|
||||
"""The method dag.is_predecessor(A, B) checks if node B is a predecessor of A"""
|
||||
|
||||
|
|
Loading…
Reference in New Issue