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

Improve initial qubit mapping algorithm #144

Merged
merged 7 commits into from
Mar 31, 2021

Conversation

wingers
Copy link
Collaborator

@wingers wingers commented Feb 11, 2021

Fixes #127 and relates to quantumlib/unitary#48.


Args:
g: A physical qubits graph or a logical qubits graph.
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

should we move the floyd-warshall implementation into a separate file? That may be better organizationally. And since it is a fairly generic algorithm, it seems like something that we could add test coverage for independently of the rest of the initial mapping implementation

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i agree the floyd-warshall algorithm and the various bfs algorithms are fairly generic, but their implementation all have to be aware of whether it's graph param is a logical qubit graph (where edges contain moment info) or physical qubit graph or either, so i think it might make more sense to keep them in the same class.

but yah, it's def worth adding test coverage independently for these more generic algorithms; maybe we can keep the test files separate? kind of like what we have right now in dynamic_look_ahead_heuristic_circuit_transformer_test.py, but with more / better test cases?

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed, lets add smaller focused files if we can. Besides the tests I'm also a bit concerned about the potential for circuit_transformer.py to explode in size if we add more transformers, but should be fine for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

by the way, I realized another reason it would be nice to refactor out the floyd-warshall implementation: the swap update step needs the precomputed node-to-node shortest path distances, too. We can leave that for a future pull request though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sg, i refactored it out to a separate function!

recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved
@wingers wingers requested a review from weinstein February 12, 2021 03:34
recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved

Args:
g: A physical qubits graph or a logical qubits graph.
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

by the way, I realized another reason it would be nice to refactor out the floyd-warshall implementation: the swap update step needs the precomputed node-to-node shortest path distances, too. We can leave that for a future pull request though.

"""
qubits = []
neighbors_sorted_by_moment = sorted(lg[lq], key=lambda x: x[1])
for neighbor in neighbors_sorted_by_moment:
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, this can be simplified:

for neighbor in neighbors_sorted_by_moment.keys():

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

neighbors_sorted_by_moment is a list but updated to make this a bit cleaner.

recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved
recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved
recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved
class DynamicLookAheadHeuristicCircuitTransformer(CircuitTransformer):
"""Optimizer that transforms a circuit to satify a device's constraints.

This implements the initial mapping algorithm and the SWAP update algorithm
Copy link
Collaborator

Choose a reason for hiding this comment

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

Referencing the paper is great, but it would be great to have a one paragraph summary for those who are too busy to read the whole paper.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done!

recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved
q = op.qubits[0]
if q not in g:
g[q] = []
if len(op.qubits) == 2:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we change this to elif len(op.qubits) == 2 and then add an else that handles len(op.qubits) > 2 (possibly by throwing a ValueError? It might be a good idea to make sure we skip measurement gates properly too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sg, updated to throw a ValueError when len(ops.qubits) > 2; also added a check to skip measurement gates.

recirq/quantum_chess/circuit_transformer.py Outdated Show resolved Hide resolved
recirq/quantum_chess/circuit_transformer_test.py Outdated Show resolved Hide resolved
recirq/quantum_chess/circuit_transformer_test.py Outdated Show resolved Hide resolved
t = ct.ConnectivityHeuristicCircuitTransformer(device)
device.validate_circuit(t.transform(c))
# t = ct.DynamicLookAheadHeuristicCircuitTransformer(device)
# device.validate_circuit(t.transform(c))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we add tests for some of the public functions? For instance, adding functionality to test least_connected_qubit should be simple enough.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yah, tests are added in initial_mapping_utils_test.py (which was previously dynamic_look_ahead_heuristic_circuit_transformer_test.py).

a4 = cirq.NamedQubit('a4')
a5 = cirq.NamedQubit('a5')
a6 = cirq.NamedQubit('a6')
a7 = cirq.NamedQubit('a7')
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional: I think the style guide would have these e capitalized (i.e. A7), but this goes against chess algebraic style, so I am not sure which is better.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd agree on lower, for consistency with chess.



@pytest.mark.parametrize('transformer', [ct.ConnectivityHeuristicCircuitTransformer])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are we parameterizing if it only has one option? Same with several functions below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added DynamicLookAheadHeuristicCircuitTransformer to the list now that it's updated to use SwapUpdater.

4: [3],
}
assert imu.get_least_connected_qubit(g, deque([0, 1, 2])) in {0, 2}
assert imu.get_least_connected_qubit(g, deque([3, 4])) in {3, 4}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we want to have a test case that is less ambiguous?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added!

Args:
g: A physical qubits graph or a logical qubits graph.
v: The size of the graph.
m: A mapping of qubit to index.
Copy link
Contributor

Choose a reason for hiding this comment

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

would the interface be simpler if we keyed things by Qid directly and returned a dict from Pair[Qid, Qid] -> int instead of requiring an intermediate Qid -> index mapping? Then the only args we'd need to provide would be the graph dict

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated and it's much cleaner now!

Copy link
Contributor

Choose a reason for hiding this comment

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

just need to update the return type hint to something like Dict[Tuple[Qid, Qid], int] (who/what is using these type hints anyways...?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ty for catching that! i'm guessing they're for eventual docs generation...?

@wingers wingers requested review from dstrain115 and weinstein March 5, 2021 02:02
@wingers wingers merged commit 2c2a514 into quantumlib:master Mar 31, 2021
@wingers wingers deleted the improve-initial-mapping branch March 31, 2021 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Quantum Chess: Improve Qubit picking algorithm
5 participants