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

Port star_preroute to rust #12761

Merged
merged 6 commits into from
Jul 29, 2024

Conversation

henryzou50
Copy link
Contributor

Summary

Closes #12337

This PR ports the core logic of star_preroute from Python to Rust. The changes involve creating a new Rust module for the star prerouting algorithm and updating the corresponding Python code to integrate with this new Rust functionality.

These changes only involve the first part of porting star_prerouting to rust, as it mainly handles porting the logic of transforming the DAG with the StarBlocks to rust, but we will still need to decide how we should port collecting the StarBlocks to rust. This is a bit more tricky as there are still ongoing discussion on how we can extend the block collection, such as in PR #12498 .

Details and comments

  • New Rust file: Added star_preroute.rs to handle the core logic of the function star_preroute from the python side. This file defines the type aliases for node and block representations, which matches the current block representation of the StarBlock (except that the center is just a bool, as we only need to know if there is a center), and the node representation matches how the nodes used in SabreDAG. The star_preroute function processes the star blocks witihin the SabreDAG to finds the linear routing equivalent and then returns the result as a SabreResult.
  • Node representation: A key part of this implementation is how it takes advantage of SabreResult and SabreDAG, so the node representation is a tuple of the node id, list of qubit indices, a set of classical bit indices, and a directive flag. However, once we update the regular DAG to rust, this part may change significantly, but the main logic will remain unchanged.
  • Updates in the SABRE rust module: To use sabre_dag.rs and swap_map.rs in star_prerouting, I change them to be public in crates/accelerate/src/sabre/mod.rs. Not sure if it makes more sense to do it this way or to move star_prerouting to crates/accelerate/src/sabre/ since it mimics the methods used in Sabre to change the dag.
  • Python side updates: Imported the necessary modules and only modified the function star_preroute so that now the function performs the heavy lifting of transforming the DAG within the Rust space, leveraging _build_sabre_dag and _apply_sabre_result.
  • Issues: I was not sure how correctly handle nodes with control flow from the rust side. I know that route.rs handles this with route_control_flow_block to populate the node_block_results for SabreResult, but I was not sure how to best take advantage of this function for star_prerouting. Currently, the node_block_results for star_prerouting essentially always empty and just there to haveSabreResult. There also seems to be no unit tests for star_prerouting that includes control flow.

…st. The changes involve creating a new Rust module for the star prerouting algorithm and updating the corresponding Python code to integrate with this new Rust functionality.

Details:
- New Rust file: Added `star_preroute.rs` to handle the core logic of the function `star_preroute` from the python side. This file defines the type aliases for node and block representations, which matches the current block representation of the `StarBlock` (except that the center is just a bool, as we only need to know if there is a center), and the node representation matches how the nodes used in `SabreDAG`. The `star_preroute` function processes the star blocks witihin the `SabreDAG`  and finds the linear routing equivalent and then returns the result as a `SabreResult`. Thus we can use the same methods we used in Sabre, such as `_build_sabre_dag` and `_apply_sabre_result`.
- Node representation: A key part of this implementation is how it takes advantage of `SabreResult` and `SabreDAG`, so the node representation is a tuple of the node id, list of qubit indices, a set of classical bit indices, and a directive flag. However, once we update the regular DAG to rust, this part may change significantly.
- Updates in the SABRE rust module: To use `sabre_dag.rs` and `swap_map.rs` in `star_prerouting`, I change them to be public in `crates/accelerate/src/sabre/mod.rs`. Not sure if it makes more sense to do it this way or to move `star_prerouting` to `crates/accelerate/src/sabre/` since it mimics the methods used in Sabre to change the dag.
- Python side updates: Imported the necessary modules and only modified the function `star_preroute` so that now the function performs the heavy lifting of transforming the DAG within the Rust space, leveraging `_build_sabre_dag` and `_apply_sabre_result`.
- Possible issues: I was not sure how correctly handle control flow from the rust side. I know that `route.rs` handles this with `route_control_flow_block` to populate the `node_block_results` for `SabreResult`, but I was not sure how to best take advantage of this function for `star_prerouting`. Currently, the `node_block_results` for `star_prerouting` essentially always empty and just there to have`SabreResult`. There also seems to be no unit tests for `star_prerouting` that includes control flow.
@henryzou50 henryzou50 requested a review from a team as a code owner July 11, 2024 15:02
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core
  • @kevinhartman
  • @mtreinish

@mtreinish mtreinish added this to the 1.2.0 milestone Jul 11, 2024
@mtreinish mtreinish added Changelog: New Feature Include in the "Added" section of the changelog Rust This PR or issue is related to Rust code in the repository performance mod: transpiler Issues and PRs related to Transpiler labels Jul 11, 2024
@coveralls
Copy link

coveralls commented Jul 12, 2024

Pull Request Test Coverage Report for Build 10144562567

Details

  • 167 of 174 (95.98%) changed or added relevant lines in 4 files are covered.
  • 20 unchanged lines in 5 files lost coverage.
  • Overall coverage decreased (-0.01%) to 89.758%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/transpiler/passes/routing/star_prerouting.py 27 34 79.41%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/expr.rs 1 94.02%
qiskit/transpiler/passes/synthesis/unitary_synthesis.py 2 88.39%
crates/qasm2/src/lex.rs 5 92.11%
crates/qasm2/src/parse.rs 6 97.61%
qiskit/synthesis/two_qubit/xx_decompose/decomposer.py 6 90.84%
Totals Coverage Status
Change from base Build 10143161798: -0.01%
Covered Lines: 66928
Relevant Lines: 74565

💛 - Coveralls

Copy link
Contributor

@sbrandhsn sbrandhsn left a comment

Choose a reason for hiding this comment

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

This mostly looks great to me, thanks! :-) I left a couple of in-line comments that should partially be addressed in my opinion. Apart from this:

  1. Do you think porting SPR to Rust requires any extra testing?
  2. I think a good additional test would be to route our standard QFT definition and check whether the resulting circuit requires n-1 swap gates where n is the number of CNOT gates and check whether the QFT circuit has been linearized (you can run
    def build_interaction_graph(dag, strict_direction=True):
    and check whether #edges -1 == #vertices)?
  3. Can you run a quick benchmark on QFT to see how the runtime improves? I'm thinking about just routing the QFT circuit and measuring the time of doing that (no ASV or so required).

WRT circuits with classical feedback, I think it is fine to just have it as is right now. Ideally, we would check whether we wanted to run SPR at all and a ControlFlowOp may very likely result in blocking a SPR run.

crates/accelerate/src/star_prerouting.rs Show resolved Hide resolved
crates/accelerate/src/star_prerouting.rs Outdated Show resolved Hide resolved
crates/accelerate/src/star_prerouting.rs Show resolved Hide resolved
- Added the additional test of qft linearization and that the resultings circuit has `n-2` swap gates where `n` is the number of cp gates.
- Changed the `node_id` in `apply_swap` of `star_preroute.rs` to use the current node id as it is more efficient, but just does not match how we do it in Sabre. This makes it so that we apply the gate first then the swap, which fixes an error we had before where we never placed a swap gate at the end of the processing a block. This only affected tests where we had multiple blocks to process. To make sure we apply the results correctly from `SabreResult`, I added a flag to `_apply_sabre_result` to treat the case of `StarPrerouting` differently so that it applies the swap after applying the node.
- Added a hasp map from node to block to make processing each node in the given processing order have `n + n` time complexity instead of `n^2`. As a result, we can also remove the function `find_block_id`
@henryzou50
Copy link
Contributor Author

This mostly looks great to me, thanks! :-) I left a couple of in-line comments that should partially be addressed in my opinion. Apart from this:

1. Do you think porting SPR to Rust requires any extra testing?

2. I think a good additional test would be to route our standard QFT definition and check whether the resulting circuit requires n-1 swap gates where n is the number of CNOT gates and check whether the QFT circuit has been linearized (you can run https://github.com/Qiskit/qiskit/blob/1191fcbc7277216ce03d30f1bf0d2767ea681cd9/qiskit/transpiler/passes/layout/vf2_utils.py#L29
    and check whether #edges -1 == #vertices)?

3. Can you run a quick benchmark on QFT to see how the runtime improves? I'm thinking about just routing the QFT circuit and measuring the time of doing that (no ASV or so required).

WRT circuits with classical feedback, I think it is fine to just have it as is right now. Ideally, we would check whether we wanted to run SPR at all and a ControlFlowOp may very likely result in blocking a SPR run.

  1. I don't think porting StarPrerouting to rust requires any extra testing at the moment, especially since this PR only ports the logic of the function star_preroute. I think the tests in test_star_prerouting.py are cover the correctness of `star_preroute.

  2. That is a great test! I just added it, but I have some clarifying questions:

  • Shouldn't the resulting circuit requires n-2 swap gates where n is the number of cp gates
  • For instance, in the 6-qubit QFT after applying StarPreRouting we get
q_4 -> 0 ──────■──────────────────────────────────────────────────────────░─┤ H ├─■────────X───────────────────────────────────────░─┤ H ├─■────────X──────────────────────────░─┤ H ├─■────────X──────────────░─┤ H ├─■────────░───────░─
         ┌───┐ │P(π/2)                                                    ░ └───┘ │P(π/2)  │                                       ░ └───┘ │P(π/2)  │                          ░ └───┘ │P(π/2)  │              ░ └───┘ │P(π/2)  ░ ┌───┐ ░ 
q_5 -> 1 ┤ H ├─■────────■────────X────────────────────────────────────────░───────■────────X──■────────X───────────────────────────░───────■────────X──■────────X──────────────░───────■────────X──■────────X──░───────■────────░─┤ H ├─░─
         └───┘          │P(π/4)  │                                        ░                   │P(π/4)  │                           ░                   │P(π/4)  │              ░                   │P(π/4)  │  ░                ░ └───┘ ░ 
q_3 -> 2 ───────────────■────────X──■────────X────────────────────────────░───────────────────■────────X──■────────X───────────────░───────────────────■────────X──■────────X──░───────────────────■────────X──░────────────────░───────░─
                                    │P(π/8)  │                            ░                               │P(π/8)  │               ░                               │P(π/8)  │  ░                               ░                ░       ░ 
q_2 -> 3 ───────────────────────────■────────X──■─────────X───────────────░───────────────────────────────■────────X──■─────────X──░───────────────────────────────■────────X──░───────────────────────────────░────────────────░───────░─
                                                │P(π/16)  │               ░                                           │P(π/16)  │  ░                                           ░                               ░                ░       ░ 
q_1 -> 4 ───────────────────────────────────────■─────────X──■─────────X──░───────────────────────────────────────────■─────────X──░───────────────────────────────────────────░───────────────────────────────░────────────────░───────░─
                                                             │P(π/32)  │  ░                                                        ░                                           ░                               ░                ░       ░ 
q_0 -> 5 ────────────────────────────────────────────────────■─────────X──░────────────────────────────────────────────────────────░───────────────────────────────────────────░───────────────────────────────░────────────────░───────░─
                                                                          ░                                                        ░                                           ░                               ░                ░       ░ 
                                                                          

where only the first and last cp gates do not have a corresponding swap gate.

  1. In a benchmark with a 100 qubit QFT:
(main)     Took: 29.963886976242065s
(this PR) Took: 23.62939691543579s              

Which shows that this PR is about 21% faster.

@henryzou50 henryzou50 closed this Jul 25, 2024
@henryzou50 henryzou50 reopened this Jul 25, 2024
@henryzou50
Copy link
Contributor Author

@sbrandhsn Thank you for your comments and I finished adding the changes!

While doing these changes, I also made another change of changing how the swap_map of the SabreResult is handled in this case. I changed the node_id in apply_swap of star_preroute.rs to use the current node id instead of the next node id as it is more efficient, but just does not match how we normally do it in SabreSwap. This makes it so that we apply the gate first then the swap, which also fixes an error we had before where we never placed a swap gate at the end of the processing a block. This only affected tests where we had multiple blocks to process. To make sure we apply the results correctly from SabreResult, I added a flag to _apply_sabre_result to treat the case of StarPreRouting differently so that it applies the swap after applying the node.

@sbrandhsn
Copy link
Contributor

Looks good, thanks for addressing these. Yeah it is n-2 I forgot about not needing a swap gate for the first 2q-gate. :-) Do you see a scenario where a user may want to have control over apply_swap_first? I currently do not see one, so I would suggest to remove that flag and keep whatever default behavior you deem to be better. :-) This behavior is not covered by our stability policy, so I don't see an issue in changing it. :-)

Thanks for your work. I will accept the PR as soon as apply_swap_first is handled. :-)

…side

- Removed `apply_swap_first` flag in `_apply_sabre_result` as it did not make sense to have it as there are no other scenario where a user may want to have control over applying the swap first.
- To adjust for this and make `star_preroute` consistent with `apply_sabre_result` to apply swaps before the node id on the swap map, I adjusted `star_preroute.rs` to first process the blocks to gather the swap locations and the gate order. Once we have the full gate order, we can use the swap locations to apply the swaps while knowing the `qargs` of the node before the swap and the `node_id` of the node after the swap.
- Since the above in done in the main `star_preroute` function, I removed `qubit_ampping` and `out_map` as arguments for `process_blocks`.
@henryzou50
Copy link
Contributor Author

Looks good, thanks for addressing these. Yeah it is n-2 I forgot about not needing a swap gate for the first 2q-gate. :-) Do you see a scenario where a user may want to have control over apply_swap_first? I currently do not see one, so I would suggest to remove that flag and keep whatever default behavior you deem to be better. :-) This behavior is not covered by our stability policy, so I don't see an issue in changing it. :-)

Thanks for your work. I will accept the PR as soon as apply_swap_first is handled. :-)

Thanks! No, I do not see a scenario where a user may want to have control over apply_swap_first, as this should just mainly be used for SABRE. I removed the flag and reimplemented the default behavior :)

@sbrandhsn
Copy link
Contributor

LGTM! Can you resolve the merge conflict? :-) I would be happy to approve then! Thanks!

@henryzou50
Copy link
Contributor Author

LGTM! Can you resolve the merge conflict? :-) I would be happy to approve then! Thanks!

Done! Thanks :)

Copy link
Contributor

@sbrandhsn sbrandhsn left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@ElePT ElePT added this pull request to the merge queue Jul 29, 2024
@ElePT ElePT added the stable backport potential The bug might be minimal and/or import enough to be port to stable label Jul 29, 2024
Merged via the queue into Qiskit:main with commit b23c545 Jul 29, 2024
15 checks passed
mergify bot pushed a commit that referenced this pull request Jul 29, 2024
* This commit ports the core logic of `star_preroute` from Python to Rust. The changes involve creating a new Rust module for the star prerouting algorithm and updating the corresponding Python code to integrate with this new Rust functionality.

Details:
- New Rust file: Added `star_preroute.rs` to handle the core logic of the function `star_preroute` from the python side. This file defines the type aliases for node and block representations, which matches the current block representation of the `StarBlock` (except that the center is just a bool, as we only need to know if there is a center), and the node representation matches how the nodes used in `SabreDAG`. The `star_preroute` function processes the star blocks witihin the `SabreDAG`  and finds the linear routing equivalent and then returns the result as a `SabreResult`. Thus we can use the same methods we used in Sabre, such as `_build_sabre_dag` and `_apply_sabre_result`.
- Node representation: A key part of this implementation is how it takes advantage of `SabreResult` and `SabreDAG`, so the node representation is a tuple of the node id, list of qubit indices, a set of classical bit indices, and a directive flag. However, once we update the regular DAG to rust, this part may change significantly.
- Updates in the SABRE rust module: To use `sabre_dag.rs` and `swap_map.rs` in `star_prerouting`, I change them to be public in `crates/accelerate/src/sabre/mod.rs`. Not sure if it makes more sense to do it this way or to move `star_prerouting` to `crates/accelerate/src/sabre/` since it mimics the methods used in Sabre to change the dag.
- Python side updates: Imported the necessary modules and only modified the function `star_preroute` so that now the function performs the heavy lifting of transforming the DAG within the Rust space, leveraging `_build_sabre_dag` and `_apply_sabre_result`.
- Possible issues: I was not sure how correctly handle control flow from the rust side. I know that `route.rs` handles this with `route_control_flow_block` to populate the `node_block_results` for `SabreResult`, but I was not sure how to best take advantage of this function for `star_prerouting`. Currently, the `node_block_results` for `star_prerouting` essentially always empty and just there to have`SabreResult`. There also seems to be no unit tests for `star_prerouting` that includes control flow.

* lint

* Added additional test and adjust the swap map result

- Added the additional test of qft linearization and that the resultings circuit has `n-2` swap gates where `n` is the number of cp gates.
- Changed the `node_id` in `apply_swap` of `star_preroute.rs` to use the current node id as it is more efficient, but just does not match how we do it in Sabre. This makes it so that we apply the gate first then the swap, which fixes an error we had before where we never placed a swap gate at the end of the processing a block. This only affected tests where we had multiple blocks to process. To make sure we apply the results correctly from `SabreResult`, I added a flag to `_apply_sabre_result` to treat the case of `StarPrerouting` differently so that it applies the swap after applying the node.
- Added a hasp map from node to block to make processing each node in the given processing order have `n + n` time complexity instead of `n^2`. As a result, we can also remove the function `find_block_id`

* Reverted changes to `_apply_sabre_result` and fixed handling on rust side

- Removed `apply_swap_first` flag in `_apply_sabre_result` as it did not make sense to have it as there are no other scenario where a user may want to have control over applying the swap first.
- To adjust for this and make `star_preroute` consistent with `apply_sabre_result` to apply swaps before the node id on the swap map, I adjusted `star_preroute.rs` to first process the blocks to gather the swap locations and the gate order. Once we have the full gate order, we can use the swap locations to apply the swaps while knowing the `qargs` of the node before the swap and the `node_id` of the node after the swap.
- Since the above in done in the main `star_preroute` function, I removed `qubit_ampping` and `out_map` as arguments for `process_blocks`.

(cherry picked from commit b23c545)

# Conflicts:
#	crates/pyext/src/lib.rs
github-merge-queue bot pushed a commit that referenced this pull request Jul 29, 2024
* Port `star_preroute` to rust (#12761)

* This commit ports the core logic of `star_preroute` from Python to Rust. The changes involve creating a new Rust module for the star prerouting algorithm and updating the corresponding Python code to integrate with this new Rust functionality.

Details:
- New Rust file: Added `star_preroute.rs` to handle the core logic of the function `star_preroute` from the python side. This file defines the type aliases for node and block representations, which matches the current block representation of the `StarBlock` (except that the center is just a bool, as we only need to know if there is a center), and the node representation matches how the nodes used in `SabreDAG`. The `star_preroute` function processes the star blocks witihin the `SabreDAG`  and finds the linear routing equivalent and then returns the result as a `SabreResult`. Thus we can use the same methods we used in Sabre, such as `_build_sabre_dag` and `_apply_sabre_result`.
- Node representation: A key part of this implementation is how it takes advantage of `SabreResult` and `SabreDAG`, so the node representation is a tuple of the node id, list of qubit indices, a set of classical bit indices, and a directive flag. However, once we update the regular DAG to rust, this part may change significantly.
- Updates in the SABRE rust module: To use `sabre_dag.rs` and `swap_map.rs` in `star_prerouting`, I change them to be public in `crates/accelerate/src/sabre/mod.rs`. Not sure if it makes more sense to do it this way or to move `star_prerouting` to `crates/accelerate/src/sabre/` since it mimics the methods used in Sabre to change the dag.
- Python side updates: Imported the necessary modules and only modified the function `star_preroute` so that now the function performs the heavy lifting of transforming the DAG within the Rust space, leveraging `_build_sabre_dag` and `_apply_sabre_result`.
- Possible issues: I was not sure how correctly handle control flow from the rust side. I know that `route.rs` handles this with `route_control_flow_block` to populate the `node_block_results` for `SabreResult`, but I was not sure how to best take advantage of this function for `star_prerouting`. Currently, the `node_block_results` for `star_prerouting` essentially always empty and just there to have`SabreResult`. There also seems to be no unit tests for `star_prerouting` that includes control flow.

* lint

* Added additional test and adjust the swap map result

- Added the additional test of qft linearization and that the resultings circuit has `n-2` swap gates where `n` is the number of cp gates.
- Changed the `node_id` in `apply_swap` of `star_preroute.rs` to use the current node id as it is more efficient, but just does not match how we do it in Sabre. This makes it so that we apply the gate first then the swap, which fixes an error we had before where we never placed a swap gate at the end of the processing a block. This only affected tests where we had multiple blocks to process. To make sure we apply the results correctly from `SabreResult`, I added a flag to `_apply_sabre_result` to treat the case of `StarPrerouting` differently so that it applies the swap after applying the node.
- Added a hasp map from node to block to make processing each node in the given processing order have `n + n` time complexity instead of `n^2`. As a result, we can also remove the function `find_block_id`

* Reverted changes to `_apply_sabre_result` and fixed handling on rust side

- Removed `apply_swap_first` flag in `_apply_sabre_result` as it did not make sense to have it as there are no other scenario where a user may want to have control over applying the swap first.
- To adjust for this and make `star_preroute` consistent with `apply_sabre_result` to apply swaps before the node id on the swap map, I adjusted `star_preroute.rs` to first process the blocks to gather the swap locations and the gate order. Once we have the full gate order, we can use the swap locations to apply the swaps while knowing the `qargs` of the node before the swap and the `node_id` of the node after the swap.
- Since the above in done in the main `star_preroute` function, I removed `qubit_ampping` and `out_map` as arguments for `process_blocks`.

(cherry picked from commit b23c545)

# Conflicts:
#	crates/pyext/src/lib.rs

* Update lib.rs

* Update crates/pyext/src/lib.rs

---------

Co-authored-by: Henry Zou <87874865+henryzou50@users.noreply.github.com>
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
Procatv pushed a commit to Procatv/qiskit-terra-catherines that referenced this pull request Aug 1, 2024
* This commit ports the core logic of `star_preroute` from Python to Rust. The changes involve creating a new Rust module for the star prerouting algorithm and updating the corresponding Python code to integrate with this new Rust functionality.

Details:
- New Rust file: Added `star_preroute.rs` to handle the core logic of the function `star_preroute` from the python side. This file defines the type aliases for node and block representations, which matches the current block representation of the `StarBlock` (except that the center is just a bool, as we only need to know if there is a center), and the node representation matches how the nodes used in `SabreDAG`. The `star_preroute` function processes the star blocks witihin the `SabreDAG`  and finds the linear routing equivalent and then returns the result as a `SabreResult`. Thus we can use the same methods we used in Sabre, such as `_build_sabre_dag` and `_apply_sabre_result`.
- Node representation: A key part of this implementation is how it takes advantage of `SabreResult` and `SabreDAG`, so the node representation is a tuple of the node id, list of qubit indices, a set of classical bit indices, and a directive flag. However, once we update the regular DAG to rust, this part may change significantly.
- Updates in the SABRE rust module: To use `sabre_dag.rs` and `swap_map.rs` in `star_prerouting`, I change them to be public in `crates/accelerate/src/sabre/mod.rs`. Not sure if it makes more sense to do it this way or to move `star_prerouting` to `crates/accelerate/src/sabre/` since it mimics the methods used in Sabre to change the dag.
- Python side updates: Imported the necessary modules and only modified the function `star_preroute` so that now the function performs the heavy lifting of transforming the DAG within the Rust space, leveraging `_build_sabre_dag` and `_apply_sabre_result`.
- Possible issues: I was not sure how correctly handle control flow from the rust side. I know that `route.rs` handles this with `route_control_flow_block` to populate the `node_block_results` for `SabreResult`, but I was not sure how to best take advantage of this function for `star_prerouting`. Currently, the `node_block_results` for `star_prerouting` essentially always empty and just there to have`SabreResult`. There also seems to be no unit tests for `star_prerouting` that includes control flow.

* lint

* Added additional test and adjust the swap map result

- Added the additional test of qft linearization and that the resultings circuit has `n-2` swap gates where `n` is the number of cp gates.
- Changed the `node_id` in `apply_swap` of `star_preroute.rs` to use the current node id as it is more efficient, but just does not match how we do it in Sabre. This makes it so that we apply the gate first then the swap, which fixes an error we had before where we never placed a swap gate at the end of the processing a block. This only affected tests where we had multiple blocks to process. To make sure we apply the results correctly from `SabreResult`, I added a flag to `_apply_sabre_result` to treat the case of `StarPrerouting` differently so that it applies the swap after applying the node.
- Added a hasp map from node to block to make processing each node in the given processing order have `n + n` time complexity instead of `n^2`. As a result, we can also remove the function `find_block_id`

* Reverted changes to `_apply_sabre_result` and fixed handling on rust side

- Removed `apply_swap_first` flag in `_apply_sabre_result` as it did not make sense to have it as there are no other scenario where a user may want to have control over applying the swap first.
- To adjust for this and make `star_preroute` consistent with `apply_sabre_result` to apply swaps before the node id on the swap map, I adjusted `star_preroute.rs` to first process the blocks to gather the swap locations and the gate order. Once we have the full gate order, we can use the swap locations to apply the swaps while knowing the `qargs` of the node before the swap and the `node_id` of the node after the swap.
- Since the above in done in the main `star_preroute` function, I removed `qubit_ampping` and `out_map` as arguments for `process_blocks`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: transpiler Issues and PRs related to Transpiler performance Rust This PR or issue is related to Rust code in the repository stable backport potential The bug might be minimal and/or import enough to be port to stable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Port StarPrerouting to Rust
6 participants