Skip to content

Commit 07ce476

Browse files
adding optional conversion data when converting to DAGDependency_V2
1 parent c0f5995 commit 07ce476

File tree

6 files changed

+103
-27
lines changed

6 files changed

+103
-27
lines changed

qiskit/converters/circuit_conversion_data.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ class CircuitConversionData:
1717
"""Conversion data when switching between different circuit formats."""
1818

1919
def __init__(self):
20-
self._fwd_map = dict()
21-
self._bwd_map = dict()
20+
self._fwd_map = {}
21+
self._bwd_map = {}
2222

2323
def store_mapping(self, from_node, to_node):
2424
"""Stores that ``from_node`` is mapped to ``to_node``."""

qiskit/converters/dag_to_dagdependency.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
# that they have been altered from the originals.
1212

1313
"""Helper function for converting a dag circuit to a dag dependency"""
14-
from .circuit_conversion_data import CircuitConversionData
1514
from qiskit.dagcircuit.dagdependency import DAGDependency
15+
from .circuit_conversion_data import CircuitConversionData
1616

1717

1818
def dag_to_dagdependency_with_data(
@@ -78,7 +78,7 @@ def dag_to_dagdependency(dag, create_preds_and_succs=True):
7878
Return:
7979
DAGDependency: the DAG representing the input circuit as a dag dependency.
8080
"""
81-
dagdependency, conversion_data = dag_to_dagdependency_with_data(
81+
dagdependency, _ = dag_to_dagdependency_with_data(
8282
dag, create_preds_and_succs=create_preds_and_succs
8383
)
8484
return dagdependency

qiskit/converters/dag_to_dagdependency_v2.py

+29-3
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,26 @@
1212

1313
"""Helper function for converting a dag circuit to a dag dependency"""
1414
from qiskit.dagcircuit.dagdependency_v2 import _DAGDependencyV2
15+
from .circuit_conversion_data import CircuitConversionData
1516

1617

17-
def _dag_to_dagdependency_v2(dag):
18+
def _dag_to_dagdependency_v2_with_data(dag, *, create_conversion_data=False):
1819
"""Build a ``_DAGDependencyV2`` object from a ``DAGCircuit``.
1920
2021
Args:
2122
dag (DAGCircuit): the input dag.
23+
create_conversion_data (bool): whether to construct mappings
24+
between nodes in the input and the output circuits.
2225
2326
Return:
2427
_DAGDependencyV2: the DAG representing the input circuit as a dag dependency.
28+
CircuitConversionData: data storing mappings between nodes
29+
in the input and the output circuits when ``create_conversion_data``
30+
is ``True``, and ``None`` otherwise.
31+
2532
"""
33+
conversion_data = CircuitConversionData() if create_conversion_data else None
34+
2635
dagdependency = _DAGDependencyV2()
2736
dagdependency.name = dag.name
2837
dagdependency.metadata = dag.metadata
@@ -38,7 +47,24 @@ def _dag_to_dagdependency_v2(dag):
3847
for register in dag.cregs.values():
3948
dagdependency.add_creg(register)
4049

41-
for node in dag.topological_op_nodes():
42-
dagdependency.apply_operation_back(node.op.copy(), node.qargs, node.cargs)
50+
for in_node in dag.topological_op_nodes():
51+
out_node = dagdependency.apply_operation_back(
52+
in_node.op.copy(), in_node.qargs, in_node.cargs
53+
)
54+
if create_conversion_data:
55+
conversion_data.store_mapping(in_node, out_node)
56+
57+
return dagdependency, conversion_data
58+
59+
60+
def _dag_to_dagdependency_v2(dag):
61+
"""Build a ``_DAGDependencyV2`` object from a ``DAGCircuit``.
62+
63+
Args:
64+
dag (DAGCircuit): the input dag.
4365
66+
Return:
67+
_DAGDependencyV2: the DAG representing the input circuit as a dag dependency.
68+
"""
69+
dagdependency, _ = _dag_to_dagdependency_v2_with_data(dag)
4470
return dagdependency

qiskit/dagcircuit/dagdependency_v2.py

+4
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@ def apply_operation_back(self, operation, qargs=(), cargs=()):
339339
operation (qiskit.circuit.Operation): operation as a quantum gate
340340
qargs (list[~qiskit.circuit.Qubit]): list of qubits on which the operation acts
341341
cargs (list[Clbit]): list of classical wires to attach to
342+
343+
Returns:
344+
DAGOpNode: the newly appended node
342345
"""
343346
new_node = DAGOpNode(
344347
op=operation,
@@ -349,6 +352,7 @@ def apply_operation_back(self, operation, qargs=(), cargs=()):
349352
new_node._node_id = self._multi_graph.add_node(new_node)
350353
self._update_edges()
351354
self._increment_op(new_node.op)
355+
return new_node
352356

353357
def _update_edges(self):
354358
"""

test/python/converters/test_dag_to_dagdependency.py

+17-19
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,8 @@ def test_metadata(self):
8484
dag_out = dagdependency_to_dag(dag_dependency)
8585
self.assertEqual(dag_out.metadata, meta_dict)
8686

87-
def test_conversion_data(self):
88-
"""Test that conversion data is created and is correct when
89-
``create_conversion_data`` is ``True``.
90-
"""
87+
def test_conversion_data_not_created_by_default(self):
88+
"""Test that conversion data is not created by default."""
9189
qr = QuantumRegister(3)
9290
cr = ClassicalRegister(3)
9391
circuit_in = QuantumCircuit(qr, cr)
@@ -101,20 +99,13 @@ def test_conversion_data(self):
10199
circuit_in.measure(qr[2], cr[2])
102100
dag_in = circuit_to_dag(circuit_in)
103101

104-
dag_dependency, conversion_data = dag_to_dagdependency_with_data(
105-
dag_in, create_conversion_data=True
106-
)
107-
self.assertIsNotNone(conversion_data)
108-
109-
# Check that mapping an op_node first forward and then backward gives back the same node.
110-
for in_node in dag_in.op_nodes():
111-
out_node = conversion_data.forward_map(in_node)
112-
self.assertIsNotNone(out_node)
113-
in_out_node = conversion_data.backward_map(out_node)
114-
self.assertEqual(in_node, in_out_node)
102+
_, conversion_data = dag_to_dagdependency_with_data(dag_in)
103+
self.assertIsNone(conversion_data)
115104

116-
def test_conversion_data_not_created_by_default(self):
117-
"""Test that conversion data is not created by default."""
105+
def test_conversion_data(self):
106+
"""Test that conversion data is created and is correct when
107+
``create_conversion_data`` is ``True``.
108+
"""
118109
qr = QuantumRegister(3)
119110
cr = ClassicalRegister(3)
120111
circuit_in = QuantumCircuit(qr, cr)
@@ -128,8 +119,15 @@ def test_conversion_data_not_created_by_default(self):
128119
circuit_in.measure(qr[2], cr[2])
129120
dag_in = circuit_to_dag(circuit_in)
130121

131-
dag_dependency, conversion_data = dag_to_dagdependency_with_data(dag_in)
132-
self.assertIsNone(conversion_data)
122+
_, conversion_data = dag_to_dagdependency_with_data(dag_in, create_conversion_data=True)
123+
self.assertIsNotNone(conversion_data)
124+
125+
# Check that mapping an op_node first forward and then backward gives back the same node.
126+
for in_node in dag_in.op_nodes():
127+
out_node = conversion_data.forward_map(in_node)
128+
self.assertIsNotNone(out_node)
129+
in_out_node = conversion_data.backward_map(out_node)
130+
self.assertEqual(in_node, in_out_node)
133131

134132

135133
if __name__ == "__main__":

test/python/converters/test_dag_to_dagdependency_v2.py

+49-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
import unittest
1717

1818
from qiskit.converters.circuit_to_dag import circuit_to_dag
19-
from qiskit.converters.dag_to_dagdependency_v2 import _dag_to_dagdependency_v2
19+
from qiskit.converters.dag_to_dagdependency_v2 import (
20+
_dag_to_dagdependency_v2,
21+
_dag_to_dagdependency_v2_with_data,
22+
)
2023
from qiskit.converters.dagdependency_to_dag import dagdependency_to_dag
2124
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
2225
from test import QiskitTestCase # pylint: disable=wrong-import-order
@@ -60,6 +63,51 @@ def test_metadata(self):
6063
dag_out = dagdependency_to_dag(dag_dependency)
6164
self.assertEqual(dag_out.metadata, meta_dict)
6265

66+
def test_conversion_data_not_created_by_default(self):
67+
"""Test that conversion data is not created by default."""
68+
qr = QuantumRegister(3)
69+
cr = ClassicalRegister(3)
70+
circuit_in = QuantumCircuit(qr, cr)
71+
circuit_in.h(qr[0])
72+
circuit_in.h(qr[1])
73+
circuit_in.measure(qr[0], cr[0])
74+
circuit_in.measure(qr[1], cr[1])
75+
circuit_in.x(qr[0]).c_if(cr, 0x3)
76+
circuit_in.measure(qr[0], cr[0])
77+
circuit_in.measure(qr[1], cr[1])
78+
circuit_in.measure(qr[2], cr[2])
79+
dag_in = circuit_to_dag(circuit_in)
80+
81+
_, conversion_data = _dag_to_dagdependency_v2_with_data(dag_in)
82+
self.assertIsNone(conversion_data)
83+
84+
def test_conversion_data(self):
85+
"""Test that conversion data is created and is correct when
86+
``create_conversion_data`` is ``True``.
87+
"""
88+
qr = QuantumRegister(3)
89+
cr = ClassicalRegister(3)
90+
circuit_in = QuantumCircuit(qr, cr)
91+
circuit_in.h(qr[0])
92+
circuit_in.h(qr[1])
93+
circuit_in.measure(qr[0], cr[0])
94+
circuit_in.measure(qr[1], cr[1])
95+
circuit_in.x(qr[0]).c_if(cr, 0x3)
96+
circuit_in.measure(qr[0], cr[0])
97+
circuit_in.measure(qr[1], cr[1])
98+
circuit_in.measure(qr[2], cr[2])
99+
dag_in = circuit_to_dag(circuit_in)
100+
101+
_, conversion_data = _dag_to_dagdependency_v2_with_data(dag_in, create_conversion_data=True)
102+
self.assertIsNotNone(conversion_data)
103+
104+
# Check that mapping an op_node first forward and then backward gives back the same node.
105+
for in_node in dag_in.op_nodes():
106+
out_node = conversion_data.forward_map(in_node)
107+
self.assertIsNotNone(out_node)
108+
in_out_node = conversion_data.backward_map(out_node)
109+
self.assertEqual(in_node, in_out_node)
110+
63111

64112
if __name__ == "__main__":
65113
unittest.main(verbosity=2)

0 commit comments

Comments
 (0)