A toolbox for measuring expectation values of quantum Hamiltonians using commuting-operator grouping (cmopt) and shadow grouping (sg).
uv syncThis installs all Python dependencies in a virtual environment, including Qiskit, PySCF, matplotlib, numpy, and the local sg library.
To run any Python script afterwards:
uv run python src/<path>/<script>.pyFrom the project root, enter Julia's Pkg mode (press ]) and run:
(CommuteMeasure) pkg> activate .
(CommuteMeasure) pkg> instantiateThis installs all Julia dependencies (Yao, Graphs, Plots, etc.) and the local packages under lib/.
To run a Julia script:
julia --project=. src/<path>/<script>.jlCommuteMeasure/
├── src/ # source code: Hamiltonian generation, experiment
│ # processing (quantum + classical), and plotting
├── data/ # where experiment data goes (see below)
├── figs/ # output figures
├── lib/
│ ├── CommuteMeasureAPI # Build and run cmopt experiments
│ ├── PostProcess # Process cmopt experiment results
│ ├── SGinterface # Build and process SG experiments
│ ├── sg # Shadow Grouping algorithm (Python)
│ └── jlPauliop.zip # Pauli arithmetic utilities
└── docs/ # paper, presentation, notes
Place your experiment data under data/ using the following convention. Downstream code will pick it up automatically.
data/
└── <TASK>/ # e.g. Molecule, QECC, Rand2rdm, kLocal
└── <SUBTASK>/ # e.g. figa, figb
└── <METHOD>/ # cmopt or sg
For example, data/QECC/figa/cmopt holds data for the QECC task, figure a, using the cmopt method.
Each method directory corresponds to one or more quantum states, stored in state.mat:
- Single state: key
state - Multiple states: keys
state_1,state_2, ...
- cmopt: settings live in
setting_1/,setting_2/, ... subdirectories. - sg: settings live under
settings/PPPPsubdirectories (e.g.settings/XXXX).
Each setting folder contains:
| File | Key | Description |
|---|---|---|
unitary.mat |
unitary |
Unitary matrix of the circuit |
probability.mat |
probability |
Theoretical probability distribution |
experiment_probability.mat |
probability |
Measured probability distribution |
After running experiments, place your processed diagonal elements (the measured probability distribution) into experiment_probability.mat inside the corresponding setting folder.
SG experiment directories also need:
| File | Description |
|---|---|
hamiltonian.txt |
Target Hamiltonian |
required_shots.txt |
Required number of shots |
setting_distribute.json |
Measurement setting distribution |
If you don't have real experiment data, use fake_experiment_data to generate synthetic data. It copies the theoretical probability.mat to experiment_probability.mat, simulating a noiseless experiment where measurement matches theory exactly.
julia> using CommuteMeasure
julia> fake_experiment_data("data/QECC/figa/cmopt")This recursively walks the given directory and copies every probability.mat to experiment_probability.mat. See src/Molecule/figureb/fakedata.jl for a standalone example.
All scripts are run from the project root. Use uv run python for Python scripts and julia --project=. for Julia scripts.
-
Generate Hamiltonians:
uv run python src/Molecule/datagen/hamiltonian.py
-
Prepare experiment data (or fake it):
julia --project=. src/Molecule/figureb/fakedata.jl
-
Process experiment results:
julia --project=. src/Molecule/figureb/qproc.jl # quantum processing julia --project=. src/Molecule/figureb/cproc.jl # classical processing
-
Plot:
uv run python src/Molecule/plot.py
| Task | Julia | Python |
|---|---|---|
| Molecule/figa | src/Molecule/figurea/cmopt.jl, sg.jl |
src/Molecule/figurea/fine_plot/ |
| Molecule/figb | src/Molecule/figureb/qproc.jl, cproc.jl |
src/Molecule/datagen/hamiltonian.py, src/Molecule/plot.py |
| QECC/figa | src/QECC/figa/qproc.jl, cproc.jl, sg.jl |
src/QECC/figa/plotting.py |
| QECC/figb | src/QECC/figb/figb.jl |
src/QECC/figb/plot_3d_bar.py |
| Rand2rdm | src/Rand2rdm/qproc.jl, cproc_hamil.jl, cproc_each.jl |
src/Rand2rdm/plot_hamil.py, plot_each.py |
| kLocality/figa | src/kLocality/figa/qproc.jl, cproc.jl |
src/kLocality/figa/plot.py |
The depth branch contains code for analyzing and comparing circuit depths across different commuting-operator grouping strategies. It uses the Knill-Gottesman theorem to efficiently simulate Clifford (stabilizer) circuits at scale, enabling large-scale depth benchmarks without full state-vector simulation.
Switch to the branch:
git checkout depthThe branch includes:
| Directory | Description |
|---|---|
circuit_gen/ |
Generate quantum circuits from grouped Hamiltonians |
depth_compare/ |
Depth comparison across models (c6h6, lattice Ising, QEC, XXZ) and grouping strategies (CCG, CM, find_basis) |
data_plot/ |
Plotting scripts for depth benchmark results |
Setup and run:
uv sync
uv run python depth_compare/<script>.pyThe opt_ccg branch contains code for simulating larger molecular systems without real experiment data — everything runs in classical simulation (no hardware backend needed).
git checkout opt_ccgThe main code entry is under whz/code/:
| Directory | Description |
|---|---|
whz/code/2dheisenberg/ |
2D Heisenberg model |
whz/code/chemistry/ |
Quantum chemistry (H4, etc.) |
Setup and run:
uv sync
julia --project=. whz/code/2dheisenberg/qproc.jlThe other_method branch contains implementations of additional commuting-operator measurement schemes: ShadowGrouping (SG), Overlapped Grouping Measurement (OGM), Classical Shadows (CS), and Derandomized Classical Shadows.
git checkout other_methodThe main entry point is jupyter.py. Run it with:
uv sync
uv run python jupyter.py