-
Notifications
You must be signed in to change notification settings - Fork 2
Tips and Tricks
At present, our core interface for user programs to bind to is the Helios QIS. The user's program calls the functions defined in the header file provided by the bundled helios_qis interface, and these functions are implemented as wrappers over the selene-native interface.
Sometimes during development of new features in selene or a connected project, program flow might not work as expected. For example, when implementing measure_leaked I ran into an issue where a measure pipeline was being triggered instead. Debugging this using the default output can be difficult.
However, one can add diagnostic logging to the helios_qis -> selene interface. While the default interface avoids logging for obvious performance reasons, additional implementations are provided for debug usage. Here's how to use them:
from selene_helios_qis_plugin import HeliosInterface, LogLevel
# ...
runner = build(
your_program,
interface=HeliosInterface(log_level=LogLevel.DIAGNOSTIC),
build_dir="/tmp/selene_debug" # example
)When you invoke the runner's run or run_shots functions, the build directory gains a new entry in /tmp/selene_debug/runs. The stderr of a run will now be populated with information about every call issued by the user program, and any return values provided:
[interface] diagnostic: selene_init() with args:
[interface] diagnostic: 0: /tmp/debug/artifacts/program.selene.x
[interface] diagnostic: 1: --configuration
[interface] diagnostic: 2: /tmp/thing/runs/0001/configuration.yaml
[interface] diagnostic: Number of shots: 50
[interface] diagnostic: Starting shot 0
[interface] diagnostic: ----------------------------
[interface] diagnostic: setup(0)
[interface] diagnostic: set_tc(0)
[interface] diagnostic: [done]
[interface] diagnostic: ___qalloc()
[interface] diagnostic: address: 0
[interface] diagnostic: ___reset(0)
[interface] diagnostic: [done]
[interface] diagnostic: ___rxy(0, 1.570796, -1.570796)
[interface] diagnostic: [done]
[interface] diagnostic: ___rz(0, 3.141593)
[interface] diagnostic: [done]
...
[interface] diagnostic: ___lazy_measure_leaked(0)
[interface] diagnostic: reference: 0
[interface] diagnostic: ___qfree(0)
[interface] diagnostic: [done]
[interface] diagnostic: ___inc_future_refcount(0)
[interface] diagnostic: [done]
[interface] diagnostic: ___read_future_uint(0)
[interface] diagnostic: returned 2
[interface] diagnostic: ___dec_future_refcount(0)
[interface] diagnostic: [done]
[interface] diagnostic: ___dec_future_refcount(0)
[interface] diagnostic: [done]
[interface] diagnostic: print_int("USER:INT:head_leaked", 1)
[interface] diagnostic: [done]
If you modify selene's rust code, or that of a plugin, to emit diagnostics information to stderr, they will also appear in the run's stderr file, and the two aspects can provide additional context for eachother. Here is an example while I was print-debugging a simple leakage model:
[interface] diagnostic: ___rxy(7, -1.570796, 1.570796)
Random value for leakage: 0.048205655355746946
[interface] diagnostic: [done]
[interface] diagnostic: ___rzz(0, 7, 1.570796)
Random value for leakage: 0.0015259836437150343
Qubit 0 leaked
Qubit 0 set to leaked
Random value for leakage: 0.9660562144157374
Qubit 7 set to leaked
[interface] diagnostic: [done]
...
[interface] diagnostic: ___read_future_uint(0)
[interface] diagnostic: returned 2
[interface] diagnostic: ___dec_future_refcount(0)
[interface] diagnostic: [done]
[interface] diagnostic: ___dec_future_refcount(0)
[interface] diagnostic: [done]
[interface] diagnostic: print_int("USER:INT:head_leaked", 1)
[interface] diagnostic: [done]