CLI reference¶
Installing QQA4CO registers a single console script:
The CLI is a thin argparse layer over the public Python API and does not add
dependencies beyond those required by the selected backend. For a
quick "what does this flag do?" prefer qqa <subcommand> --help; this
page is the explanation of how the flags interact.
qqa version¶
Prints the value of qqa.__version__, which is single-sourced from
the wheel metadata via importlib.metadata. Use this to verify the
installed version inside a Docker container or a CI job.
qqa inspect and qqa plan¶
qqa inspect model.mps
qqa plan model.mps --profile quality --budget 60s --device auto
qqa doctor model.mps --replicas 128 --json
inspect emits solver-independent structure. plan previews the selected
QQA route, repair, optional exact backend, replica count, memory estimate, and
fallbacks without spending the solve budget.
doctor MODEL additionally checks bounds, factor capabilities, scaling,
curvature, contradictions, decomposition, proof routes, and resource
estimates. qqa doctor without a model retains the local installation/device
diagnostic.
qqa solve¶
The main subcommand. A positional model file uses the stable qqa.solve API;
the legacy catalogue flags remain available for compatibility.
Common flags¶
| Flag | Default | What it does |
|---|---|---|
positional MODEL |
(none) | MPS, LP, QPLIB, JSON ModelIR, OPB, CNF/WCNF, QUBO, or Ising file |
--profile |
balanced |
fast, balanced, quality, certify/prove, diverse, pareto, or reproducible |
--budget |
(none) | Total wall-clock duration such as 250ms, 30s, 2m, or 0.5h |
--problem |
(none) | Built-in catalogue problem used when positional MODEL is omitted |
--problem-file |
(none) | Trusted local Python file defining problem or make_problem(); requires --allow-unsafe-python |
--graph-file |
(none) | GraphML / edgelist NetworkX graph; pickle additionally requires --allow-unsafe-python |
--allow-unsafe-python |
off | Explicitly permit local Python execution or pickle deserialization; never use for untrusted input |
--size |
50 |
Size for synthetic problem generators |
--sol-size |
profile / 100 |
Parallel population size; positional models use the profile, while the legacy catalogue defaults to 100 |
--epochs |
profile / 1000 |
Solver steps; positional models use the profile, while the legacy catalogue defaults to 1000 |
--schedule |
profile / linear |
QQA schedule; positional models use the profile and the legacy catalogue retains linear scheduling |
--device |
auto |
auto chooses CUDA → MPS → CPU; explicit cpu, cuda, cuda:0, mps also work |
--seed |
0 |
Seed passed to qqa.fix_seed |
--quiet |
off | Suppress per-epoch progress logs |
--output |
(none) | If given, pickle the full AnnealResult to this path |
--report |
(none) | Write a self-contained interactive HTML diagnostic report |
Hyper-parameter flags¶
| Flag | Default | What it does |
|---|---|---|
--learning-rate |
backend-aware (1.0 for qqa, 1e-4 for pignn/cpra) |
AdamW learning rate |
--temp |
0.0 |
Langevin noise temperature (0 = no noise) |
--min-bg / --max-bg |
-2.0 / 0.1 |
Linear schedule endpoints |
--curve-rate |
2 |
QQA penalty exponent (must be even) |
--div-param |
0.0 |
Cross-replica diversity weight (0 = off) |
--restart-patience |
250 |
Replace weak QQA replicas after this many epochs without an incumbent improvement; 0 disables |
--restart-fraction |
0.15 |
Fraction of weak replicas replaced at each recovery event |
--restart-jitter |
0.10 |
Local latent jitter around the incumbent for half of restarted replicas |
--gradient-clip |
100 |
Global latent-gradient norm cap; 0 disables |
Backend flags¶
| Flag | Default | What it does |
|---|---|---|
--backend |
qqa |
qqa, sa, pa, isco, scip, pignn, or cpra |
--exact-backend |
auto |
Positional models only: none, scip, highs, cpsat, or cuopt; execution remains opt-in |
--scip-time-limit / --scip-gap |
60 / 0 |
Total QQA+SCIP wall-clock budget and target relative gap |
--scip-warm-starts / --scip-threads |
32 / 1 |
Diverse QQA incumbents and exact-solver threads |
--pignn-init-reg-param |
-20.0 |
CRA initial γ (only --backend pignn/cpra) |
--pignn-annealing-rate |
1e-3 |
CRA γ increment per epoch |
--pignn-tol / --pignn-patience |
1e-4 / 1000 |
Early-stopping (loss-stagnation) |
--pignn-hidden |
√N | GCN hidden width |
--pignn-no-annealing |
off | Run vanilla PI-GNN (γ ≡ 0) instead of CRA-style annealing |
--cpra-num-replicas |
4 |
Number of CPRA heads R |
--cpra-vari-param |
0.0 |
CPRA variation-diversification weight |
--cpra-penalty-levels |
(none) | Comma-separated penalty weights for penalty-diversification (MIS / VertexCover only) |
Per-backend defaults¶
The --learning-rate flag is backend-aware. Omit it and the CLI
applies the right default:
| Backend | Default --learning-rate |
|---|---|
qqa (default) |
1.0 |
pignn |
1e-4 |
cpra |
1e-4 |
This is the behaviour of qqa.anneal, qqa.pignn.train_cra_pi_gnn,
and qqa.pignn.train_cpra_pi_gnn respectively. Pass an explicit
--learning-rate to override.
Problems supported per backend¶
| Backend | Supported --problem values |
|---|---|
qqa |
All problems exposed by the current built-in catalogue |
sa, pa |
Flat binary/spin catalogue problems |
isco |
QUBO catalogue problems |
scip |
Single-instance QUBOProblem models |
pignn |
mis, maxcut, maxclique, vertex_cover, graph_bisection |
cpra |
Same as pignn (penalty diversification works for mis, vertex_cover only) |
Examples¶
# Inspect and solve a portable model through the stable API.
qqa inspect model.mps
qqa plan model.mps --profile balanced --budget 60s
qqa solve model.mps --profile balanced --budget 60s
# Explicit QQA warm start followed by certification.
qqa solve model.mps --profile certify --exact-backend scip --budget 60s
# Quickest check that the install works.
qqa solve --problem sk --size 60 --sol-size 64 --epochs 500
# A real MIS solve on a saved graph.
qqa solve --problem mis --graph-file data/my_graph.graphml \
--sol-size 256 --epochs 2000 --device cuda \
--output results/mis.pkl
# CRA-PI-GNN comparison run on the same graph.
qqa solve --problem mis --graph-file data/my_graph.graphml \
--backend pignn --epochs 5000 --device cuda \
--output results/mis_cra.pkl
# CPRA portfolio: four MIS solutions at different penalty levels.
qqa solve --problem mis --graph-file data/my_graph.graphml \
--backend cpra --cpra-num-replicas 4 \
--cpra-penalty-levels 1.0,1.5,2.0,2.5 \
--epochs 5000 --device cuda --output results/mis_cpra.pkl
# QQA GPU exploration followed by SCIP improvement/certification.
qqa solve --problem maxcut --size 80 --backend scip --device cuda \
--epochs 1500 --scip-time-limit 120 --scip-warm-starts 64
# A user-defined problem.
qqa solve --problem-file my_problem.py --allow-unsafe-python \
--sol-size 128 --epochs 1500 \
--report results/model-report.html
qqa bench¶
Run a small benchmark on bundled data. Useful as a reproducibility sanity check.
| Flag | Default | What it does |
|---|---|---|
--preset |
er-small |
One of er-small, sk-small, ea-small |
--sol-size |
64 |
|
--epochs |
500 |
|
--device |
cpu |
|
--seed |
0 |
qqa benchmark¶
Fetch, inspect, and solve public MIPLIB/QPLIB instances. This is distinct from
qqa bench, which runs the bundled combinatorial presets.
qqa benchmark fetch miplib --instance pk1 --output data/public-benchmarks/miplib
qqa benchmark fetch qplib --instance 31 --output data/public-benchmarks/qplib
qqa benchmark inspect data/public-benchmarks/qplib/QPLIB_0031.qplib
qqa benchmark run data/public-benchmarks/miplib/pk1.mps.gz \
--solver sg-cqqa --time-limit 60 --output result.json
qqa benchmark compare data/public-benchmarks/miplib/pk1.mps.gz \
--baseline-solver scip-aggressive --seeds 0 1 2 \
--time-limit 60 --output comparison.json
qqa benchmark merge shard-0.json shard-1.json --output comparison.json
qqa benchmark publish \
--campaign miplib=comparison.json \
--snapshot miplib=miplib-snapshot.json \
--implementation-revision COMMIT_SHA \
--output public-results
fetch accepts miplib or qplib; omit --instance to download the full
official archive. inspect emits sparse dimensions, variable-type counts,
PROBTYPE when available, and portable source provenance.
run accepts --solver scip, --solver scip-aggressive, or
--solver sg-cqqa. Shared flags are
--time-limit, --gap, --threads, --reference-file, --format,
--worker-timeout, --implementation-revision,
--include-solution-values, --output, and --quiet.
The solution flag stores values in original variable order and can produce a
large JSON file; a SHA-256 solution identity is recorded even when values are
omitted. SG-CQQA additionally accepts --core-size,
--maximum-problem-variables, --maximum-integer-variables,
--qplib-problem-types, --minimum-core-size,
--maximum-core-saturation, --sol-size, --epochs, --max-calls,
--max-candidates, --completion-time, --completion-nodes,
--dive-lp-iterations, --qqa-fix-fraction, --repair-beam-width,
--reference-pool-size, --minimum-relative-improvement,
call-time/node spacing limits,
--fast-candidates, --max-lp-rows, objective/row/proximity weights,
--allow-no-incumbent, --no-adaptive-row-lagrangian,
--no-subscip-repair, --continue-qqa-without-improvement, --seed, and
--device. --qplib-problem-types is a three-character PROBTYPE allow-list;
the two --maximum-*-variables flags accept a positive integer or none to
remove that structural gate while the callback core remains bounded.
Non-matching QPLIB inputs use the exact aggressive-SCIP bypass in paired runs.
The time limit covers parsing/setup, QQA, continuous completion, and SCIP.
compare runs a paired Cartesian product of input instances, --solvers, and
--seeds. Every pair receives the same total budget and thread count. Its JSON
contains per-run trajectories, portable run configuration, per-solver medians,
and win/tie/loss counts against --baseline-solver, including counts
stratified by actual QQA execution. The defaults compare scip-aggressive
against sg-cqqa in balanced order. This is the direct plugin ablation because
both use the same aggressive native SCIP heuristic setting.
The balanced order uses a stable hash of the portable instance basename plus
the seed, so splitting a campaign into shards does not reset the order phase.
For audit-grade cells, --include-import-in-budget starts before launching each
isolated interpreter and therefore includes package startup and original-model
parsing. --isolate-all gives every solver a fresh native process, and
--no-equivalent-baseline-reuse independently executes structurally bypassed
SG-CQQA cells. The summary still reports independent runs, equivalent reuse,
QQA plugin activation, actual QQA calls, QQA-attributable improvements,
normalized failure outcomes, stage durations, peak memory, and instance-level
confidence intervals separately.
--threads constrains SCIP workers, LP-solver threads, and (for SG-CQQA)
Torch threads. Reproducible CPU campaigns should additionally cap the BLAS and
OpenMP thread pools in their launcher.
For run, metric clocks begin before parsing. For paired compare, one common
algebraic import is excluded from every solver and the clocks begin before each
solver model is built. Primal integral uses the configured time limit as a
fixed common horizon.
--output is also an incremental checkpoint. Add --continue-on-error for a
large heterogeneous archive and repeat the identical command with --resume
after interruption. A mismatched instance list, solver list, seed set, time,
thread count, reference name, or SG-CQQA configuration is rejected rather than
mixed into an existing campaign. --retry-failures retries only the anonymous
failure records during a resumed run.
benchmark merge can combine shards split by instances, seeds, or both. The
requested (instance, seed) cells must be disjoint and form one complete
Cartesian grid; partial or overlapping campaign collections are rejected.
merge combines disjoint comparison shards after checking that every setting
except the instance list is identical. It rejects overlapping instances or
duplicate solver/instance/seed rows and recomputes all medians and W/T/L counts.
benchmark publish accepts repeatable --campaign LIBRARY=PATH and matching
--snapshot LIBRARY=PATH options. It emits path-free compact/full artifacts
and a checksum manifest; duplicate library names or mismatched sets are
rejected.
See the MIPLIB/QPLIB guide for metric definitions and
reproducibility guidance.
qqa ask¶
Describe a bounded optimisation problem in ordinary language, compile it through an OpenAI-compatible endpoint, validate the model locally, show the route chosen by trusted code, and solve:
export QQA_LLM_API_KEY='…'
export QQA_LLM_BASE_URL='https://api.example.com'
export QQA_LLM_MODEL='your-model-id'
qqa ask \
"Choose integer batches in [0,20] and real overtime in [0,8]. \
Minimize 3*batches + square(overtime), with 4*batches + overtime >= 45." \
--solver auto --device auto --output-plan plan.json --report result.html
The dedicated system prompt is separate from the untrusted request. Generated
JSON is interpreted through the same restricted grammar as qqa tex; it is
never evaluated as Python. Local checks cover schema fields, bounded variable
domains, model-size quotas, expression syntax, scalar shape, and finite sample
values. The route and rationale are printed before execution.
Input and review flags¶
Exactly one input source is required:
| Flag/input | What it does |
|---|---|
PROMPT |
Compile the quoted request |
- |
Read the request from standard input |
--file REQUEST.txt |
Read a UTF-8 request file |
--spec MODEL.json |
Plan or solve a reviewed ModelSpec without an API call |
--plan-only |
Stop after validation and route selection |
--show-model |
Print the validated model JSON |
--output-plan PLAN.json |
Save the audited model and routing explanation |
Routing and execution flags¶
| Flag | Default | What it does |
|---|---|---|
--solver |
auto |
auto, qqa, qqa-scip/hybrid, scip, pareto, or blackbox |
--device / --seed |
auto / 0 |
Compute device and reproducibility seed |
--sol-size / --epochs |
256 / 1500 |
QQA or Pareto population and iterations |
--budget / --batch-size / --workers |
96 / 8 / 4 |
Black-box evaluation budget and concurrency |
--scip-time-limit / --scip-gap |
60 / 0 |
Total QQA+SCIP wall-clock budget and target gap |
--scip-threads / --scip-warm-starts |
1 / 32 |
SCIP threads and QQA primal starts |
--json / --output-result |
off / none | Print or save a machine-readable result |
--report |
none | Save an interactive HTML report |
auto routes multiple declared objectives to one-run parallel Pareto QQA and
keeps compatible single-objective symbolic models on pure QQA. QQA→SCIP is
enabled only by explicitly selecting qqa-scip or scip. Black-box intent can select the
budget-aware route when the request explicitly provides a safe objective
formula: the validated expression is evaluated point by point without
gradients. If the objective exists only in a simulator, external API, or
experiment, prose is insufficient—bind the real callable or service adapter
through qqa.BlackBoxProblem. QQA must not invent a missing evaluator. Use
--plan-only, inspect notes, and correct any material assumption before
execution.
The API key deliberately has no command-line flag, avoiding shell-history and
process-list exposure. Configure it as QQA_LLM_API_KEY. Endpoint and model
profiles use QQA_LLM_BASE_URL and QQA_LLM_MODEL, or the corresponding
--api-base, --model, and --api-style options. QQA embeds no
provider-specific endpoint or model default.
The full reviewed workflow is also available in the natural-language optimisation Colab.
qqa tex¶
Translate a TeX optimisation problem through an OpenAI-compatible Responses or Messages endpoint, validate the declarative model locally, and solve it:
export QQA_LLM_API_KEY='…'
export QQA_LLM_BASE_URL='https://api.example.com'
export QQA_LLM_MODEL='your-model-id'
qqa tex '\min_{x\in[-5,5]} (x-1.5)^2' \
--device cuda --output-model model.json --report result.html
The key has no CLI flag by design, so it does not leak into shell history.
--dry-run validates without solving. qqa tex --spec model.json solves an
audited model offline. --api-base, --model, and --api-style configure a
compatible gateway; --insecure explicitly disables TLS verification.
TeX may also be piped through stdin:
Production-style file input and exact refinement:
qqa tex --file production-plan.tex --solver scip --device auto \
--output-model audited-model.json --output-result result.json \
--report result.html
--solver auto is pure QQA for a single objective. --solver scip explicitly
uses QQA→SCIP when the scip extra is installed. --show-model prints the
strict intermediate JSON. Use
--spec audited-model.json for repeatable offline solving without an API key.
qqa example¶
List and run packaged realistic applications:
qqa example list
qqa example run microgrid-dispatch --output-dir results/dispatch
qqa example run microgrid-pareto --device auto --output-dir results/pareto
qqa example run portfolio-pareto --device auto --output-dir results/portfolio
qqa example run process-blackbox --device auto --output-dir results/process
Each output directory contains machine-readable JSON plus CSV and/or a self-contained interactive HTML report.
qqa doctor¶
qqa doctor reports Python, Torch, CUDA/GPU, SCIP, PyG, Streamlit, Plotly, and
pandas capability. qqa doctor --json is suitable for support bundles and CI.
qqa gui¶
Launch the Streamlit dashboard in a subprocess. Reads the dashboard
sources either from the installed wheel (under qqa/_app/) or from
the repo's app/ directory in editable installs.
| Flag | Default | What it does |
|---|---|---|
--port |
8501 |
|
--host |
loopback interface | Network interface accepted by Streamlit |
--headless |
off | Disable automatic browser launch |
Exit codes¶
0— success.1— non-fatal user error (bad combination of flags, infeasible result, etc.). The error message is printed to stderr.2— argparse failure (unknown flag, missing required argument).
Where to look in the source¶
The whole CLI lives in src/qqa/cli.py. Read it
top-to-bottom — the structure is one build_parser() followed by one
_cmd_<name>(args) function per subcommand.