Internals — what lives where¶
A guided tour of the source tree for new contributors. If you only need to use QQA4CO see Quickstart; if you want to add a new problem, relaxation, or backend see Extending QQA4CO. This page is for everyone who wants to read the code.
Top-level layout¶
QQA4CO/
├── src/qqa/ # The Python package (everything ships in the wheel)
├── app/ # Streamlit dashboard (also shipped in the wheel)
├── tests/ # 11 pytest files, < 60 s on CPU
├── notebooks/ # Curated walkthroughs (CRA-PI-GNN, CPRA)
├── examples/ # Auto-generated per-problem notebooks
├── scripts/ # Demos, benchmarks, gallery / verification regen
├── docs/ # MkDocs-Material source (this site)
├── data/ # Bundled MIS-ER datasets, gallery assets
├── deploy/ # Streamlit Cloud config
├── tasks/ # Maintainer-only journal: todo.md + lessons.md
├── pyproject.toml # PEP 621, hatchling, ruff, pytest, extras
├── mkdocs.yml # Site nav (this site is built from docs/)
├── CHANGELOG.md # Keep-a-Changelog
├── CITATION.cff # GitHub citation widget + Zenodo
├── CONTRIBUTING.md # Setup, tests, style, PR process
├── CODE_OF_CONDUCT.md # Contributor Covenant
├── SECURITY.md # Vulnerability reporting
├── Makefile # `make test / lint / format / docs / serve`
└── README.md # The 30-second pitch and the long sales page
tasks/ is a maintainer journal that we keep in git so future-us can
re-derive design decisions; it is not part of the public surface.
src/qqa/ — module map¶
src/qqa/
├── __init__.py # Public API surface, __version__ via importlib.metadata
├── annealing.py # The single anneal() loop and AnnealResult
├── relaxation.py # Binary / Spin / Categorical / Instance relaxations + Protocol
├── schedule.py # LinearBGSchedule (callable contract)
├── callbacks.py # Callback ABC, CallbackState, History/AutoDiv/Population/Trajectory
├── utils.py # fix_seed, generate_graph, MIS / MaxCut analytics
├── datasets.py # Bundled MIS-ER loaders + benchmark constants
├── visualization.py # Plot helpers (matplotlib + optional plotly)
├── cli.py # The qqa command (argparse, no third-party deps)
├── legacy.py # Deprecated 0.2.x batch_annealing_* shims
├── problems/
│ ├── __init__.py
│ ├── base.py # COProblem / QUBOProblem ABCs + normalize_graph
│ ├── qubo.py # MIS / MaxClique / MaxCut (+ batched instance variants)
│ ├── categorical.py # Coloring, BalancedGraphPartition
│ ├── spin.py # SpinProblem, Ising1D, EA, SK, Perceptron, Hopfield
│ ├── extras.py # Knapsack, NumberPartitioning, VertexCover, GraphBisection,
│ │ # MaxSAT3, TSP, QAP, NQueens
│ └── user.py # UserProblem + load_problem_from_file (--problem-file CLI hook)
└── pignn/ # Optional CRA-PI-GNN / CPRA backends (PyG)
├── __init__.py # Re-exports train_cra_pi_gnn / train_cpra_pi_gnn
├── _import.py # require_pyg() with an actionable ImportError
├── graph.py # extract_nx_graph + nx_to_edge_index helpers
├── model.py # GCNNet (2-layer GCNConv, multi-head for CPRA)
└── trainer.py # The two trainer functions (returning AnnealResult)
Hard rules for changes inside src/qqa/¶
- Never import
torch_geometricfromqqa.__init__or any module that does not live underqqa/pignn/. It pulls in heavy transitive deps that core users do not need; a strayimporthere is enough to breakpip install qqafor everyone withoutqqa[pignn]. - Public API additions go in
src/qqa/__init__.pyand its__all__so they show up indir(qqa)and the auto-generated API reference. - Bug fixes that touch
anneal()need a regression test. That loop is the central nervous system of the package; every previous bug there shipped because the diff "looked obvious". - Public function signatures are append-only. Add a new keyword with a sensible default — never reorder, rename, or remove an existing argument without a deprecation cycle.
app/ — Streamlit dashboard¶
app/
├── streamlit_app.py # Landing page (cache config + intro)
├── _common.py # Cached resources shared across pages
├── _solution_viz.py # Per-problem solution renderers
└── pages/
├── 1_Solve.py # Build a problem + run anneal + show progress
├── 2_Visualize.py # Re-render an AnnealResult pickle
└── 3_Compare.py # Hyperparameter sweeps
The wheel ships this directory under qqa/_app/ (see
pyproject.toml [tool.hatch.build.targets.wheel.force-include]) so
qqa gui works after pip install qqa without a repo checkout.
tests/ — what each file covers¶
| File | Covers |
|---|---|
test_smoke.py |
End-to-end anneal() on each variable kind |
test_qqa_correctness.py |
Numerical guarantees against ground truth on small instances |
test_problems.py |
Constructor / shape contracts of binary/categorical problems |
test_extra_problems.py |
The extras.py catalogue |
test_spin_problems.py |
Spin-glass problems (Ising/EA/SK/Hopfield/Perceptron) |
test_pignn.py |
Optional PyG backends — CRA-PI-GNN + CPRA |
test_cli.py |
qqa solve / bench / version subcommands |
test_gui_smoke.py |
Streamlit imports without a browser |
test_gui_apptest.py |
streamlit.testing harness on the multi-page app |
test_visualization.py |
Plot helpers do not crash with a minimal AnnealResult |
test_legacy.py |
Deprecated batch_annealing_* aliases still emit a DeprecationWarning |
The full suite finishes in well under a minute on CPU because every problem instance is intentionally tiny.
scripts/ — runnable demos and reproducibility¶
Listed in docs/reference/backends.md and partially on the README.
The categories:
demo_*.py— single-problem walkthroughs you can run asuv run python scripts/demo_mis.py.bench_*.py— small benchmarks;bench_qqa_vs_pignn.pyregenerates the headline comparison table.make_gallery.py— regenerates the README/docs gallery PNGs.verify_all_problems.py— the catalogue-wide correctness sweep that producesdocs/verification.md._generate_notebooks.py— deterministically rebuilds theexamples/notebooks (the leading underscore signals "internal tooling").check_streamlit_deploy.py— health probe for the hosted demo at https://parallelquasiquantum4co.streamlit.app/.
How tests, docs, and CI relate¶
.github/workflows/ci.yml
│
├── ruff check + ruff format --check
├── pytest -q ← uses tests/
└── mkdocs build --strict ← uses docs/ and mkdocs.yml
A PR that breaks any of those three steps is automatically blocked.
There is also a Pages workflow that publishes the same mkdocs build
output to https://yuma-ichikawa.github.io/QQA4CO/ on every push to
main.
Where to start a typical PR¶
- Open
tasks/todo.md, scroll to the bottom, and skim the most recent dated section — that is where active work is journaled. - Run the whole test suite once locally before you start; that becomes your baseline.
- After every change run
make lint test docs(or the equivalentuv run ...commands listed inCONTRIBUTING.md). - If your change adds a public-API symbol, also add it to
docs/api.mdso mkdocstrings picks it up. - Add an entry to
CHANGELOG.mdunder the Unreleased heading.
That is the whole loop. See Releasing for what happens once changes accumulate to a tag.