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

Cut graphs can be fragmented into subgraphs and communication graph #2153

Merged
merged 61 commits into from
Feb 7, 2022

Conversation

anthayes92
Copy link
Contributor

Context:
The circuit cutting pipeline consists of manually placing a wirecut operator during construction of a circuit, converting this circuit to a graph and then replacing the wirecut nodes with measure and prepare nodes. At this stage the graph is ready to be fragmented into subgraphs. A communication graph is also returned, this is a graph where each node represents a fragment and edges denote the flow of qubits between fragments. This is required for reconstruction in following steps.

Description of the Change:
A method for fragmenting cut graphs has been added

Benefits:
Facilitates the circuit cutting compiler

anthayes92 and others added 30 commits January 17, 2022 15:25
Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com>
Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com>
@anthayes92 anthayes92 changed the title Sc 14127 a user can fragment a circuit graph into Cut graphs can be fragmented into subgraphs and communication graph Feb 2, 2022
@anthayes92 anthayes92 marked this pull request as ready for review February 2, 2022 22:49
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2022

Hello. You may have forgotten to update the changelog!
Please edit doc/releases/changelog-dev.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

Copy link
Contributor

@trbromley trbromley left a comment

Choose a reason for hiding this comment

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

Thanks @anthayes92! Great work! Have left some suggestions.

doc/releases/changelog-dev.md Outdated Show resolved Hide resolved
pennylane/transforms/__init__.py Outdated Show resolved Hide resolved
pennylane/transforms/qcut.py Outdated Show resolved Hide resolved
pennylane/transforms/qcut.py Outdated Show resolved Hide resolved

Args:
graph (MultiDiGraph): directed multigraph containing measure and prepare
nodes at cut locations
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
nodes at cut locations
nodes at cut locations

tests/transforms/test_qcut.py Outdated Show resolved Hide resolved
tests/transforms/test_qcut.py Outdated Show resolved Hide resolved
sub_1_expected_edges,
sub_2_expected_edges,
sub_3_expected_edges,
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like a pain to code up!

tests/transforms/test_qcut.py Outdated Show resolved Hide resolved
compare_fragment_nodes(list(subgraph.nodes(data=True)), expected_n)

for subgraph, expected_e in zip(subgraphs, expected_edges):
compare_fragment_edges(list(subgraph.edges(data=True)), expected_e)
Copy link
Contributor

Choose a reason for hiding this comment

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

These tests are great! I'd like to consider having a few more "integration level" tests with a variety of starting configurations. But perhaps this is best left until once we have graph_to_tape(). 🤔

Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com>
Copy link
Contributor

@zeyueN zeyueN left a comment

Choose a reason for hiding this comment

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

Thanks for me keeping in the loop! Only went over the code and things made sense. The only concern is the side effects Tom's mentioned.

if isinstance(node1, MeasureNode):
assert isinstance(node2, PrepareNode)
cut_edges.append((node1, node2))
graph.remove_edge(node1, node2)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would make a (deep) copy of graph beforehand to avoid of risk of unwanted side effects, as long as the graph is not too large, which is the case for us right? Adding edges back in could change the internal order of how things are stored, which is always a risk.

if isinstance(node1, MeasureNode):
assert isinstance(node2, PrepareNode)
cut_edges.append((node1, node2))
graph.remove_edge(node1, node2)
Copy link
Contributor

Choose a reason for hiding this comment

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

If things go multiqubit, the wire should also be stored in the data of cut_edges right?

if subgraph.has_node(node2):
end_fragment = i

communication_graph.add_edge(start_fragment, end_fragment, pair=(node1, node2))
Copy link
Contributor

Choose a reason for hiding this comment

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

I would say even without multiquibit Measure/Prepare, it should be helpful if we store the wire index in the edge as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, added thanks!

subgraphs = tuple(graph.subgraph(n) for n in subgraph_nodes)

communication_graph = MultiDiGraph()
communication_graph.add_nodes_from(range(len(subgraphs)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a real suggestion but just wanted to throw it out there. Instead of constructing a graph with integer nodes, if we were to stick the subgraphs into the nodes' data attributes for the communication_graph (or, if possible, directly use subgraphs as nodes), we would only need to return the communication_graph which carries the subgraphs inside it. But again I would imagine it to be quite difficult to use with nx's default UI.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We also discussed this possibility, we came to the conclusion that there were fairly equal pros and cons so it came down to that fact that it's already coded up, would interfere with the current tests and we're pushing to implement quickly.

Happy to be persuaded otherwise though 😁

Copy link
Contributor

@trbromley trbromley left a comment

Choose a reason for hiding this comment

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

Thanks @anthayes92, approved! Although I'd be curious to quickly resolve the copy/deepcopy question first.

pennylane/transforms/qcut.py Outdated Show resolved Hide resolved
pennylane/transforms/qcut.py Outdated Show resolved Hide resolved
tests/transforms/test_qcut.py Show resolved Hide resolved
anthayes92 and others added 2 commits February 7, 2022 17:52
Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com>
@anthayes92 anthayes92 merged commit e4f33cc into master Feb 7, 2022
@anthayes92 anthayes92 deleted the sc-14127-a-user-can-fragment-a-circuit-graph-into branch February 7, 2022 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants