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

Replace NetworkX by RetworkX #1791

Merged
merged 32 commits into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
264cb7a
Add retworkx as pl-requirements
maliasadi Oct 15, 2021
305be9c
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
maliasadi Oct 18, 2021
5c33c3e
Add RX support to qaoa/cycle.py
maliasadi Oct 18, 2021
17d0edb
Update RX in qaoa/cycle.py
maliasadi Oct 19, 2021
91b1ed6
Add RX support to qaoa/cost.py
maliasadi Oct 19, 2021
ff8a2d6
Update RX in qaoa/cost.py
maliasadi Oct 19, 2021
310b860
Add RX support to qaoa/mixers.py
maliasadi Oct 19, 2021
298f24f
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
maliasadi Oct 19, 2021
5c50590
Update RX support in qaoa
maliasadi Oct 19, 2021
afabefd
Add RX support to CircuitGraph and update QAOA tests
maliasadi Oct 21, 2021
8529194
Update CircuitGraph
maliasadi Oct 21, 2021
5e03a59
Update RX in circuit_graph
maliasadi Oct 21, 2021
d0cf841
Update CircuitGraph tests
maliasadi Oct 22, 2021
8c70589
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
maliasadi Oct 22, 2021
3a2fe89
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
maliasadi Oct 22, 2021
4d5c10b
Fix merge master conflicts
maliasadi Dec 16, 2021
cb01927
Update RX @ qaoa
maliasadi Dec 17, 2021
c15fbc6
Update formatting
maliasadi Dec 17, 2021
dbc6011
Update circuit_graph
maliasadi Dec 17, 2021
c84d711
Merge branch 'master' of github.com:PennyLaneAI/pennylane into add_re…
maliasadi Dec 17, 2021
85c4680
Add RX support to CircuitGraph
maliasadi Dec 17, 2021
a05f8e9
Merge branch 'master' into add_retworkx_support
maliasadi Dec 17, 2021
e6736f8
Update formatting
maliasadi Dec 17, 2021
4644238
Merge branch 'master' into add_retworkx_support
maliasadi Dec 19, 2021
9a8dcbf
Merge branch 'master' of github.com:PennyLaneAI/pennylane into add_re…
maliasadi Dec 19, 2021
565f449
Merge branch 'add_retworkx_support' of github.com:PennyLaneAI/pennyla…
maliasadi Dec 19, 2021
ccac319
Apply codecov suggestions
maliasadi Dec 20, 2021
7279a2a
Add lollipop_graph_rx
maliasadi Dec 20, 2021
ea31100
Apply code review suggestions
maliasadi Dec 20, 2021
9203c37
Update doc/releases/changelog-dev.md
maliasadi Dec 21, 2021
048cf79
Add more comments
maliasadi Dec 21, 2021
af47884
Update has_path
maliasadi Dec 21, 2021
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
10 changes: 9 additions & 1 deletion doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@
* Interferometer is now a class with `shape` method.
[(#1946)](https://github.com/PennyLaneAI/pennylane/pull/1946)

* The `CircuitGraph`, used to represent circuits via directed acyclic graphs, now
uses RetworkX for its internal representation. This results in significant speedup
for algorithms that rely on a directed acyclic graph representation.
[(#1791)](https://github.com/PennyLaneAI/pennylane/pull/1791)

* The QAOA module now accepts both NetworkX and RetworkX graphs as function inputs.
[(#1791)](https://github.com/PennyLaneAI/pennylane/pull/1791)

<h3>Breaking changes</h3>

<h3>Bug fixes</h3>
Expand Down Expand Up @@ -151,4 +159,4 @@

This release contains contributions from (in alphabetical order):

Juan Miguel Arrazola, Esther Cruz, Olivia Di Matteo, Diego Guala, Ankit Khandelwal, Antal Száva, David Wierichs, Shaoming Zhang
Juan Miguel Arrazola, Ali Asadi, Esther Cruz, Olivia Di Matteo, Diego Guala, Ankit Khandelwal, Antal Száva, David Wierichs, Shaoming Zhang
72 changes: 53 additions & 19 deletions pennylane/circuit_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# pylint: disable=too-many-branches,too-many-arguments,too-many-instance-attributes
from collections import Counter, OrderedDict, namedtuple

import networkx as nx
import retworkx as rx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


import pennylane as qml
import numpy as np
Expand Down Expand Up @@ -167,22 +167,31 @@ def __init__(self, ops, obs, wires, par_info=None, trainable_params=None):

# TODO: State preparations demolish the incoming state entirely, and therefore should have no incoming edges.

self._graph = nx.DiGraph() #: nx.DiGraph: DAG representation of the quantum circuit
self._graph = rx.PyDiGraph(
multigraph=False
) #: rx.PyDiGraph: DAG representation of the quantum circuit

# Iterate over each (populated) wire in the grid
for wire in self._grid.values():
# Add the first operator on the wire to the graph
# This operator does not depend on any others
self._graph.add_node(wire[0])

# Check if wire[0] in self._grid.values()
# is already added to the graph
if wire[0] not in self._graph.nodes():
self._graph.add_node(wire[0])
maliasadi marked this conversation as resolved.
Show resolved Hide resolved

for i in range(1, len(wire)):
# For subsequent operators on the wire:
if wire[i] not in self._graph:
if wire[i] not in self._graph.nodes():
# Add them to the graph if they are not already
# in the graph (multi-qubit operators might already have been placed)
self._graph.add_node(wire[i])

# Create an edge between this and the previous operator
self._graph.add_edge(wire[i - 1], wire[i])
self._graph.add_edge(
self._graph.nodes().index(wire[i - 1]), self._graph.nodes().index(wire[i]), ""
maliasadi marked this conversation as resolved.
Show resolved Hide resolved
)

# For computing depth; want only a graph with the operations, not
# including the observables
Expand Down Expand Up @@ -264,7 +273,7 @@ def observables_in_order(self):
Returns:
list[Observable]: observables
"""
nodes = [node for node in self._graph.nodes if _is_observable(node)]
nodes = [node for node in self._graph.nodes() if _is_observable(node)]
return sorted(nodes, key=_by_idx)

@property
Expand All @@ -284,7 +293,7 @@ def operations_in_order(self):
Returns:
list[Operation]: operations
"""
nodes = [node for node in self._graph.nodes if not _is_observable(node)]
nodes = [node for node in self._graph.nodes() if not _is_observable(node)]
return sorted(nodes, key=_by_idx)

@property
Expand All @@ -300,7 +309,7 @@ def graph(self):
and directed edges pointing from nodes to their immediate dependents/successors.

Returns:
networkx.DiGraph: the directed acyclic graph representing the quantum circuit
retworkx.PyDiGraph: the directed acyclic graph representing the quantum circuit
"""
return self._graph

Expand All @@ -324,7 +333,13 @@ def ancestors(self, ops):
Returns:
set[Operator]: ancestors of the given operators
"""
return set().union(*(nx.dag.ancestors(self._graph, o) for o in ops)) - set(ops)
anc = set(
self._graph.get_node_data(n)
for n in set().union(
*(rx.ancestors(self._graph, self._graph.nodes().index(o)) for o in ops)
)
maliasadi marked this conversation as resolved.
Show resolved Hide resolved
)
return anc - set(ops)

def descendants(self, ops):
"""Descendants of a given set of operators.
Expand All @@ -335,7 +350,13 @@ def descendants(self, ops):
Returns:
set[Operator]: descendants of the given operators
"""
return set().union(*(nx.dag.descendants(self._graph, o) for o in ops)) - set(ops)
des = set(
self._graph.get_node_data(n)
for n in set().union(
*(rx.descendants(self._graph, self._graph.nodes().index(o)) for o in ops)
)
)
return des - set(ops)

def _in_topological_order(self, ops):
"""Sorts a set of operators in the circuit in a topological order.
Expand All @@ -346,8 +367,9 @@ def _in_topological_order(self, ops):
Returns:
Iterable[Operator]: same set of operators, topologically ordered
"""
G = nx.DiGraph(self._graph.subgraph(ops))
return nx.dag.topological_sort(G)
G = self._graph.subgraph(list(self._graph.nodes().index(o) for o in ops))
indexes = rx.topological_sort(G)
return list(G[x] for x in indexes)

def ancestors_in_order(self, ops):
"""Operator ancestors in a topological order.
Expand All @@ -360,8 +382,7 @@ def ancestors_in_order(self, ops):
Returns:
list[Operator]: ancestors of the given operators, topologically ordered
"""
# return self._in_topological_order(self.ancestors(ops)) # an abitrary topological order
return sorted(self.ancestors(ops), key=_by_idx)
return sorted(self.ancestors(ops), key=_by_idx) # an abitrary topological order

def descendants_in_order(self, ops):
"""Operator descendants in a topological order.
Expand Down Expand Up @@ -585,8 +606,10 @@ def update_node(self, old, new):
# NOTE Does not alter the graph edges in any way. variable_deps is not changed, _grid is not changed. Dangerous!
if new.wires != old.wires:
raise ValueError("The new Operator must act on the same wires as the old one.")

new.queue_idx = old.queue_idx
nx.relabel_nodes(self._graph, {old: new}, copy=False) # change the graph in place
self._graph[self._graph.nodes().index(old)] = new

self._operations = self.operations_in_order
self._observables = self.observables_in_order

Expand Down Expand Up @@ -632,9 +655,10 @@ def get_depth(self):
# expressed in terms of edges, and we want it in terms of nodes).
if self._depth is None and self.operations:
if self._operation_graph is None:
self._operation_graph = self.graph.subgraph(self.operations)
self._depth = nx.dag_longest_path_length(self._operation_graph) + 1

self._operation_graph = self._graph.subgraph(
list(self._graph.nodes().index(node) for node in self.operations)
)
self._depth = rx.dag_longest_path_length(self._operation_graph) + 1
return self._depth

def has_path(self, a, b):
Expand All @@ -647,7 +671,17 @@ def has_path(self, a, b):
Returns:
bool: returns ``True`` if a path exists
"""
return nx.has_path(self._graph, a, b)
if a == b:
return True
maliasadi marked this conversation as resolved.
Show resolved Hide resolved

return (
len(
rx._digraph_dijkstra_shortest_path(
maliasadi marked this conversation as resolved.
Show resolved Hide resolved
self._graph, self._graph.nodes().index(a), self._graph.nodes().index(b)
)
)
!= 0
)

@property
def max_simultaneous_measurements(self):
Expand Down
Loading