Skip to content

[Feature]: Auto keep-alive for always-on / sticky elements #136

Description

@JacobFastQM

Feature Description

A general keep-alive mechanism for "always-on" sticky elements so they stay asserted for the whole program without a per-component manual call that will be usable by gate level users.

Problem Statement

This is a more featureful extension of a bugfix for #123.

The merged keep-alive primitive BaseQuam.twpa_keepalive() (#135) requires the user to call it once per loop iteration in a hand-written QUA program. That's fine for pulse-level users but breaks down for gate-level / circuit-compilation use cases.

For those more abstract level users who don't write bare QUA, there's no point in their code to call it. Users also shouldn't have to know a TWPA is a sticky element that decays. Finally, the bugfix manual solution adds increasing complexity to the stack. Each new always-on component adds another "remember to keep this alive" rule, with nothing enforcing it, and the list grows with the library and user base.

Proposed Solution

A registry behind one keep_sticky_alive() base method. Components opt in by declaring the elements they need re-asserted; BaseQuam collects them by walking the QUAM tree and re-asserts all of them in a single align().

# a component opts in by declaring its sticky element(s), scoped to the qubits in use:
component.keepalive_elements(qubits) -> [element names]

# BaseQuam gains one method:
keep_sticky_alive(qubits = active_qubits):
    elements = collect keepalive_elements(qubits)
               from every always-on component in the QUAM tree
    if elements:
        align(elements + channels of qubits)

# twpa_keepalive() becomes a thin alias of keep_sticky_alive() 

Auto-injection per shot. Whatever generates the shot loop inserts the call once per iteration.

# near-term: a loop helper owns the for_ and injects the call
shot_loop(n_shots, qubits):
    with for_(... n_shots ...):
        keep_sticky_alive(qubits)
        yield                      # user's per-shot body runs here

# long-term: the circuit->QUA compiler emits it when it builds the shot loop
with for_(shot in n_shots):
    keep_sticky_alive(active_qubits)
    <compiled circuit>

Alternatives Considered

Explicit manual calls as twpa_keepalive but as noted above, this is not a workable solution for gate level users.

Example Usage

Today, manual:

with for_(n, 0, n < n_avg, n + 1):
    machine.twpa_keepalive([q1])
    # gates / measure ...

With this feature, handwritten qua automatic:

for n in machine.shot_loop(n_avg, qubits=[q1]):
    # gates / measure ...   keep-alive handled automatically

With this feature, gate-level (compiler owns the loop; user writes no QUA):

results = machine.run(circuit, n_shots=1000)   # keep_sticky_alive injected per shot internally

Priority

Important

Additional Context

Confirmed one call per shot is sufficient via simulation on hardware: the sticky hold carries the element through the rest of the iteration, and it holds across nested loops and conditionals, so auto-injection is a single line where the loop is emitted, with no interleaving among gates. Align must include always on elements + active qubits channels.

Checklist

  • I have searched existing issues to ensure this feature hasn't been requested before
  • I have checked the documentation to see if this feature already exists
  • I am willing to help implement this feature (optional)

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions