Skip to content

Reference: Async Read

AsyncReadResult Class

psiqworkbench.AsyncReadResult

AsyncReadResult(qc, start_flag=None, bitflags=None, read_mask=None, qint=None, target_xor=0, resolved_value=None, warning_str=None, held_ops=None, fallback_read=None)

AsyncReadResult is the type returned by qc.read_async() and qc.ppm_async(). It provides a "flag" which has not been evaluated.

WITHOUT read_async(), you'd normally do things like this:

Synchronous (stalled) reading:

    result = myqubit.read()
    if result:
        do_something()

    if myqubit.read():
        do_something()

    r1 = myq1.read()
    r2 = myq2.read()
    r3 = myq3.read()
    if r1 and r2 and not r3:
        do_something()
This is nice and flexible, but it requires the Python interpreter to pause while the QPU compiles and executes all of its instructions until this measurement has been performed.

To use measurements without stalling, we can treat measured qubits as classical conditions:

    myq1.read()
    myq2.hadamard(myq1)
    myq2.x(myq1)

This works, but it's not very flexible and has a few catches. The biggest problem is that if the "condition" qubit is re-used for something else you can no longer use it as a condition.

WITH read_async() you have more options:

  1. Call .resolve(), which is the simplest and slowest way to get the result. This causes the program to stall until the QPU has performed the corresponding measurement and can return the result.

        flag = myqubit.read_async()
        if flag.resolve():
            do_something()
    
        flag = myqubit.read()
        if int(flag):
            do_something()
    
  2. Leave the flag unresolved, and use it in a with block instead of an if. This avoids stalling the pipe; any QPU ops inside the with block will be marked with the flag so they only execute if the flag resolves as true.

        flag = myqubit.read_async()
        with flag:
            do_something()
    
        with myqubit.read_async():
            do_something()
    
        r1 = myq1.read_async()
        r2 = myq2.read_async()
        r3 = myq3.read_async()
        with r1 and r2 and not r3:
            do_something()
    
  3. Attach the flag to QPU instructions. While it's not as nice syntactically, the flag can be attached to QPU instructions, so they'll only execute if that measurement resolves as true.

        flag = myq1.read_async()
        myq2.hadamard(if_flag=flag)
        myq2.x(if_flag=flag)
    

In all of these cases, the dependent QPU ops are allowed to be issued (or not issued) in a deferred manner, without causing stalls.

Parameters:

Name Type Description Default
qc QPU

The QPU instance associated with this result.

required
start_flag int

The starting flag index for this result.

None
bitflags list

A list of bitflags associated with this result.

None
read_mask int

A mask identifying which qubits are read.

None
qint Qubits

The quantum integer involved in this result.

None
target_xor int

XOR values for the result's target.

0
resolved_value int

The resolved value of this result, if known.

None
warning_str str

A warning message associated with this result.

None
held_ops list

A list of held operations for deferred execution.

None

get_bool_flag

get_bool_flag()

Make a deferred flag equivalent to "!= 0".

get_flag

get_flag(flag_index)

Get a flag by index value (not bit position).

set_flag

set_flag(flag_index, new_flag_value)

Set a flag by index value (not bit position).

get_held_ops

get_held_ops()

Return any currently-held ops.

resolve

resolve(force=False, as_index_list=False)

Stall until this result has been resolved, and cache the result. If force is True, re-resolve instead of using the cached result.