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

Extracting permutation of classical registers from Quantum Circuit #5350

Closed
yourball opened this issue Nov 6, 2020 · 9 comments · Fixed by #8597
Closed

Extracting permutation of classical registers from Quantum Circuit #5350

yourball opened this issue Nov 6, 2020 · 9 comments · Fixed by #8597
Assignees
Labels
type: enhancement It's working, but needs polishing

Comments

@yourball
Copy link

yourball commented Nov 6, 2020

Hi,

during routing/mapping passes input quantum registers could be permuted, the permutation logical -> physical qregs is saved in quantum_circuit._layout property and could be easily accessed by a user.

Similarly, classical cregs also become permuted after routing/mapping: physical cregs->logical cregs. This permutation can be extracted when applying measure gates quantum_circuit.measure_all(). E.g. when two cregs (0 and 1) are permuted than
the measure gates will look like:
measure qreg[0] creg[1];
measure qreg[1] creg[0].

However, when measure gates are not applied, there is still could be implicit permutation of cregs after mapping/routing pass. It seems that there is no simple way to access information about cregs permutation, which could be inconvenient in some cases. For example this information is necessary to check the equivalence of original and transpiled circuits.
Is it possible to add this information as a property of QuantumCircuit object? Or there is some other way to access this information?

Thanks a lot!

@yourball yourball added the type: enhancement It's working, but needs polishing label Nov 6, 2020
@alvinjoseph7
Copy link

The plot_gate_map() from qiskit.visualization can be used to view the original layout. And transpiled circuit can be viewed via plot_circuit_layout() which also belongs to qiskit.visualization.
In this way, 2 plots will be displayed and both will have to be compared.
It's doable,but I'm open to a simpler solution if it exists.

@kdk
Copy link
Member

kdk commented Nov 25, 2020

Hi @yourball, cregs will not be modified by the routing or layout process. Can you provide an example of the behavior you're seeing and the behavior you'd expect?

@ajavadia
Copy link
Member

ajavadia commented Feb 8, 2021

The circuit._layout gives the initial layout (i.e. the initial permutation of qubits before the circuit starts). I think this issue is asking for a convenient way to view the final layout (i.e. the final permutation, which is usually absorbed into the measurements and reorders their clbit targets). I agree it could be handy to access this.

@nonhermitian
Copy link
Contributor

This is a topic for the hackathon next week: qiskit-community/qiskit-hackathon-korea-21#2

@yourball
Copy link
Author

yourball commented Feb 9, 2021

The circuit._layout gives the initial layout (i.e. the initial permutation of qubits before the circuit starts). I think this issue is asking for a convenient way to view the final layout (i.e. the final permutation, which is usually absorbed into the measurements and reorders their clbit targets). I agree it could be handy to access this.

@ajavadia Thanks, that is the exactly what I mean! It is useful to access the information about virtual permutation of qubits at the end of the circuit even when there are no measurement gates. For example this is important for equivalence checking of circuits before/after optimization.

@nonhermitian
Copy link
Contributor

It is not strictly needed in that case, although it makes it much easier. Instead of checking equiv to identity with possible phase, you look for equiv up to a permutation matrix.

@ajavadia
Copy link
Member

I recently wrote a function for my own usage, but something like this could be helpful.

def unpermute(circ_mapped):
    """
    Apply left and right permutations to remove effect of layout and measurement retargeting.
    """
    empty_circ = QuantumCircuit(circ_mapped.num_qubits)

    lo = circ_mapped._layout
    tokenswapper = LayoutTransformation(coupling_map=CouplingMap.from_line(8),
                                        to_layout=lo,
                                        from_layout=Layout.generate_trivial_layout(lo.get_registers().pop()))
    pm = PassManager(tokenswapper)
    initial_permutation = pm.run(empty_circ)
    initial_permutation.barrier()

    final_perm = [0] * 8
    for op, qubits, clbits in circ_mapped.data:
        if op.name == 'measure':
            final_perm[qubits[0].index] = clbits[0].index

    tokenswapper = LayoutTransformation(coupling_map=CouplingMap.from_line(8),
                                        to_layout=Layout({v: p for v, p in zip(circ_mapped.qubits, final_perm)}),
                                        from_layout=Layout.generate_trivial_layout(lo.get_registers().pop()))
    pm = PassManager(tokenswapper)
    empty_circ.barrier()
    final_permutation = pm.run(empty_circ)

    circ_left_permuted = initial_permutation.compose(circ_mapped.remove_final_measurements(inplace=False))
    circ_left_right_permuted = circ_left_permuted.compose(final_permutation)
    return circ_left_right_permuted

A circuit mapped by Qiskit:
image

Calling unpermute() function on it models the left layout and right measurement reordering as explicit permutations:
image

I used the TokenSwapper pass but using the qiskit.circuit.library.Permutation is easier (but it needs this bug fix: #5813)

@1ucian0
Copy link
Member

1ucian0 commented Feb 10, 2021

Could PR #5280 help here?

from qiskit import QuantumCircuit
from qiskit.compiler import transpile
from qiskit.transpiler import CouplingMap

circ = QuantumCircuit(3)
circ.h(0)
circ.cx(0,2)
print(circ)

coupling_map = CouplingMap([[0,1], [1,2]])

transpiled = transpile(circ, coupling_map=coupling_map, routing_method='basic', initial_layout=[0,1,2], restore_layout='initial')
print(transpiled)
     ┌───┐     
q_0: ┤ H ├──■──
     └───┘  │  
q_1: ───────┼──
          ┌─┴─┐
q_2: ─────┤ X ├
          └───┘
         ┌───┐           
q_0 -> 0 ┤ H ├─X───────X─
         └───┘ │       │ 
q_1 -> 1 ──────X───■───X─
                 ┌─┴─┐   
q_2 -> 2 ────────┤ X ├───
                 └───┘   

@nonhermitian
Copy link
Contributor

This is done for the StochasticSwap in #6827. Others can be modified in a similar manner.

@ajavadia ajavadia added this to the 0.20 milestone Nov 9, 2021
@kdk kdk self-assigned this Feb 15, 2022
@kdk kdk modified the milestones: 0.20, 0.21 Mar 29, 2022
@kdk kdk modified the milestones: 0.21, 0.22 Jun 14, 2022
mtreinish added a commit to mtreinish/qiskit-core that referenced this issue Aug 22, 2022
This commit expands the transpiler to return the final layout
permutation caused by the swap mapping in the routing stage. The routing
passes already return the final layout permutation caused by the swap
mapping to the property set (although for some passes it was only
setting it sometime, which this fixes). This commit just sets the
_final_layout attribute of QuantumCircuit objects to store this Layout
object. This lets user track the qubit permutation caused by
transpilation if they need.

Fixes Qiskit#5350
@mtreinish mtreinish removed this from the 0.22 milestone Sep 30, 2022
@mergify mergify bot closed this as completed in #8597 Jan 18, 2023
mergify bot added a commit that referenced this issue Jan 18, 2023
* Add final layout to output quantum circuit from transpiler

This commit expands the transpiler to return the final layout
permutation caused by the swap mapping in the routing stage. The routing
passes already return the final layout permutation caused by the swap
mapping to the property set (although for some passes it was only
setting it sometime, which this fixes). This commit just sets the
_final_layout attribute of QuantumCircuit objects to store this Layout
object. This lets user track the qubit permutation caused by
transpilation if they need.

Fixes #5350

* Fix qarg list construction

* Use permutation to get a hacky solution

* Fix lint

* Add release note

* Add test case for manually setting final layout

* Handle transpile changing registers internally

* Fix tests

* Remove stray debug print

* Remove out of date raises documentation

Co-authored-by: Alexander Ivrii <alexi@il.ibm.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement It's working, but needs polishing
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants