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 +43 -0
- qqa-0.3.0/CHANGELOG.md +47 -0
- qqa-0.3.0/LICENCE.txt +12 -0
- qqa-0.3.0/PKG-INFO +532 -0
- qqa-0.3.0/README.md +449 -0
- qqa-0.3.0/pyproject.toml +123 -0
- qqa-0.3.0/src/qqa/__init__.py +104 -0
- qqa-0.3.0/src/qqa/annealing.py +279 -0
- qqa-0.3.0/src/qqa/callbacks.py +171 -0
- qqa-0.3.0/src/qqa/cli.py +375 -0
- qqa-0.3.0/src/qqa/datasets.py +248 -0
- qqa-0.3.0/src/qqa/legacy.py +200 -0
- qqa-0.3.0/src/qqa/problems/__init__.py +80 -0
- qqa-0.3.0/src/qqa/problems/base.py +63 -0
- qqa-0.3.0/src/qqa/problems/categorical.py +115 -0
- qqa-0.3.0/src/qqa/problems/extras.py +616 -0
- qqa-0.3.0/src/qqa/problems/qubo.py +273 -0
- qqa-0.3.0/src/qqa/problems/spin.py +448 -0
- qqa-0.3.0/src/qqa/problems/user.py +180 -0
- qqa-0.3.0/src/qqa/relaxation.py +197 -0
- qqa-0.3.0/src/qqa/schedule.py +27 -0
- qqa-0.3.0/src/qqa/utils.py +91 -0
- qqa-0.3.0/src/qqa/visualization.py +710 -0
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
|
+
```
|