Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use retworkx #3810

Closed
wants to merge 44 commits into from
Closed
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7a9c4ca
Start conversion of networkx to retworkx
mtreinish Jan 28, 2020
fde9f74
Implement to_networkx() method
mtreinish Jan 29, 2020
c4d3fb3
Use lexicographical_topological_sort()
mtreinish Jan 31, 2020
326e854
More fixes
mtreinish Jan 31, 2020
9fec1c9
Add back deepycopy to __eq__
mtreinish Feb 3, 2020
19d2a21
Fix indexing on node_on_wire test
mtreinish Feb 3, 2020
6b93c85
Return iterator for successors and predecessors
mtreinish Feb 6, 2020
463f311
Update longest_path method
mtreinish Feb 8, 2020
9aaa48b
Update bfs_successors return type
mtreinish Feb 9, 2020
eab76f6
Use node_id for apply_operation_back_conditional_tests
mtreinish Feb 9, 2020
6fb58dc
Fix layers methods
mtreinish Feb 9, 2020
ab94ea1
De-duplicate in retworkx not dagcircuit
mtreinish Feb 10, 2020
2f501c5
Fix missing node id from has_edge call
mtreinish Feb 10, 2020
20004e8
The networkx node indices were one-indexed. retworkx is zero-indexed.…
lcapelluto Feb 10, 2020
cc98261
Merge pull request #5 from lcapelluto/zero-index-the-hardcoded-node-i…
mtreinish Feb 10, 2020
3caab84
Bump minimum retworkx version to working version
mtreinish Feb 10, 2020
0f6004a
Merge branch 'master' into use-retworkx
mtreinish Feb 10, 2020
a7e16fc
Fix lint
mtreinish Feb 11, 2020
94cf754
Fix lint again
mtreinish Feb 11, 2020
9b6e105
Merge branch 'master' into use-retworkx
mtreinish Feb 11, 2020
d6a4a4e
Merge branch 'master' into use-retworkx
mtreinish Feb 14, 2020
c966f02
Rename variable in _add_wire()
mtreinish Feb 14, 2020
df57161
Fix multigraph bug in quantum_* dagcircuit methods
mtreinish Feb 14, 2020
82c27cd
Update deepcopy comment in __eq__
mtreinish Feb 14, 2020
c925287
Fix lint
mtreinish Feb 14, 2020
4620c4d
Fix lint again
mtreinish Feb 14, 2020
709bf88
Merge branch 'master' into use-retworkx
mtreinish Feb 14, 2020
c7777bc
Merge branch 'master' into use-retworkx
mtreinish Feb 18, 2020
3fcb04a
Merge branch 'master' into use-retworkx
mtreinish Feb 19, 2020
438875c
Use retwork for multigraph_layers
mtreinish Feb 20, 2020
1e8cdc7
Merge branch 'master' into use-retworkx
mtreinish Feb 21, 2020
d1fcc89
Merge branch 'master' into use-retworkx
mtreinish Feb 23, 2020
fa02f00
Merge branch 'master' into use-retworkx
mtreinish Feb 24, 2020
5f46cc5
Switch edges to use out_edges instead of in_edges
mtreinish Feb 24, 2020
af19051
Remove unecessary iter() from tests
mtreinish Feb 24, 2020
dc7ba58
Merge branch 'master' into use-retworkx
mtreinish Feb 24, 2020
c67dc50
Remove unecessary list() casts
mtreinish Feb 24, 2020
58b1ad5
Add release note
mtreinish Feb 24, 2020
a685bfe
Merge branch 'master' into use-retworkx
mtreinish Feb 25, 2020
89ee38e
Merge branch 'master' into use-retworkx
mtreinish Feb 25, 2020
2761f1e
Merge branch 'master' into use-retworkx
mtreinish Mar 3, 2020
f7b2ba5
Merge branch 'master' into use-retworkx
mtreinish Mar 3, 2020
195f2a9
Merge branch 'master' into use-retworkx
mtreinish Mar 5, 2020
bb57d84
Merge branch 'master' into use-retworkx
mtreinish Mar 6, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ ignore-mixin-members=yes
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=matplotlib.cm,numpy.random
ignored-modules=matplotlib.cm,numpy.random,retworkx

# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
Expand Down
267 changes: 133 additions & 134 deletions qiskit/dagcircuit/dagcircuit.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion qiskit/transpiler/passes/utils/merge_adjacent_barriers.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def _collect_potential_merges(dag, barriers):
for next_barrier in barriers[1:]:

# Ensure barriers are adjacent before checking if they are mergeable.
if dag._multi_graph.has_edge(end_of_barrier, next_barrier):
if dag._multi_graph.has_edge(end_of_barrier._node_id, next_barrier._node_id):

# Remove all barriers that have already been included in this new barrier from the
# set of ancestors/descendants as they will be removed from the new DAG when it is
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ marshmallow>=3,<4
marshmallow_polyfield>=5.7,<6
networkx>=2.2;python_version>'3.5'
networkx>=2.2,<2.4;python_version=='3.5'
retworkx>=0.3.0
numpy>=1.13
ply>=3.10
psutil>=5
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"networkx>=2.2;python_version>'3.5'",
# Networkx 2.4 is the final version with python 3.5 support.
"networkx>=2.2,<2.4;python_version=='3.5'",
"retworkx>=0.3.0",
"numpy>=1.13",
"ply>=3.10",
"psutil>=5",
Expand Down
78 changes: 39 additions & 39 deletions test/python/test_dagcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from ddt import ddt, data

import networkx as nx
import retworkx as nx

from qiskit.dagcircuit import DAGCircuit
from qiskit.circuit import QuantumRegister
Expand Down Expand Up @@ -72,8 +72,8 @@ def raise_if_dagcircuit_invalid(dag):

# Every edge should be labled with a known wire.
edges_outside_wires = [edge_data['wire']
for source, dest, edge_data
in multi_graph.edges(data=True)
for edge_data
in multi_graph.edges()
if edge_data['wire'] not in dag.wires]
if edges_outside_wires:
raise DAGCircuitError('multi_graph contains one or more edges ({}) '
Expand All @@ -94,23 +94,22 @@ def raise_if_dagcircuit_invalid(dag):
for wire in dag.wires:
cur_node = dag.input_map[wire]
out_node = dag.output_map[wire]

while cur_node != out_node:
out_edges = multi_graph.out_edges(cur_node, data=True)
out_edges = multi_graph.out_edges(cur_node._node_id)
edges_to_follow = [(src, dest, data) for (src, dest, data) in out_edges
if data['wire'] == wire]

assert len(edges_to_follow) == 1
cur_node = edges_to_follow[0][1]
cur_node = dag._id_to_node[edges_to_follow[0][1]]

# Wires can only terminate at input/output nodes.
for op_node in dag.op_nodes():
assert multi_graph.in_degree(op_node) == multi_graph.out_degree(op_node)
assert multi_graph.in_degree(op_node._node_id) == multi_graph.out_degree(op_node._node_id)

# Node input/output edges should match node qarg/carg/condition.
for node in dag.op_nodes():
in_edges = multi_graph.in_edges(node, data=True)
out_edges = multi_graph.out_edges(node, data=True)
in_edges = multi_graph.in_edges(node._node_id)
out_edges = multi_graph.out_edges(node._node_id)

in_wires = {data['wire'] for src, dest, data in in_edges}
out_wires = {data['wire'] for src, dest, data in out_edges}
Expand Down Expand Up @@ -219,24 +218,24 @@ def test_apply_operation_back_conditional(self):
self.assertEqual(h_node.condition, h_gate.condition)

self.assertEqual(
sorted(self.dag._multi_graph.in_edges(h_node, data=True)),
sorted(self.dag._multi_graph.in_edges(h_node._node_id)),
sorted([
(self.dag.input_map[self.qubit2], h_node,
(self.dag.input_map[self.qubit2]._node_id, h_node._node_id,
{'wire': self.qubit2, 'name': 'qr[2]'}),
(self.dag.input_map[self.clbit0], h_node,
(self.dag.input_map[self.clbit0]._node_id, h_node._node_id,
{'wire': self.clbit0, 'name': 'cr[0]'}),
(self.dag.input_map[self.clbit1], h_node,
(self.dag.input_map[self.clbit1]._node_id, h_node._node_id,
{'wire': self.clbit1, 'name': 'cr[1]'}),
]))

self.assertEqual(
sorted(self.dag._multi_graph.out_edges(h_node, data=True)),
sorted(self.dag._multi_graph.out_edges(h_node._node_id)),
sorted([
(h_node, self.dag.output_map[self.qubit2],
(h_node._node_id, self.dag.output_map[self.qubit2]._node_id,
{'wire': self.qubit2, 'name': 'qr[2]'}),
(h_node, self.dag.output_map[self.clbit0],
(h_node._node_id, self.dag.output_map[self.clbit0]._node_id,
{'wire': self.clbit0, 'name': 'cr[0]'}),
(h_node, self.dag.output_map[self.clbit1],
(h_node._node_id, self.dag.output_map[self.clbit1]._node_id,
{'wire': self.clbit1, 'name': 'cr[1]'}),
]))

Expand All @@ -261,24 +260,24 @@ def test_apply_operation_back_conditional_measure(self):
self.assertEqual(meas_node.condition, meas_gate.condition)

self.assertEqual(
sorted(self.dag._multi_graph.in_edges(meas_node, data=True)),
sorted(self.dag._multi_graph.in_edges(meas_node._node_id)),
sorted([
(self.dag.input_map[self.qubit0], meas_node,
(self.dag.input_map[self.qubit0]._node_id, meas_node._node_id,
{'wire': self.qubit0, 'name': 'qr[0]'}),
(self.dag.input_map[self.clbit0], meas_node,
(self.dag.input_map[self.clbit0]._node_id, meas_node._node_id,
{'wire': self.clbit0, 'name': 'cr[0]'}),
(self.dag.input_map[new_creg[0]], meas_node,
(self.dag.input_map[new_creg[0]]._node_id, meas_node._node_id,
{'wire': Clbit(new_creg, 0), 'name': 'cr2[0]'}),
]))

self.assertEqual(
sorted(self.dag._multi_graph.out_edges(meas_node, data=True)),
sorted(self.dag._multi_graph.out_edges(meas_node._node_id)),
sorted([
(meas_node, self.dag.output_map[self.qubit0],
(meas_node._node_id, self.dag.output_map[self.qubit0]._node_id,
{'wire': self.qubit0, 'name': 'qr[0]'}),
(meas_node, self.dag.output_map[self.clbit0],
(meas_node._node_id, self.dag.output_map[self.clbit0]._node_id,
{'wire': self.clbit0, 'name': 'cr[0]'}),
(meas_node, self.dag.output_map[new_creg[0]],
(meas_node._node_id, self.dag.output_map[new_creg[0]]._node_id,
{'wire': Clbit(new_creg, 0), 'name': 'cr2[0]'}),
]))

Expand All @@ -300,24 +299,24 @@ def test_apply_operation_back_conditional_measure_to_self(self):
self.assertEqual(meas_node.condition, meas_gate.condition)

self.assertEqual(
sorted(self.dag._multi_graph.in_edges(meas_node, data=True)),
sorted(self.dag._multi_graph.in_edges(meas_node._node_id)),
sorted([
(self.dag.input_map[self.qubit1], meas_node,
(self.dag.input_map[self.qubit1]._node_id, meas_node._node_id,
{'wire': self.qubit1, 'name': 'qr[1]'}),
(self.dag.input_map[self.clbit0], meas_node,
(self.dag.input_map[self.clbit0]._node_id, meas_node._node_id,
{'wire': self.clbit0, 'name': 'cr[0]'}),
(self.dag.input_map[self.clbit1], meas_node,
(self.dag.input_map[self.clbit1]._node_id, meas_node._node_id,
{'wire': self.clbit1, 'name': 'cr[1]'}),
]))

self.assertEqual(
sorted(self.dag._multi_graph.out_edges(meas_node, data=True)),
sorted(self.dag._multi_graph.out_edges(meas_node._node_id)),
sorted([
(meas_node, self.dag.output_map[self.qubit1],
(meas_node._node_id, self.dag.output_map[self.qubit1]._node_id,
{'wire': self.qubit1, 'name': 'qr[1]'}),
(meas_node, self.dag.output_map[self.clbit0],
(meas_node._node_id, self.dag.output_map[self.clbit0]._node_id,
{'wire': self.clbit0, 'name': 'cr[0]'}),
(meas_node, self.dag.output_map[self.clbit1],
(meas_node._node_id, self.dag.output_map[self.clbit1]._node_id,
{'wire': self.clbit1, 'name': 'cr[1]'}),
]))

Expand Down Expand Up @@ -476,7 +475,8 @@ def test_topological_nodes(self):
('cr[0]', []),
('cr[1]', []),
('cr[1]', [])]
self.assertEqual(expected, [(i.name, i.qargs) for i in named_nodes])
result = [(i.name, i.qargs) for i in named_nodes]
self.assertEqual(expected, result)

def test_topological_op_nodes(self):
"""The topological_op_nodes() method"""
Expand All @@ -501,12 +501,12 @@ def test_dag_nodes_on_wire(self):
self.dag.apply_operation_back(HGate(), [self.qubit0], [])

qbit = self.dag.qubits()[0]
self.assertEqual([1, 11, 12, 2], [i._node_id for i in self.dag.nodes_on_wire(qbit)])
self.assertEqual([11, 12],
self.assertEqual([0, 10, 11, 1], [i._node_id for i in self.dag.nodes_on_wire(qbit)])
self.assertEqual([10, 11],
[i._node_id for i in self.dag.nodes_on_wire(qbit, only_ops=True)])

cbit = self.dag.clbits()[0]
self.assertEqual([7, 8], [i._node_id for i in self.dag.nodes_on_wire(cbit)])
self.assertEqual([6, 7], [i._node_id for i in self.dag.nodes_on_wire(cbit)])
self.assertEqual([], [i._node_id for i in self.dag.nodes_on_wire(cbit, only_ops=True)])

with self.assertRaises(DAGCircuitError):
Expand Down Expand Up @@ -565,7 +565,7 @@ def test_remove_non_op_node(self):
"""Try to remove a non-op node with remove_op_node method."""
self.dag.apply_operation_back(HGate(), [self.qubit0])

in_node = next(self.dag.topological_nodes())
in_node = next(iter(self.dag.topological_nodes()))
mtreinish marked this conversation as resolved.
Show resolved Hide resolved
self.assertRaises(DAGCircuitError, self.dag.remove_op_node, in_node)

def test_dag_collect_runs(self):
Expand Down Expand Up @@ -671,7 +671,7 @@ def test_layers_maintains_order(self):
qr = QuantumRegister(1, 'q0')

# the order the nodes should be in
truth = [('in', 'q0[0]', 1), ('op', 'x', 3), ('op', 'id', 4), ('out', 'q0[0]', 2)]
truth = [('in', 'q0[0]', 0), ('op', 'x', 2), ('op', 'id', 3), ('out', 'q0[0]', 1)]

# this only occurred sometimes so has to be run more than once
# (10 times seemed to always be enough for this bug to show at least once)
Expand Down
60 changes: 30 additions & 30 deletions test/python/transpiler/test_commutation_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,18 @@ def test_all_gates(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1],
expected = {'qr[0]': [[0],
[4],
[5],
[6],
[7],
[8, 9, 10, 11],
[7, 8, 9, 10],
[11],
[12],
[13],
[14],
[15],
[16],
[2]],
'qr[1]': [[3], [14], [15], [16], [4]]}
[1]],
'qr[1]': [[2], [13], [14], [15], [3]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_non_commutative_circuit(self):
Expand All @@ -116,7 +116,7 @@ def test_non_commutative_circuit(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [7], [2]], 'qr[1]': [[3], [8], [4]], 'qr[2]': [[5], [9], [6]]}
expected = {'qr[0]': [[0], [6], [1]], 'qr[1]': [[2], [7], [3]], 'qr[2]': [[4], [8], [5]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_non_commutative_circuit_2(self):
Expand All @@ -137,9 +137,9 @@ def test_non_commutative_circuit_2(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [7], [2]],
'qr[1]': [[3], [7], [9], [4]],
'qr[2]': [[5], [8], [9], [6]]}
expected = {'qr[0]': [[0], [6], [1]],
'qr[1]': [[2], [6], [8], [3]],
'qr[2]': [[4], [7], [8], [5]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_commutative_circuit(self):
Expand All @@ -161,9 +161,9 @@ def test_commutative_circuit(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [7], [2]],
'qr[1]': [[3], [7, 9], [4]],
'qr[2]': [[5], [8], [9], [6]]}
expected = {'qr[0]': [[0], [6], [1]],
'qr[1]': [[2], [6, 8], [3]],
'qr[2]': [[4], [7], [8], [5]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_commutative_circuit_2(self):
Expand All @@ -187,9 +187,9 @@ def test_commutative_circuit_2(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [7, 8], [2]],
'qr[1]': [[3], [7, 10], [4]],
'qr[2]': [[5], [9], [10], [6]]}
expected = {'qr[0]': [[0], [6, 7], [1]],
'qr[1]': [[2], [6, 9], [3]],
'qr[2]': [[4], [8], [9], [5]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_commutative_circuit_3(self):
Expand All @@ -215,9 +215,9 @@ def test_commutative_circuit_3(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [7, 9, 11, 13], [2]],
'qr[1]': [[3], [7, 10, 11], [14], [4]],
'qr[2]': [[5], [8], [10], [12, 14], [6]]}
expected = {'qr[0]': [[0], [6, 8, 10, 12], [1]],
'qr[1]': [[2], [6, 9, 10], [13], [3]],
'qr[2]': [[4], [7], [9], [11, 13], [5]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_jordan_wigner_type_circuit(self):
Expand Down Expand Up @@ -253,12 +253,12 @@ def test_jordan_wigner_type_circuit(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [13, 23], [2]],
'qr[1]': [[3], [13], [14, 22], [23], [4]],
'qr[2]': [[5], [14], [15, 21], [22], [6]],
'qr[3]': [[7], [15], [16, 20], [21], [8]],
'qr[4]': [[9], [16], [17, 19], [20], [10]],
'qr[5]': [[11], [17], [18], [19], [12]]}
expected = {'qr[0]': [[0], [12, 22], [1]],
'qr[1]': [[2], [12], [13, 21], [22], [3]],
'qr[2]': [[4], [13], [14, 20], [21], [5]],
'qr[3]': [[6], [14], [15, 19], [20], [7]],
'qr[4]': [[8], [15], [16, 18], [19], [9]],
'qr[5]': [[10], [16], [17], [18], [11]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)

def test_all_commute_circuit(self):
Expand All @@ -279,11 +279,11 @@ def test_all_commute_circuit(self):

self.pass_.run(dag)

expected = {'qr[0]': [[1], [11, 15, 17], [2]],
'qr[1]': [[3], [11, 12, 17, 18], [4]],
'qr[2]': [[5], [12, 14, 18, 20], [6]],
'qr[3]': [[7], [13, 14, 19, 20], [8]],
'qr[4]': [[9], [13, 16, 19], [10]]}
expected = {'qr[0]': [[0], [10, 14, 16], [1]],
'qr[1]': [[2], [10, 11, 16, 17], [3]],
'qr[2]': [[4], [11, 13, 17, 19], [5]],
'qr[3]': [[6], [12, 13, 18, 19], [7]],
'qr[4]': [[8], [12, 15, 18], [9]]}
self.assertCommutationSet(self.pset["commutation_set"], expected)


Expand Down
2 changes: 1 addition & 1 deletion test/python/transpiler/test_pass_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ def test_fenced_dag(self):
self.passmanager.append(PassI_Bad_AP())
self.assertSchedulerRaises(circ, self.passmanager,
['run analysis pass PassI_Bad_AP',
'cx_runs: {(5, 6, 7, 8)}'],
'cx_runs: {(4, 5, 6, 7)}'],
TranspilerError)

def test_analysis_pass_is_idempotent(self):
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ setenv =
LANGUAGE=en_US
LC_ALL=en_US.utf-8
ARGS="-V"
RUST_BACKTRACE=full
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/requirements-dev.txt
commands =
Expand Down