11. CLI and integration
11.1 CLI tool (cli.py)
For quick experimentation without writing Python, the package ships a command-line tool:
The CLI is essentially a thin wrapper over Optimizer. It supports two ways of specifying the phase vector:
- Provide
--vec-json path/to/file.json, where the JSON file contains a list of integers (a \(\mathbb{Z}_8\) vector of length \(2^n - 1\)). - Or ask it to generate a synthetic vector in-process using
--genand related options.
Key arguments:
--decoder– one ofdumer,dumer-list,rpa,ml-exact, orauto(default). These are passed directly to theOptimizerconstructor.--effort– integer effort level (default 3) that controls beam size and RPA parameters, just like in the Python API.--n– number of qubits (default 6).--vec-json– path to a JSON file with a list of integers.--gen– synthetic generator:near1,rand_sparse, orrand_z8.--flips,--density,--seed– parameters for the synthetic generators.--json– optional path to a JSON report file.
The core logic is:
- Load or generate a
vecviagen_vec. - Build the original circuit with
synthesize_from_coeffs(vec, n). - Construct an
Optimizer(decoder=args.decoder, effort=args.effort). - Call
opt.optimize(circ)to getnew_circ,rep. - Print:
- Decoder, effort, n.
- T-before, T-after, distance.
- The actual decoder strategy used internally (
opt.last_decoder_used), which matters ifdecoder="auto".
If --json is provided, it writes a JSON object with basic fields:
{
"decoder": "...",
"effort": 3,
"n": 6,
"before_t": 32,
"after_t": 18,
"distance": 14,
"strategy": "...",
"selected_monomials": [...],
"signature": "..."
}
11.2 rmcore loader (rmcore.py)
While decoders._load_rmcore() tries to find the compiled extension in several ways, rmcore.py provides a more structured import mechanism for the package namespace rmsynth.rmcore.
The logic is:
_find_binary_path():
- Inspects the package directory (
os.path.dirname(__file__)) for files whose names start withrmcoreand end with any of the extension suffixes known to Python (.so,.pyd, etc.). - Scans each directory in
sys.pathfor armsynthsubdirectory and looks there for such files. - Deduplicates candidates and sorts them by modification time, choosing the newest one.
_load_as_rmcore(path):
- Creates an
ExtensionFileLoaderandModuleSpecfor the name"rmsynth.rmcore". - Loads and executes the binary extension from
path, effectively calling itsPyInit_rmcore.
Finally, at import time:
_path = _find_binary_path()is evaluated.- If
_pathisNone, anImportErroris raised with a clear message: “Compiled rmcore extension not found … Please build/install the project first, e.g.:pip install -v .” - If
_pathis found,_mod = _load_as_rmcore(_path)is created, andsys.modules[__name__]is replaced with that module. This means that importingrmsynth.rmcoregives direct access to the compiled functions, just like a normal extension.
This loader is complementary to _load_rmcore() in decoders.py, which tries several import patterns but falls back gracefully to pure‑Python decoding if the extension cannot be found. Together they allow both “installed package” and “local build” workflows.