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.