qqa 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
qqa-0.3.0/.gitignore ADDED
@@ -0,0 +1,43 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+
8
+ # Distribution / packaging
9
+ build/
10
+ dist/
11
+ *.egg-info/
12
+ *.egg
13
+
14
+ # uv / virtualenv
15
+ .venv/
16
+ venv/
17
+ env/
18
+
19
+ # Testing / coverage
20
+ .pytest_cache/
21
+ .ruff_cache/
22
+ .coverage
23
+ htmlcov/
24
+
25
+ # Jupyter
26
+ .ipynb_checkpoints/
27
+
28
+ # OS
29
+ .DS_Store
30
+
31
+ # IDE
32
+ .vscode/
33
+ .idea/
34
+
35
+ # MkDocs
36
+ site/
37
+
38
+ # Local task planning (not versioned)
39
+ tasks/
40
+
41
+ # Streamlit cache
42
+ .streamlit/secrets.toml
43
+
qqa-0.3.0/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format is based
4
+ on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project
5
+ follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.3.0] - Unreleased
8
+
9
+ ### Added
10
+
11
+ - **Spin problem family** in `qqa.problems`:
12
+ - `Ising1D`, `EdwardsAnderson`, `SherringtonKirkpatrick`
13
+ - `BinaryPerceptron` (teacher-student), `HopfieldMemory`
14
+ - New `SpinRelaxation` that maps `[0,1]` → `±1` with differentiable forward.
15
+ - **Visualization** (`qqa.visualization`):
16
+ - Dual backend (`"matplotlib"` default, `"plotly"` optional).
17
+ - `plot_best_trajectory`, `plot_schedule`, `plot_run_comparison`,
18
+ `plot_parallel_coordinates`, `plot_solution_heatmap`.
19
+ - **CLI** (`qqa` entry point): `qqa version`, `qqa solve`, `qqa bench`,
20
+ `qqa gui`.
21
+ - **Streamlit GUI** (`qqa gui` / `uv run streamlit run app/streamlit_app.py`):
22
+ problem definition → live annealing → visualization → comparison.
23
+ - **Example notebooks**: MIS, coloring, MaxCut, 3D Edwards–Anderson, SK,
24
+ binary perceptron, Hopfield memory, parallel benchmark.
25
+ - **Docs site** via MkDocs + Material with auto API reference.
26
+ - **Tooling**: GitHub Actions CI, `pre-commit`, `CONTRIBUTING.md`,
27
+ `CITATION.cff`.
28
+
29
+ ### Changed
30
+
31
+ - `qqa.problems` is now a subpackage (`qubo.py`, `categorical.py`, `spin.py`).
32
+ Public symbols (`MaximumIndependentSet`, `Coloring`, ...) are preserved via
33
+ re-export, so existing code keeps working.
34
+
35
+ ### Deprecated
36
+
37
+ - `qqa.legacy.*` wrappers still work and emit `DeprecationWarning`; use
38
+ `qqa.anneal` instead.
39
+
40
+ ## [0.2.0]
41
+
42
+ - Initial unified `qqa.anneal` API, package reorganization under `src/qqa`,
43
+ `uv`/`pyproject.toml` based install, smoke tests and demo scripts.
44
+
45
+ ## [0.1.0]
46
+
47
+ - Original research release accompanying the ICLR 2025 paper.
qqa-0.3.0/LICENCE.txt ADDED
@@ -0,0 +1,12 @@
1
+ Copyright (c) 2025 Fujitsu Limited
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:
5
+
6
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer
7
+
8
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+
10
+ * Neither the name of Fujitsu Limited nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11
+
12
+ NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
qqa-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,532 @@
1
+ Metadata-Version: 2.4
2
+ Name: qqa
3
+ Version: 0.3.0
4
+ Summary: Quasi-Quantum Annealing (QQA): a general-purpose GPU solver for combinatorial and spin-glass optimization.
5
+ Project-URL: Homepage, https://github.com/Yuma-Ichikawa/QQA4CO
6
+ Project-URL: Repository, https://github.com/Yuma-Ichikawa/QQA4CO
7
+ Project-URL: Documentation, https://yuma-ichikawa.github.io/QQA4CO/
8
+ Project-URL: Issues, https://github.com/Yuma-Ichikawa/QQA4CO/issues
9
+ Project-URL: Changelog, https://github.com/Yuma-Ichikawa/QQA4CO/blob/main/CHANGELOG.md
10
+ Project-URL: Paper, https://openreview.net/forum?id=9EfBeXaXf0
11
+ Project-URL: Live Demo, https://parallelquasiquantum4co.streamlit.app/
12
+ Author: Yuma Ichikawa, Yamato Arai
13
+ License: Copyright (c) 2025 Fujitsu Limited
14
+ All rights reserved.
15
+
16
+ Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:
17
+
18
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer
19
+
20
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
21
+
22
+ * Neither the name of Fujitsu Limited nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
23
+
24
+ NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ License-File: LICENCE.txt
26
+ Keywords: annealing,combinatorial-optimization,hopfield,ising,optimization,perceptron,pytorch,spin-glass
27
+ Classifier: Development Status :: 4 - Beta
28
+ Classifier: Intended Audience :: Science/Research
29
+ Classifier: License :: OSI Approved :: BSD License
30
+ Classifier: Programming Language :: Python :: 3
31
+ Classifier: Programming Language :: Python :: 3.10
32
+ Classifier: Programming Language :: Python :: 3.11
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
35
+ Classifier: Topic :: Scientific/Engineering :: Physics
36
+ Requires-Python: >=3.10
37
+ Requires-Dist: matplotlib>=3.8
38
+ Requires-Dist: networkx>=3.1
39
+ Requires-Dist: numpy>=1.24
40
+ Requires-Dist: pandas>=2.0
41
+ Requires-Dist: plotly>=5.17
42
+ Requires-Dist: scipy>=1.11
43
+ Requires-Dist: streamlit>=1.30
44
+ Requires-Dist: torch>=2.1
45
+ Requires-Dist: tqdm>=4.66
46
+ Provides-Extra: all
47
+ Requires-Dist: ipykernel>=6; extra == 'all'
48
+ Requires-Dist: jupyterlab>=4; extra == 'all'
49
+ Requires-Dist: mkdocs-material>=9.5; extra == 'all'
50
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == 'all'
51
+ Requires-Dist: nbformat>=5; extra == 'all'
52
+ Requires-Dist: nbval>=0.11; extra == 'all'
53
+ Requires-Dist: pandas>=2.0; extra == 'all'
54
+ Requires-Dist: plotly>=5.17; extra == 'all'
55
+ Requires-Dist: pre-commit>=3.6; extra == 'all'
56
+ Requires-Dist: pymdown-extensions>=10; extra == 'all'
57
+ Requires-Dist: pytest>=8; extra == 'all'
58
+ Requires-Dist: requests>=2.31; extra == 'all'
59
+ Requires-Dist: ruff>=0.6; extra == 'all'
60
+ Requires-Dist: streamlit>=1.30; extra == 'all'
61
+ Provides-Extra: dev
62
+ Requires-Dist: nbval>=0.11; extra == 'dev'
63
+ Requires-Dist: pre-commit>=3.6; extra == 'dev'
64
+ Requires-Dist: pytest>=8; extra == 'dev'
65
+ Requires-Dist: requests>=2.31; extra == 'dev'
66
+ Requires-Dist: ruff>=0.6; extra == 'dev'
67
+ Provides-Extra: docs
68
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
69
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
70
+ Requires-Dist: pymdown-extensions>=10; extra == 'docs'
71
+ Provides-Extra: gui
72
+ Requires-Dist: pandas>=2.0; extra == 'gui'
73
+ Requires-Dist: plotly>=5.17; extra == 'gui'
74
+ Requires-Dist: streamlit>=1.30; extra == 'gui'
75
+ Provides-Extra: notebook
76
+ Requires-Dist: ipykernel>=6; extra == 'notebook'
77
+ Requires-Dist: jupyterlab>=4; extra == 'notebook'
78
+ Requires-Dist: nbformat>=5; extra == 'notebook'
79
+ Provides-Extra: plotly
80
+ Requires-Dist: pandas>=2.0; extra == 'plotly'
81
+ Requires-Dist: plotly>=5.17; extra == 'plotly'
82
+ Description-Content-Type: text/markdown
83
+
84
+ # QQA — Quasi-Quantum Annealing
85
+
86
+ PyTorch implementation of the ICLR 2025 paper
87
+ **[Continuous Tensor Relaxation for Finding Diverse Solutions in Combinatorial Optimization](https://openreview.net/forum?id=9EfBeXaXf0)**
88
+ by Yuma Ichikawa and Yamato Arai.
89
+
90
+ <p align="center">
91
+ <a href="https://colab.research.google.com/github/Yuma-Ichikawa/QQA4CO/blob/main/examples/00_colab_quickstart.ipynb">
92
+ <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open Quickstart in Colab">
93
+ </a>
94
+ <a href="https://parallelquasiquantum4co.streamlit.app/">
95
+ <img src="https://static.streamlit.io/badges/streamlit_badge_black_white.svg" alt="Open in Streamlit">
96
+ </a>
97
+ </p>
98
+
99
+ <p align="center">
100
+ <img src="data/fig/demo.gif" width="400">
101
+ </p>
102
+
103
+ **QQA** relaxes a discrete problem to a continuous, differentiable objective
104
+ and anneals towards a discrete minimum using gradient-based sampling. The
105
+ same loop handles combinatorial problems (MIS, Max-Cut, coloring, …) and
106
+ physics-flavoured spin problems (Ising, Edwards-Anderson, SK, binary
107
+ perceptron, Hopfield memory).
108
+
109
+ Highlights:
110
+
111
+ - **Unified Python API**: one `qqa.anneal()` for every problem.
112
+ - **Rich problem catalog** out of the box (10+ classes).
113
+ - **Interactive visualization**: matplotlib by default, Plotly optional.
114
+ - **CLI**: `qqa solve`, `qqa bench`, `qqa gui`, `qqa version`.
115
+ - **Streamlit GUI**: browser dashboard with live progress and sweep tools.
116
+ - **Docs site**: MkDocs + Material + auto API reference.
117
+
118
+ ---
119
+
120
+ ## Install
121
+
122
+ ### With [uv](https://github.com/astral-sh/uv) (recommended)
123
+
124
+ ```bash
125
+ git clone https://github.com/Yuma-Ichikawa/QQA4CO.git
126
+ cd QQA4CO
127
+ uv sync # core only
128
+ uv sync --extra plotly --extra gui --extra dev # with extras
129
+ uv run pytest -q # sanity check
130
+ ```
131
+
132
+ ### With pip
133
+
134
+ ```bash
135
+ pip install qqa # core
136
+ pip install "qqa[plotly]" # + interactive plots
137
+ pip install "qqa[gui]" # + Streamlit dashboard
138
+ pip install "qqa[all]" # everything
139
+ ```
140
+
141
+ ## Quickstart
142
+
143
+ ```python
144
+ import networkx as nx
145
+ import qqa
146
+
147
+ qqa.fix_seed(0)
148
+ g = nx.random_regular_graph(d=3, n=100, seed=0)
149
+ problem = qqa.MaximumIndependentSet(g, penalty=2)
150
+ result = qqa.anneal(problem, sol_size=100, num_epochs=1500)
151
+ print(f"MIS size: {-int(result.best_obj)} in {result.runtime:.2f}s")
152
+ ```
153
+
154
+ The same call style applies to spin problems:
155
+
156
+ ```python
157
+ problem = qqa.SherringtonKirkpatrick(N=100, seed=0)
158
+ result = qqa.anneal(problem, sol_size=200, num_epochs=2000, verbose=False)
159
+ print(f"E_0 / N ≈ {result.best_obj / 100:.4f} (target ≈ -0.7632)")
160
+ ```
161
+
162
+ ## Problem catalog
163
+
164
+ | Category | Classes |
165
+ | ----------------- | ------- |
166
+ | Binary QUBO | `MaximumIndependentSet`, `MaxClique`, `MaxCut` (+ `*Instance` batched variants) |
167
+ | Binary (classic CO) | `Knapsack`, `NumberPartitioning`, `VertexCover`, `GraphBisection`, `MaxSAT3` |
168
+ | Categorical | `Coloring`, `BalancedGraphPartition` |
169
+ | Categorical (permutation) | `TSP`, `QAP`, `NQueens` |
170
+ | 1D Ising | `Ising1D` |
171
+ | Spin glass | `EdwardsAnderson`, `SherringtonKirkpatrick` |
172
+ | Statistical phys. | `BinaryPerceptron`, `HopfieldMemory` |
173
+
174
+ Every problem exposes `problem.score_summary(x_disc) -> dict` so the CLI /
175
+ GUI can display a human-readable metric (e.g. "IS size: 22", "packed
176
+ value: 358", "tour length: 3.28") and a feasibility flag alongside the
177
+ raw loss.
178
+
179
+ Read the full mathematical definitions in
180
+ [`docs/problems.md`](docs/problems.md).
181
+
182
+ ## Command-line interface
183
+
184
+ ```bash
185
+ qqa version
186
+ qqa solve --problem sk --size 100 --sol-size 128 --epochs 1000
187
+ qqa solve --problem mis --graph-file mygraph.gpickle --epochs 1500
188
+ qqa bench --preset er-small --epochs 500
189
+ qqa gui # open http://localhost:8501
190
+ ```
191
+
192
+ Run `qqa <command> --help` for the full option list.
193
+
194
+ ## Streamlit GUI
195
+
196
+ ```bash
197
+ pip install "qqa[gui]"
198
+ qqa gui
199
+ ```
200
+
201
+ The dashboard has four pages:
202
+
203
+ - **Home** — pick a problem family (Graph, Classic CO, Categorical /
204
+ permutation, Physics), size, seed, and problem-specific parameters.
205
+ - **Solve** — set QQA hyper-parameters and launch a run with a live
206
+ progress bar, a `mean ± σ` loss band across the parallel replicas, a
207
+ population heatmap sorted by best-so-far, a population-diversity curve,
208
+ and a headline score card (e.g. "IS size: 22 / 40").
209
+ - **Visualize** — tabbed view of dynamics, best trajectory, the applied
210
+ annealing schedule, a solution heatmap, parallel population, PCA
211
+ trajectory, ridgeline of loss distributions, and per-replica fate
212
+ lines.
213
+ - **Compare** — run a small hyper-parameter grid and inspect the result
214
+ with parallel-coordinates and overlaid trajectories.
215
+
216
+ A light / dark toggle lives in the sidebar; both themes share an
217
+ academic, Plotly-aware palette.
218
+
219
+ ### Live demo
220
+
221
+ A hosted instance runs at
222
+ **<https://parallelquasiquantum4co.streamlit.app/>**. The operator runbook,
223
+ including how to switch the Streamlit Community Cloud app from *Private* to
224
+ *Anyone with the link*, is in
225
+ [`deploy/STREAMLIT_DEPLOY.md`](deploy/STREAMLIT_DEPLOY.md). A quick health
226
+ check is available via:
227
+
228
+ ```bash
229
+ uv run python scripts/check_streamlit_deploy.py
230
+ ```
231
+
232
+ > **Note.** If the URL currently redirects to `/-/auth/app?…`, the app is
233
+ > still set to Private on Streamlit Community Cloud. The fix is a single
234
+ > setting in the Streamlit Cloud dashboard — see
235
+ > [`deploy/STREAMLIT_DEPLOY.md §1`](deploy/STREAMLIT_DEPLOY.md#1-why-is-the-url-redirecting-to--auth-app).
236
+
237
+ ## Deploy to the public web (free)
238
+
239
+ The dashboard is published for free via **Streamlit Community Cloud** at
240
+ <https://parallelquasiquantum4co.streamlit.app/> — no custom domain, no
241
+ paid hosting, nothing else to wire up. The same repository can also be
242
+ dropped onto Hugging Face Spaces, Fly.io, Render, or Google Cloud Run
243
+ unchanged.
244
+
245
+ ### 1. Streamlit Community Cloud (the live URL)
246
+
247
+ The repository already ships everything Community Cloud needs:
248
+
249
+ - [`requirements.txt`](requirements.txt) — CPU-only PyTorch pin plus the
250
+ minimal runtime. Installs this repo as the `qqa` package via the
251
+ trailing `.`.
252
+ - [`runtime.txt`](runtime.txt) — pins the Python version for Community
253
+ Cloud.
254
+ - [`.streamlit/config.toml`](.streamlit/config.toml) — light theme and
255
+ telemetry off.
256
+
257
+ First-time deploy:
258
+
259
+ 1. Go to <https://share.streamlit.io> and sign in with GitHub.
260
+ 2. **New app** → Repository `Yuma-Ichikawa/QQA4CO`, Branch `main`,
261
+ Main file path `app/streamlit_app.py`.
262
+ 3. Click **Deploy**. Your app will be served at
263
+ `https://<something>.streamlit.app` after a 3–5 min build.
264
+ 4. In the app's `⋮` → **Settings** → **Sharing**, set *"Who can view
265
+ this app?"* to **"Anyone with the link can view"**. This is the only
266
+ knob standing between a green deploy and a public URL — without it
267
+ every visitor is redirected to Streamlit SSO.
268
+
269
+ Re-deploys happen automatically on every push to `main`. The runbook,
270
+ common failure modes, and the health-check endpoint are documented in
271
+ [`deploy/STREAMLIT_DEPLOY.md`](deploy/STREAMLIT_DEPLOY.md).
272
+
273
+ The custom-problem editor is **off by default** on public deployments
274
+ (it evaluates arbitrary Python via `exec`). Re-enable it on a trusted
275
+ machine with:
276
+
277
+ ```bash
278
+ QQA_ALLOW_CUSTOM=1 uv run qqa gui
279
+ ```
280
+
281
+ ### 2. Other free / cheap targets
282
+
283
+ If you would rather self-host, the repository is portable enough to drop
284
+ onto any of the usual platforms without edits:
285
+
286
+ - **Hugging Face Spaces** (Streamlit SDK) — persistent URL, free CPU
287
+ tier, HTTPS by default.
288
+ - **Fly.io / Render** — Docker-based deploys; use `app/streamlit_app.py`
289
+ as the entry point and `requirements.txt` as the dependency file.
290
+ - **Google Cloud Run** — container image, pay-per-request.
291
+
292
+ You do *not* need a domain registrar / shared-hosting account for any
293
+ of these — each platform gives you a permanent HTTPS URL out of the
294
+ box.
295
+
296
+ ## Visualization
297
+
298
+ ```python
299
+ from qqa import visualization as viz
300
+
301
+ viz.plot_history(result) # loss / penalty / diversity
302
+ viz.plot_best_trajectory(result, backend="plotly")
303
+ viz.plot_schedule(qqa.LinearBGSchedule(-2, 0.1), num_epochs=2000)
304
+ viz.plot_run_comparison([r1, r2, r3], labels=["lr=1", "lr=0.5", "lr=2"])
305
+ viz.plot_parallel_coordinates(sweep_df, objective="best_obj")
306
+ viz.plot_solution_heatmap(result, problem)
307
+ ```
308
+
309
+ Every function accepts `backend="matplotlib"` (default) or `backend="plotly"`.
310
+ Plotly is optional; if it is not installed the plot silently falls back to
311
+ matplotlib.
312
+
313
+ ### Visualization gallery
314
+
315
+ All figures below are produced by `scripts/make_gallery.py` (regenerate with
316
+ `uv run python scripts/make_gallery.py`) and stored under
317
+ [`data/fig/gallery/`](data/fig/gallery). Each row shows one problem family
318
+ from the catalog; the columns are, left → right, **dynamics**
319
+ (`plot_history`), **best trajectory** (`plot_best_trajectory`), **best
320
+ solution heatmap** (`plot_solution_heatmap`), and **parallel-population**
321
+ evolution (`plot_population_evolution`).
322
+
323
+ #### Default annealing schedule
324
+
325
+ <p align="center">
326
+ <img src="data/fig/gallery/schedule_default.png" width="520" alt="Default linear bg schedule from -3.0 to +0.1">
327
+ </p>
328
+
329
+ #### Maximum Independent Set (N=40, 3-regular)
330
+
331
+ <p align="center">
332
+ <img src="data/fig/gallery/history_mis.png" width="900" alt="MIS loss/penalty/diversity dynamics">
333
+ </p>
334
+ <p align="center">
335
+ <img src="data/fig/gallery/best_mis.png" width="440">
336
+ <img src="data/fig/gallery/solution_mis.png" width="440">
337
+ <img src="data/fig/gallery/population_mis.png" width="440">
338
+ </p>
339
+
340
+ #### Max-Cut (Erdős–Rényi, N=40, p=0.15)
341
+
342
+ <p align="center">
343
+ <img src="data/fig/gallery/history_maxcut.png" width="900">
344
+ </p>
345
+ <p align="center">
346
+ <img src="data/fig/gallery/best_maxcut.png" width="440">
347
+ <img src="data/fig/gallery/solution_maxcut.png" width="440">
348
+ <img src="data/fig/gallery/population_maxcut.png" width="440">
349
+ </p>
350
+
351
+ #### Graph coloring (N=30, 4-regular, K=3)
352
+
353
+ <p align="center">
354
+ <img src="data/fig/gallery/history_coloring.png" width="900">
355
+ </p>
356
+ <p align="center">
357
+ <img src="data/fig/gallery/best_coloring.png" width="440">
358
+ <img src="data/fig/gallery/population_coloring.png" width="440">
359
+ </p>
360
+
361
+ #### Ising 1D ferromagnet (N=32, J=1, periodic)
362
+
363
+ <p align="center">
364
+ <img src="data/fig/gallery/history_ising1d.png" width="900">
365
+ </p>
366
+ <p align="center">
367
+ <img src="data/fig/gallery/best_ising1d.png" width="440">
368
+ <img src="data/fig/gallery/solution_ising1d.png" width="440">
369
+ <img src="data/fig/gallery/population_ising1d.png" width="440">
370
+ </p>
371
+
372
+ #### Edwards–Anderson 3D spin glass (L=4, seed=0)
373
+
374
+ <p align="center">
375
+ <img src="data/fig/gallery/history_ea3d.png" width="900">
376
+ </p>
377
+ <p align="center">
378
+ <img src="data/fig/gallery/best_ea3d.png" width="440">
379
+ <img src="data/fig/gallery/solution_ea3d.png" width="440">
380
+ <img src="data/fig/gallery/population_ea3d.png" width="440">
381
+ </p>
382
+
383
+ #### Sherrington–Kirkpatrick mean-field spin glass (N=80)
384
+
385
+ <p align="center">
386
+ <img src="data/fig/gallery/history_sk.png" width="900">
387
+ </p>
388
+ <p align="center">
389
+ <img src="data/fig/gallery/best_sk.png" width="440">
390
+ <img src="data/fig/gallery/solution_sk.png" width="440">
391
+ <img src="data/fig/gallery/population_sk.png" width="440">
392
+ </p>
393
+
394
+ #### Binary perceptron (N=40, α=0.4)
395
+
396
+ <p align="center">
397
+ <img src="data/fig/gallery/history_perceptron.png" width="900">
398
+ </p>
399
+ <p align="center">
400
+ <img src="data/fig/gallery/best_perceptron.png" width="440">
401
+ <img src="data/fig/gallery/solution_perceptron.png" width="440">
402
+ <img src="data/fig/gallery/population_perceptron.png" width="440">
403
+ </p>
404
+
405
+ #### Hopfield memory (N=64, P=3)
406
+
407
+ <p align="center">
408
+ <img src="data/fig/gallery/history_hopfield.png" width="900">
409
+ </p>
410
+ <p align="center">
411
+ <img src="data/fig/gallery/best_hopfield.png" width="440">
412
+ <img src="data/fig/gallery/solution_hopfield.png" width="440">
413
+ <img src="data/fig/gallery/population_hopfield.png" width="440">
414
+ </p>
415
+
416
+ ## Verified correctness
417
+
418
+ We run QQA against a ground truth or a strong baseline for every problem in
419
+ the catalog via `scripts/verify_all_problems.py`. The most recent sweep
420
+ (29 instances across 9 problem families) is stored in
421
+ [`tasks/verification_report.md`](tasks/verification_report.md); headline
422
+ numbers:
423
+
424
+ | Problem | Instances | Reference | QQA |
425
+ | --- | --- | --- | --- |
426
+ | Maximum Independent Set | 3×(3-reg, N=50) | networkx degree-greedy | **matches or beats greedy on all seeds** |
427
+ | MaxCut | 3×ER (N=30/40/60) | best-of-400 random partition | **+6 / +16 / +27 edges over random** |
428
+ | MaxClique | 3×ER (N=30/40/50) | nx.approximation.max_clique | **+1 vertex on every seed** |
429
+ | Graph coloring (K=3) | 3×(3-reg, N=40) | Welsh–Powell greedy | **0 conflicts on all seeds** |
430
+ | Ising 1D ferromagnet | N ∈ {16, 32, 64} | exact E₀ = −N | **gap = 0 on every size** |
431
+ | Edwards–Anderson 2D L=3 | 3 seeds | brute force (2⁹) | **matches exact ground state** |
432
+ | Edwards–Anderson 3D L=4 | 2 seeds | — | E/N ≈ −1.61 (no exact solver) |
433
+ | Sherrington–Kirkpatrick | N ∈ {50, 100, 200} | Parisi e₀ = −0.7632 | **≤ 3.2 % gap at N=200** |
434
+ | Binary perceptron | α ∈ {0.3, 0.5, 0.7} | teacher reaches 0 errors | **0 errors on all α** |
435
+ | Hopfield memory | (N, P) ∈ {(32,2),(64,3),(128,4)} | ≥ 0.95 overlap | **overlap = 1.0** |
436
+
437
+ Overall: **29 / 29 checks pass (100 %)**. Re-run with
438
+ `uv run python scripts/verify_all_problems.py`; the command regenerates the
439
+ Markdown report in place.
440
+
441
+ ## Notebooks
442
+
443
+ Nine runnable notebooks live in [`examples/`](examples/). Each notebook has
444
+ an **Open in Colab** badge in its first cell and auto-installs `qqa` on Colab.
445
+
446
+ 0. `00_colab_quickstart.ipynb` — one-click tour of every problem
447
+ 1. `01_maximum_independent_set.ipynb`
448
+ 2. `02_graph_coloring.ipynb`
449
+ 3. `03_max_cut.ipynb`
450
+ 4. `04_edwards_anderson_3d.ipynb`
451
+ 5. `05_sherrington_kirkpatrick.ipynb`
452
+ 6. `06_binary_perceptron.ipynb`
453
+ 7. `07_hopfield_memory.ipynb`
454
+ 8. `08_parallel_benchmark.ipynb`
455
+
456
+ Regenerate them deterministically with
457
+ `uv run python scripts/_generate_notebooks.py`.
458
+
459
+ ## Documentation
460
+
461
+ ```bash
462
+ uv run mkdocs serve # http://127.0.0.1:8000
463
+ uv run mkdocs build --strict # produces site/
464
+ ```
465
+
466
+ The docs cover quickstart, the full problem catalog with mathematical
467
+ definitions, GUI walk-through, visualization guide, auto-generated API
468
+ reference, and a migration guide from 0.2.x.
469
+
470
+ ## Scripts
471
+
472
+ | Script | Purpose |
473
+ | ------ | ------- |
474
+ | `scripts/demo_mis.py` | Minimal MIS end-to-end demo |
475
+ | `scripts/demo_coloring.py` | 3-coloring end-to-end demo |
476
+ | `scripts/demo_parallel.py` | Parallel instances of MIS |
477
+ | `scripts/bench_er_small.py` | Benchmark on bundled ER-small MIS dataset |
478
+ | `scripts/_generate_notebooks.py` | Regenerate the shipped example notebooks |
479
+
480
+ Run any script via `uv run python scripts/<name>.py`.
481
+
482
+ ## Repository layout
483
+
484
+ ```
485
+ QQA4CO/
486
+ ├── src/qqa/ # importable package
487
+ │ ├── __init__.py
488
+ │ ├── annealing.py
489
+ │ ├── callbacks.py
490
+ │ ├── cli.py
491
+ │ ├── datasets.py
492
+ │ ├── legacy.py
493
+ │ ├── problems/ # qubo.py / categorical.py / spin.py
494
+ │ ├── relaxation.py
495
+ │ ├── schedule.py
496
+ │ ├── utils.py
497
+ │ └── visualization.py
498
+ ├── app/ # Streamlit dashboard
499
+ │ ├── streamlit_app.py
500
+ │ └── pages/
501
+ ├── docs/ # MkDocs site sources
502
+ ├── examples/ # 8 example notebooks
503
+ ├── scripts/ # demo / benchmark scripts
504
+ ├── tests/ # pytest suite
505
+ ├── data/ # bundled datasets
506
+ ├── pyproject.toml
507
+ ├── CHANGELOG.md
508
+ ├── CONTRIBUTING.md
509
+ ├── CITATION.cff
510
+ └── README.md
511
+ ```
512
+
513
+ ## Contributing
514
+
515
+ Issues and pull requests are welcome. See
516
+ [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup, style, and test commands.
517
+
518
+ ## License
519
+
520
+ BSD-3-Clause — see [`LICENCE.txt`](LICENCE.txt).
521
+
522
+ ## Cite
523
+
524
+ ```bibtex
525
+ @inproceedings{ichikawa2025qqa,
526
+ title = {Continuous Tensor Relaxation for Finding Diverse Solutions in Combinatorial Optimization},
527
+ author = {Ichikawa, Yuma and Arai, Yamato},
528
+ booktitle = {International Conference on Learning Representations (ICLR)},
529
+ year = {2025},
530
+ url = {https://openreview.net/forum?id=9EfBeXaXf0}
531
+ }
532
+ ```