Skip to content

Port the PadDynamicalDecoupling pass from Python to Rust. #14735

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

velocityraptor7085
Copy link
Contributor

@velocityraptor7085 velocityraptor7085 commented Jul 15, 2025

Summary

Details and comments

  • Updates the _pad method (in qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py) to call a rust routine instead.

  • The reason that the _pad method is updated is that it is the core logic that runs when the pass is called, and the run method in BasePadding (defined in qiskit/transpiler/passes/scheduling/padding/base_padding.py) calls it for both PadDynamicalDecoupling as well as PadDelay. Hence, it would make more sense to fully port the run method once the _pad of PadDelay is also implemented in rust (as per Port PadDelay to Rust #12266).

  • Note: This is currently opened as a draft PR since the current implementation fails the test cases. I would appreciate it if any suggestions/comments can be provided as to what may be wrong here. Thank you.

…to rust. The _pad method is the core logic that is called during the pass, whereas the run method would need to be ported along with the PadDelay pass, since it is defined in the BasePadding class.
@qiskit-bot qiskit-bot added the Community PR PRs from contributors that are not 'members' of the Qiskit repo label Jul 15, 2025
@raynelfss raynelfss added Rust This PR or issue is related to Rust code in the repository Intern PR PR submitted by IBM Quantum interns mod: transpiler Issues and PRs related to Transpiler and removed Community PR PRs from contributors that are not 'members' of the Qiskit repo labels Jul 17, 2025
Comment on lines 863 to 868
pub fn index(&self) -> usize {
match &self.0 {
BitInfo::Owned { index, .. } => *index as usize,
BitInfo::Anonymous { .. } => panic!("Anonymous qubit has no index"),
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Having this panic may be a bit extreme, remember that a panic is an unrecoverable error. Perhaps having this method return an Option<usize> might be better since the user would be able to easily handle a case where an index doesn't exist.

Copy link
Contributor

Choose a reason for hiding this comment

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

Curious if we really need this index method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kevinhartman I just thought that it would be useful to have in general, and would make the code easier to understand if the internal implementation details of the Owned and Anonymous variants of BitInfo are abstracted away in passes like this.

Copy link
Contributor

@kevinhartman kevinhartman left a comment

Choose a reason for hiding this comment

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

Looks good so far.

Just adding a couple of comments from our discussion earlier this week so we can keep track of them.

} else if extra_slack_distribution == "edges" {
let to_begin_edge: f64 = constrained_length_scalar(alignment as f64, extra_slack / 2.0);
taus[0] += to_begin_edge;
taus[taus_len - 1] = extra_slack - to_begin_edge;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
taus[taus_len - 1] = extra_slack - to_begin_edge;
taus[taus_len - 1] += extra_slack - to_begin_edge;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch. I'll apply the suggestion 👍


let node_start_time_obj = property_set.get_item("node_start_time")?;
let node_start_time_dict = node_start_time_obj.downcast::<PyDict>()?;
let start_time_opt = node_start_time_dict.del_item(prev_node).ok();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think del_item does not actually return anything, so start_time_opt might actually be () here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yes, that's right. I should get it first, then delete it afterwards 👍.

Comment on lines +223 to +227
next_node_inst.params = smallvec![
Param::Float(theta_new),
Param::Float(phi_new),
Param::Float(lam_new),
];
Copy link
Contributor

Choose a reason for hiding this comment

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

This likely won't work, since a CircuitInstruction on a DAGNode would be ephemeral (I think). You might need to replace the node in the DAG instead for this to work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, thanks for pointing this out. I'll go ahead and re-implement it to replace the node instead 👍.

@velocityraptor7085
Copy link
Contributor Author

  • Thank you for your comments @kevinhartman and @raynelfss.
  • There are some panicking test cases which I have to inspect deeper and fix.
  • However, I don't understand how some of the circuit comparison tests are failing. For example, I've attached a screenshot of the fail message for the test case: test.python.transpiler.test_dynamical_decoupling.TestPadDynamicalDecoupling.test_asymmetric_xy4_in_t2. It displays the 2 circuits which seem identical to me, and I even printed out the matrix representation of the circuit operator which is also the same. I would appreciate any help on this matter and how I can take this forward 🙂
Screenshot 2025-07-23 at 10 26 07 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Intern PR PR submitted by IBM Quantum interns mod: transpiler Issues and PRs related to Transpiler Rust This PR or issue is related to Rust code in the repository
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Port PadDynamicalDecoupling to Rust
4 participants