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

Context-aware dynamical decoupling #12825

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

Conversation

Cryoris
Copy link
Contributor

@Cryoris Cryoris commented Jul 26, 2024

Summary

Implement context-aware dynamical decoupling (DD) from arXiv:2403.06852.

Details and comments

When selecting decoupling sequences for an idle qubit, context-aware DD takes into account what actions are occuring on neighboring qubits. It ensures that neighboring sequences are mutually orthogonal (to avoid collisions, like in staggered DD) but also whether the qubit is a CX or ECR target/control spectator. This is nicely summarized in a figure of the paper, where the different wire colors denote different decoupling sequences:

image

This particularly leads to improvement if a lot of qubits are idle at the same time or if they are next to ECR/CX gates. One important category of circuits in this class are the layers in twirled circuits. This pass also works best if the ECR/CX gate times are the same for all connections, which is almost always the case on IBM devices.

Some simple experiments show that this pass performs better than the current standard in Qiskit, PadDynamicaDecoupling with an X-X sequence. Here's some basic benchmarks, see the paper for more:

image

This code is based off @kdk and @ajavadia 🙂

Cryoris and others added 3 commits July 26, 2024 14:48
Co-authored-by: Kevin Krsulich <[email protected]>
Co-authored-by: Ali Javadi <[email protected]>
@Cryoris Cryoris added Changelog: New Feature Include in the "Added" section of the changelog mod: transpiler Issues and PRs related to Transpiler labels Jul 26, 2024
@Cryoris Cryoris added this to the 1.3 beta milestone Jul 26, 2024
@Cryoris Cryoris requested a review from a team as a code owner July 26, 2024 14:59
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Jul 30, 2024

Pull Request Test Coverage Report for Build 11685932835

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

  • 332 of 355 (93.52%) changed or added relevant lines in 4 files are covered.
  • 30 unchanged lines in 5 files lost coverage.
  • Overall coverage increased (+0.03%) to 88.802%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py 329 352 93.47%
Files with Coverage Reduction New Missed Lines %
crates/accelerate/src/unitary_synthesis.rs 1 92.2%
qiskit/primitives/backend_sampler_v2.py 2 98.53%
crates/qasm2/src/lex.rs 6 91.98%
qiskit/primitives/backend_estimator.py 9 96.12%
crates/qasm2/src/parse.rs 12 97.15%
Totals Coverage Status
Change from base Build 11669445061: 0.03%
Covered Lines: 77120
Relevant Lines: 86845

💛 - Coveralls

done as the functions use data already available in the class-context, so we can avoid redundant passing of variables
@mtreinish mtreinish modified the milestones: 1.3 beta, 1.3.0 Aug 1, 2024
@miamico
Copy link
Contributor

miamico commented Oct 18, 2024

Anything holding this up from being merged? Happy to lend a hand if needed to speed up the process @Cryoris @eliarbel

Copy link
Contributor

@eliarbel eliarbel left a comment

Choose a reason for hiding this comment

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

Thanks Julien, overall seems well written and documented. I didn't read the paper so the review is not about the actual algorithmic part of the DD method itself. I suggest getting input from Kevin or Ali if you want another pair of eyes on this aspect.
I've left line comments, most of which are minor but still require addressing.
In terms of performence - do you have a sense about the overhead of the block collection and manipulation (e.g. _collect_adjacenet_delay_blocks )?

qiskit/transpiler/passes/__init__.py Show resolved Hide resolved
test/python/transpiler/test_context_aware_dd.py Outdated Show resolved Hide resolved
test/python/transpiler/test_context_aware_dd.py Outdated Show resolved Hide resolved
if len(closed_delay.active_qubits) > 0:
raise RuntimeError("Failed remove active qubits on closed delays.")

if validate:
Copy link
Contributor

Choose a reason for hiding this comment

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

There are several validation checks across the code. I suggest enabling and using them in test_context_aware_dd.py

Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Thanks @Cryoris, as you know I have ran this pass and noticed a few painpoints I wanted to point out. In addition to the documentation suggestions, I have noticed that min_joinable_duration is a key parameter to avoid 1q gate explosion in some circuits, I wonder if you had considered setting it no a non-0 default value?

Comment on lines +113 to +115
min_joinable_duration: Do not join delays with others below this duration. This
can be useful, e.g. if a big delay block would be interrupted and split into
smaller blocks due to a very short, adjacent delay.
Copy link
Contributor

Choose a reason for hiding this comment

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

I would find it very helpful if the documentation mentioned something that could be linked easier to "minimal delay time" and what units are used, something like (I still find it a bit clunky):

Suggested change
min_joinable_duration: Do not join delays with others below this duration. This
can be useful, e.g. if a big delay block would be interrupted and split into
smaller blocks due to a very short, adjacent delay.
min_joinable_duration: Minimal duration to join delays (in dt units). Do not join delays with
others below this duration . This can be useful, e.g. if a big delay block would be interrupted
and split into smaller blocks due to a very short, adjacent delay.

can be useful, e.g. if a big delay block would be interrupted and split into
smaller blocks due to a very short, adjacent delay.
skip_reset_qubits: Skip initial delays and delays after a reset.
skip_dd_threshold: Skip dynamical decoupling on an idle qubit, if the duration of
Copy link
Contributor

Choose a reason for hiding this comment

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

In what units is skip_dd_threshold? I have noticed that min_joinable_duration is an int but this one is a float, so maybe it's not dt?

Comment on lines +120 to +123
pulse_alignment: The hardware constraints for gate timing allocation.
This is usually provided om ``backend.configuration().timing_constraints``.
If provided, the delay length, i.e. ``spacing``, is implicitly adjusted to
satisfy this constraint. If ``None``, this is extracted from the ``target``.
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment about units

Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Another comment, I believe there is a bug in the instruction duration assignation, because the timeline drawer fails after running this pass complaining about missing gate durations:

Traceback (most recent call last):
  File "/Users/ept/qiskit_workspace/qiskit/debug_dd.py", line 84, in <module>
    timeline_drawer(bound_scheduled_circuit, filename="out.png")
  File "/Users/ept/qiskit_workspace/qiskit/qiskit/utils/deprecation.py", line 183, in wrapper
    return func(*args, **kwargs)
  File "/Users/ept/qiskit_workspace/qiskit/qiskit/utils/deprecation.py", line 183, in wrapper
    return func(*args, **kwargs)
  File "/Users/ept/qiskit_workspace/qiskit/qiskit/visualization/timeline/interface.py", line 379, in draw
    canvas.load_program(program=program)
  File "/Users/ept/qiskit_workspace/qiskit/qiskit/visualization/timeline/core.py", line 193, in load_program
    for datum in gen(gate_source, formatter=self.formatter):
  File "/Users/ept/qiskit_workspace/qiskit/qiskit/visualization/timeline/generators.py", line 158, in gen_sched_gate
    if gate.duration > 0:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

@raynelfss raynelfss modified the milestones: 1.3.0, 2.0.0 Nov 7, 2024
Copy link
Contributor

@eliarbel eliarbel left a comment

Choose a reason for hiding this comment

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

Thanks @Cryoris for applying all the changes. This looks good and I have no further comments. There are still some comments from @ElePT.

Copy link
Contributor

@eliarbel eliarbel left a comment

Choose a reason for hiding this comment

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

Fine from my side. Please address the remaining comments from @ElePT

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
Projects
None yet
Development

Successfully merging this pull request may close these issues.