-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[WIP] Adding FinalPermutation attribute to DAGCircuit and QuantumCircuit #12534
base: main
Are you sure you want to change the base?
Conversation
One or more of the following people are relevant to this code:
|
def compose_with_permutation(self, permutation, front) -> "FinalPermutation": | ||
"""Composes FinalPermution with a permutation.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am looking for a better name for this function.
"""Creates a copy of the FinalPermutation object.""" | ||
return FinalPermutation(self.permutation.copy()) | ||
|
||
def push_using_mapping(self, forward_map, num_target_qubits=None) -> "FinalPermutation": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And for a better name for this function.
original_qubit_indices (dict): The mapping from qubits to positional indices | ||
for the ``layout`` argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This argument allows creating a callback function that checks the equivalence of the current operator and the original operator after each transpiler pass, something along the following:
def callback_func(pass_, dag, time, property_set, count):
circuit = dag_to_circuit(dag)
current_op = Operator.from_circuit(
circuit,
layout=property_set['layout'],
final_layout=property_set['final_layout'],
original_qubit_indices=property_set['original_qubit_indices']
)
current_op_new = Operator._from_circuit_new(
circuit,
layout=property_set['layout'],
original_qubit_indices=property_set['original_qubit_indices']
)
original_op = op if circuit.num_qubits == original_num_qubits else extended_op
print(f"After-pass: equiv = {original_op.equiv(current_op)}")
print(f"After-pass-new: equiv = {original_op.equiv(current_op_new)}")
I have found this very useful to catch problems, however this is still not fully correct: the SetLayout
pass sets the pass manager's "layout" attribute, but it's only the later pass ApplyLayout
that effectively applies it to the circuit, so in-between these two passes the equivalence is not preserved. Though a simple way would be to have ApplyLayout
set an extra attribute layout_is_applied
and use layout
when checking equivalence only when layout_is_applied
is set.
layout_permutation = _inverse_pattern(layout.to_permutation(circuit_graph.qubits)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and in other similar code things could be done more directly. I.e. instead of computing the final layout and converting it to a permutation, we could directly compute the permutation.
@@ -71,3 +71,13 @@ def _decompose_cycles(cycles): | |||
for i in range(m // 2): | |||
swap_list.append((cycle[i - 1], cycle[m - 2 - i])) | |||
return swap_list | |||
|
|||
|
|||
def _compose_permutations(*perms): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note that this file was moved to rust in #12327
Pull Request Test Coverage Report for Build 9449141832Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
Summary
This PR addresses #12127. It supersedes #12206. See also @jakelishman's comments in #9523.
The current way of reasoning about the implicit permutation applied to DAGCircuit's output qubits throughout the transpiler flow is very complicated and non-intuitive, involving reasoning about "layouts", storing both the "final_layout" and the "virtual_permutation_layout" attributes in the property set, and updating the "final_layout" at the end of the transpiler run.
A simpler way is to simply keep track of this implicit permutation throughout the transpiler flow, with every transpiler pass having to update both the dag circuit and the implicit output permutation accordingly. This PR implements this proposal, and in addition keeps the final permutation as an attribute of DAGCircuit and Quantum circuit (and not of the pass manager).
I would love to have feedback on the current implementation, as well as a discussion on how to move forward and hopefully completely replace the "final_layout", etc. attributes by this new functionality.