Skip to content

Commit 9cbf579

Browse files
authored
examples: correct the bitstring layout and drop stale docs (#14)
The count_dict.json format section in examples/README.md had the spin halves inverted. It said the first NORB bits are alpha and the last NORB are beta; qiskit-addon-sqd does the opposite -- _prepare_ci_strings() takes samples[:, norb:] as alpha and samples[:, :norb] as beta, i.e. the layout is [beta | alpha]. Anyone building a counts file from that sentence would have swapped their spin sectors. The error went unnoticed because all three example bitstrings were (5,5) symmetric and so read the same either way; the first is now the Hartree-Fock configuration, which is unambiguous. Also documents the within-half order (orbital 0 is the rightmost bit), which was missing entirely. Other corrections, all drift from recent merges: - --samples is no longer uniform random (it draws at the target Hamming weights), and the text now says plainly that the energy from random determinants is not meaningful. - The notebook section still described uniform-random bitstrings plus HF initial_occupancies and quoted ~-76.19 Ha. It now uses the bundled count_dict_h2o.json and reaches ~-76.236 Ha. - Dropped the instruction to install qiskit-addon-sqd from @main, in both the README and run_sqd_sbd.py's module docstring. The distributed (SPMD) support is in 0.13.1 -- is_control_process and broadcast are both present in the release -- which is what pyproject.toml already requires. Dropped the matching "fork" reference too. - The lead run_sqd_sbd.py example, in both the README and the docstring, now passes --counts count_dict_h2o.json rather than relying on random samples, and the file itself is documented. - Backend list gained gpu-omp, with a note that it links a different OpenMP runtime (libnvomp) and is normally its own install. "Both backends" -> all compiled backends, since there are three. - Notebook run command uses pytest --nbmake (what CI runs); nbconvert is not a declared dependency.
1 parent 29be7e5 commit 9cbf579

2 files changed

Lines changed: 48 additions & 37 deletions

File tree

python/examples/README.md

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Examples demonstrating SBD's capabilities for quantum chemistry calculations.
55
## Overview
66

77
- **Communication:** MPI for distributed computing
8-
- **Backends:** CPU (OpenMP) and GPU (CUDA), switchable at runtime via `device` parameter
8+
- **Backends:** CPU (host OpenMP), GPU (NVHPC Thrust) and GPU (OpenMP target offload), switchable at runtime via `device` parameter
99

1010
## Extra dependencies (only for the SQD examples)
1111

@@ -18,17 +18,14 @@ extra Python packages. Install them once into the same venv:
1818

1919
```bash
2020
source ~/venvs/<your-sbd-venv>/bin/activate
21-
pip install pyscf qiskit \
22-
"git+https://github.com/Qiskit/qiskit-addon-sqd@main"
21+
pip install pyscf qiskit "qiskit-addon-sqd>=0.13.1"
2322
```
2423

2524
- **`pyscf`** — reads FCIDUMP, restores 4-fold integral symmetry.
2625
- **`qiskit`**`BitArray` type for sampled-bitstring input.
2726
- **`qiskit-addon-sqd`** — the SQD loop (`diagonalize_fermionic_hamiltonian`).
28-
Requires the **distributed (SPMD) support** that calls `sci_solver` on
29-
every MPI rank. That now lives in upstream `qiskit-addon-sqd`, but is not
30-
yet in a PyPI release, so install from `@main` for now. Once a release
31-
includes it, plain `pip install qiskit-addon-sqd` will suffice.
27+
Needs the **distributed (SPMD) support** that calls `sci_solver` on every MPI
28+
rank; that shipped in 0.13.1, so the PyPI release suffices.
3229

3330
`pyscf` is the heavy one (~150 MB plus `h5py`). qiskit-addon-sqd is a thin
3431
layer on top of upstream qiskit, so most of `qiskit`'s ~300 MB is what
@@ -68,13 +65,16 @@ Run `python run_sbd_diag.py --help` for the full list.
6865
Runs the self-consistent SQD workflow (qiskit-addon-sqd) using SBD as the
6966
eigensolver backend. Supports two bitstring input modes:
7067

71-
- `--counts FILE` — load hardware bitstrings from a count_dict.json
72-
- `--samples N` — generate N uniform random bitstrings (default)
68+
- `--counts FILE` — load bitstrings from a count_dict.json
69+
- `--samples N` — generate N random bitstrings at the target Hamming weights
70+
(default). A plumbing check only: random determinants give a random subspace,
71+
so the energy is not meaningful. Use `--counts` for real results.
7372

7473
```bash
75-
# H2O with random samples (default)
74+
# H2O with the bundled counts file (275 bitstrings -> ~ -76.236 Ha)
7675
mpirun -np 4 python run_sqd_sbd.py \
7776
--fcidump ../../vendor/sbd-upstream/data/h2o/fcidump.txt \
77+
--counts count_dict_h2o.json \
7878
--device cpu \
7979
--adet_comm_size 2 --bdet_comm_size 2
8080

@@ -95,28 +95,39 @@ mpirun -np 8 python run_sqd_sbd.py \
9595
```
9696

9797
**count_dict.json format:** A JSON object mapping bitstrings to shot counts, as
98-
produced by a quantum device or simulator. Each bitstring has length `2 × NORB`
99-
the first `NORB` bits are alpha (spin-up) orbitals and the last `NORB` are beta
100-
(spin-down):
98+
produced by a quantum device or simulator. Each bitstring has length `2 × NORB`
99+
and is laid out as **`[beta | alpha]`**: the first `NORB` bits are beta
100+
(spin-down), the last `NORB` are alpha (spin-up), and within each half **orbital 0
101+
is the rightmost bit**. qiskit-addon-sqd postselects the last `NORB` bits on
102+
`num_elec_a` and the first `NORB` on `num_elec_b`.
103+
104+
For H2O (NORB=24, 5α+5β) the Hartree–Fock configuration — the five lowest
105+
orbitals doubly occupied — is therefore `"0"*19 + "1"*5` in *both* halves:
101106

102107
```json
103108
{
104-
"010000000010001010000001010000000001000010100100": 16,
105-
"000010001110000000000010001001000110000000000100": 12,
106-
"000101000000010011000000000010000000001001000110": 8
109+
"000000000000000000011111000000000000000000011111": 16,
110+
"010000000010001010000001010000000001000010100100": 12,
111+
"000010001110000000000010001001000110000000000100": 8
107112
}
108113
```
109114

110-
Supply your own `count_dict.json` produced by a quantum device or simulator.
111-
The bitstring length must be `2 × NORB` — e.g. for [`../../vendor/sbd-upstream/data/h2o/fcidump.txt`](../../vendor/sbd-upstream/data/h2o/fcidump.txt) that is NORB=24 (5α+5β electrons).
115+
Bitstrings whose halves do not hold exactly `num_elec_a` / `num_elec_b` ones are
116+
dropped by postselection, so a file of uniform-random strings yields nothing
117+
usable — for H2O only `C(24,5)² / 4²⁴ ≈ 6e-6` of them qualify.
118+
119+
[`count_dict_h2o.json`](./count_dict_h2o.json) in this directory is a ready-made
120+
H2O example: 275 bitstrings taken from the vendored `h2o-1em3-alpha.txt`
121+
determinant list, giving a 275 × 275 = 75,625-determinant subspace at
122+
≈ -76.236 Ha.
112123

113124
**Key options:** `--fcidump` (required), `--counts`, `--samples`,
114125
`--samples_per_batch`, `--num_batches`, `--max_iterations`, `--device`,
115126
MPI decomposition flags. SBD solver flags (`--method`, `--tolerance`,
116127
`--iteration`, etc.) have sensible defaults; run `python run_sqd_sbd.py --help`
117128
for the full list.
118129

119-
**Requirements:** see [Extra dependencies](#extra-dependencies-only-for-the-sqd-examples) above (`pyscf`, `qiskit`, `qiskit-addon-sqd` fork).
130+
**Requirements:** see [Extra dependencies](#extra-dependencies-only-for-the-sqd-examples) above (`pyscf`, `qiskit`, `qiskit-addon-sqd`).
120131

121132
#### SQD Parameter Guide
122133

@@ -131,7 +142,7 @@ postselection).
131142
| Parameter | What it controls | Typical values |
132143
|-----------|-----------------|----------------|
133144
| `--counts FILE` | Load hardware bitstrings from a JSON file (use one or the other) | 10K–1M+ shots |
134-
| `--samples N` | Generate N uniform random bitstrings for testing (default) | 10K–1M+ |
145+
| `--samples N` | Generate N random bitstrings at the target Hamming weights; plumbing check only, energy not meaningful | any |
135146
| `--samples_per_batch` | Subspace dimension per batch (accuracy vs. cost) | 300–800 (small), 1M+ (production) |
136147
| `--num_batches` | Independent subsamples for averaging occupancies | 3–10 (small), up to 100 (large) |
137148
| `--max_iterations` | SQD self-consistent loop iterations (not SBD `--iteration`) | 3–5 |
@@ -143,14 +154,13 @@ increases wall time linearly but does not require more ranks.
143154

144155
### 3. run_sqd_sbd.ipynb — Jupyter walkthrough (serial)
145156

146-
Interactive single-rank companion to `run_sqd_sbd.py`. Same SQD self-
147-
consistent loop on h2o, but runs inside a Jupyter kernel
148-
(`MPI.COMM_WORLD` size 1). Uses uniform-random bitstrings + HF
149-
`initial_occupancies` as a self-contained demo. Converges to ~−76.19 Ha
150-
in a few seconds on CPU.
157+
Interactive single-rank companion to `run_sqd_sbd.py`. Same SQD self-consistent
158+
loop on h2o, but inside a Jupyter kernel (`MPI.COMM_WORLD` size 1). Uses the
159+
bundled [`count_dict_h2o.json`](./count_dict_h2o.json) (275 bitstrings → 75,625
160+
determinants) and reaches ≈ −76.236 Ha in a few seconds on CPU.
151161

152162
```bash
153-
jupyter nbconvert --to notebook --execute --inplace run_sqd_sbd.ipynb
163+
pytest --nbmake run_sqd_sbd.ipynb # what CI runs; needs the nbtest extra
154164
# or open it in JupyterLab and step through the cells
155165
```
156166

@@ -169,14 +179,19 @@ When using more than one rank, specify at least `--adet_comm_size`. Examples:
169179

170180
## Backend Selection
171181

172-
Both backends are loaded at import time. Select per-call via `--device`:
182+
All compiled backends load eagerly at import. Select per-call via `--device`:
173183

174184
```bash
175-
--device cpu # OpenMP (default)
176-
--device gpu # CUDA (requires NVIDIA GPU + HPC SDK build)
177-
--device auto # GPU if available, else CPU
185+
--device cpu # host OpenMP (default)
186+
--device gpu # NVHPC Thrust (requires NVIDIA GPU + HPC SDK build)
187+
--device gpu-omp # NVHPC OpenMP target offload
188+
--device auto # GPU if available, else CPU
178189
```
179190

191+
`gpu-omp` links a different OpenMP runtime (`libnvomp`) than `cpu`/`gpu`, so it is
192+
normally built into its own install — see the [Python Bindings README](../../README.md).
193+
`sbd.available_backends()` reports what the current install actually has.
194+
180195
Within Python, backends can also be switched at runtime without re-initialization:
181196

182197
```python

python/examples/run_sqd_sbd.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@
1212

1313
"""SQD loop using SBD solver with qiskit-addon-sqd.
1414
15-
Requires qiskit-addon-sqd with distributed (SPMD) support. This currently
16-
lives on upstream main (not yet in a PyPI release):
17-
pip install "git+https://github.com/Qiskit/qiskit-addon-sqd@main"
18-
Once a release includes it, plain `pip install qiskit-addon-sqd` will suffice.
19-
2015
Runs the self-consistent SQD workflow: subsample bitstrings into batches,
2116
diagonalize via SBD, update occupancies, repeat.
2217
@@ -25,9 +20,10 @@
2520
--samples N generate N random bitstrings at the target Hamming weights
2621
2722
Usage (MPI required):
28-
# H2O with bundled data, random samples
23+
# H2O with the bundled counts file (275 bitstrings -> ~ -76.236 Ha)
2924
mpirun -np 4 python run_sqd_sbd.py \
30-
--fcidump ../../vendor/sbd-upstream/data/h2o/fcidump.txt
25+
--fcidump ../../vendor/sbd-upstream/data/h2o/fcidump.txt \
26+
--counts count_dict_h2o.json
3127
3228
# Custom FCIDUMP with hardware bitstrings
3329
mpirun -np 8 python run_sqd_sbd.py \

0 commit comments

Comments
 (0)