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

[WIP] Adding FinalPermutation attribute to DAGCircuit and QuantumCircuit #12534

Open
wants to merge 22 commits into
base: main
Choose a base branch
from

Conversation

alexanderivrii
Copy link
Contributor

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.

@alexanderivrii alexanderivrii requested review from ShellyGarion and a team as code owners June 9, 2024 22:18
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

Comment on lines +51 to +52
def compose_with_permutation(self, permutation, front) -> "FinalPermutation":
"""Composes FinalPermution with a permutation."""
Copy link
Contributor Author

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":
Copy link
Contributor Author

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.

Comment on lines +395 to +396
original_qubit_indices (dict): The mapping from qubits to positional indices
for the ``layout`` argument.
Copy link
Contributor Author

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.

Comment on lines 389 to 390
layout_permutation = _inverse_pattern(layout.to_permutation(circuit_graph.qubits))

Copy link
Contributor Author

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):
Copy link
Member

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

@coveralls
Copy link

coveralls commented Jun 10, 2024

Pull Request Test Coverage Report for Build 9449141832

Warning: 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

  • 89 of 99 (89.9%) changed or added relevant lines in 14 files are covered.
  • 50 unchanged lines in 4 files lost coverage.
  • Overall coverage decreased (-0.03%) to 89.561%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/circuit/final_permutation.py 32 36 88.89%
qiskit/quantum_info/operators/operator.py 23 29 79.31%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/lex.rs 5 91.09%
qiskit/providers/providerutils.py 10 48.48%
qiskit/synthesis/one_qubit/one_qubit_decompose.py 11 79.52%
crates/qasm2/src/parse.rs 24 96.23%
Totals Coverage Status
Change from base Build 9418156791: -0.03%
Covered Lines: 62585
Relevant Lines: 69880

💛 - Coveralls

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.

4 participants