Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for disjoint coupling maps to SabreLayout (#9802)
* Add support for disjoint coupling maps to SabreLayout This commit adds support to the SabreLayout pass for targeting disjoint CouplingMap objects. The SABRE algorithm is written assuming a connected graph, so to enable targeting a disjoint coupling graph this commit decomposes the circuit into it's weakly connected components and then maps those to the connected components of the coupling map and runs the rust portion of the sabre code on each connected component of the coupling graph. The results for each subgraph of the target backend is then combined the pass is building the output dag. In general the biggest potential issue for output quality right now is the mapping function does not take into account the relative connectivity of the dag component and the coupling map component. The mapping is just done in order and it tries every component until it finds one that has enough qubits. In the future we should use a heuristic to try and pack the components based on what we expect will require the least amount of swaps, but we can attempt that in a future PR. * Fix handling of barriers across separating components This commit fixes the handling of the barrier directive as the input DAG is split across multiple components. It is entirely valid for an input dag to have a multi-qubit barrier that spans multiple connected components. However, such barriers shouldn't be treated as multi-qubit operation for computing the connected components (as this result in the components being treated larger than they otherwise would be). To handle this edge case the logic introduced into this commit is prior to computing the connected components in the input dag we split each multi-qubit barrier into n single qubit barriers and assign a UUID label to each of the single qubit barriers. Then after we create each subgraph DAGCircuit object for each connected component we find all the barriers with a UUID and recombine them into a multi qubit barrier. This will retain the barriers characteristics for each connected component (as if it were in the original disjoint dag). Then in `SabreLayout` after we've built the output mapped dagcircuit we run the combination function one more time to combine the multiqubit dags across the different components, and in that process the UUID labels are removed. It is worth pointing out the downside with this approach is that it precludes preserving barriers with labels through transpile(). * Fix compatibility with Python < 3.9 * Adjust sorting order for mapping components * Add full path transpile() tests * Tag six component test as a slow test * Fix handling of splitting dags with shared classical bits This commit fixes the handling of the separate_dag() function when the input DAGCircuit has shared classical bits between quantum connected components. In previous commits on this branch these would incorrectly be treated as a single connected component because from the perspective of rustworkx's weakly_connected_components() function there is no difference between the type of wires when computing the connected components of the graph. This commit fixes this by instead of computing the connected components of the DAG itself we create an interaction graph of just the quantum component and use that to find the connected components of qubits. From that we build subgraphs of the DAGCircuit for each connected component DAGCircuit. This ends up being less efficient, but produces the correct result by ignoring the classical component for computing the connected components. * Add more test coverage and release notes * Don't route in SabreLayout with > 1 layout component with shared clbits When we run SabreLayout normally we're running both the layout and routing stage together. This is done for performance because the rust component is running routing internally so we avoid multiple back and forths between Python and Rust this way and it can lead to noticeable runtime improvements when doing this. However, in the case of > 1 circuit component that have any shared clbits we can not safetly route from the split dag components because the data dependency is lost for the classical component of the circuit is lost between the split components. To do routing without potentially reordering the data dependencies for the classical bits we need to run it on the combined dag all at once. For SabreLayout the easiest way to do that is to just have it work as a normal layout pass and let `SabreSwap` do the routing as it will have the full context and won't cause things to reorder incorrectly. This commit makes the change by checking if we have more than one component and any shared clbits between any components. If we do then we skip routing in SabreLayout and only return layout information. * Apply suggestions from code review Co-authored-by: Kevin Hartman <kevin@hart.mn> * Fix return type hint for map_components() * Cleanup variables and set usage in separate_dag * Remove duplicate lines in SabreLayout * Update error message text for routing_pass arg and disjoint cmap Co-authored-by: Kevin Hartman <kevin@hart.mn> * Improve docstring for map_components * Add comment explaining dag composition in run_pass_over_connected_components --------- Co-authored-by: Kevin Hartman <kevin@hart.mn>
- Loading branch information