Python API¶
Besides the intended usage from C++, libqasm also has a (comparatively
simplistic) Python interface, installable via the
libqasm PyPI package or using
pip3 install -v -e .
(or equivalent) from the root directory of the
repository. This exposes two modules, libQasm
and cqasm.v1
. The
former exists for backward compatibility with the original Python API,
and supports only cQASM 1.0 and the default instruction set. The latter
supports up to cQASM 1.2, mirroring the C++ API.
Documentation is unfortunately scarce, as the Python interface has not been a priority compared to the C++ interface. The new API is rather straightforward, however. This should hopefully get you started:
import cqasm.v1
analyzer = cqasm.v1.Analyzer('1.2')
result = a.analyze_string('version 1.2; qubits 3; x q[0]')
The argument passed to the Analyzer()
constructor specifies the API version
that your application supports. This version follows the cQASM file versions.
This ensures that you don’t get problems when a new version of libqasm comes
out that supports a newer version; if the user then passes a file that’s too
new, they get an error message stating the maximum version, rather than a
cryptic error down the line when your application receives something from
libqasm that it doesn’t understand.
The Analyzer()
has an optional second argument, too. This is a boolean,
named without_defaults
, defaulting to False
. When set to True
, the
process that registers the default instruction set and error models with the
analyzer is skipped. You can then add instructions to the instruction set using
the register_instruction()
method:
Analyzer.register_instruction(
name,
param_types='',
allow_conditional=True,
allow_parallel=True,
allow_reused_qubits=False,
allow_different_index_sizes=False
)
The param_types
argument specifies the allowed operand types for the
instruction. Each character represents an operand:
Q
= qubit;B
= assignable bit/boolean (measurement register);b
= bit/boolean;a
= axis (x, y, or z);i
= integer;r
= real;c
= complex;u
= complex matrix of size 4^n, where n is the number of qubits in the parameter list (automatically deduced);s
= (quoted) string;j
= json.
The rest of the parameters should be fairly obvious.
It is also possibly to disable the default instruction set and not add any instructions. In this case – rather than rejecting all cQASM files – libqasm will accept any instruction with any operand list, allowing you to do instruction set management yourself.
You can register error models in much the same way, if you want:
Analyzer.register_error_model(
name,
param_types=''
)
Besides analyze_string(data)
, the Analyzer
class also has
analyze_file(filename)
, parse_string(data)
, and parse_file(filename)
variants. The difference between *_string
and *_file
should be obvious;
the difference between analyze_*
and parse_*
is that the former runs
the complete analysis process, while the latter gives you the raw parse result.
You’ll almost always want the former.
The result of these functions is either a list of error messages or a tree
structure. The tree structure is quite involved, but also very easy to traverse
once you have one in Python. Simply print the value to get a multiline,
pretty-printed representation of the (sub)tree. Tree access (or manipulation,
if you want) is then done via the usual Python operators (.
for field
access, []
for indexing into lists, and so on).
Some additional information may be available via the C++ documentation here. Note however that some stuff here may be inaccurate or incomplete, as it only documents the C++ portion, and some Python stuff is added on top to make the interface more Pythonic. This unfortunately does not have generated documentation at this time.