final first commit

This commit is contained in:
2026-05-19 17:19:36 +08:00
commit b199e2105e
114 changed files with 6844 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
# Example scripts
This folder contains example bash scripts that execute the `compare.py` benchmark for different circuit configurations and different libraries.
The available circuits are described in the main ``README.md`` of this repository
(some of them are presented in Table 1 of the [HyQuas paper](https://dl.acm.org/doi/pdf/10.1145/3447818.3460357)).
The provided scripts are the following:
### `qibo.sh`
Execute a specific circuit with different sizes and different Qibo backends.
By default, it executes the circuit with all backends (NumPy, TensorFlow, Qibotf and Qibojit) and with circuit sizes from 3 to 31 (28 for NumPy).
If different platforms are available, it will use the default one.
It is straightforward to edit the bash script to fine tune the variation ranges and the number of repetitions for each circuit size.
A starter code to plot the results is available in ``plots/qibo.ipynb``.
Options:
- ``circuit``: circuit to execute (default: ``qft``)
- ``precision``: ``single`` or ``double`` (default: ``double``)
### ``qibojit.sh``
Similar to ``qibo.sh``, but uses only qibojit. Useful to compare the performance across different platforms and different GPUs.
A starter code to plot the results is available in ``plots/qibojit.ipynb``.
Options:
- ``filename``: where to store the logs (default: ``qibojit.dat``)
- ``circuit``: circuit to execute (default: ``qft``)
- ``precision``: ``single`` or ``double`` (default: ``double``)
- ``nreps``: number of repetitions for each circuit size (default: ``10``)
- ``platform``: platform to use for simulation (default: ``cupy``)
### ``qibo_circuits.sh``
Execute a set of circuits for different circuit sizes, using a specific backend.
Useful to plot the breakdown of execution times (starter code in ``plots/qibo.ipynb``).
Options:
- ``backend``: backend to use for simulation (default: ``qibojit``)
- ``precision``: ``single`` or ``double`` (default: ``double``)
- ``nreps``: number of repetitions for each circuit and size (default: ``10``)
### ``library_single.sh``
Execute a set of circuits for different circuit sizes, using a variety of different libraries.
This script focuses on libraries that support single precision simulation.
It is straightforward to edit the bash script to change the circuit sizes and the libraries.
A starter code to plot the results is available in ``plots/libraries.ipynb``.
Options:
- ``nreps``: number of repetitions for each circuit size (default: ``10``)
### ``library_double.sh``
Same as ``library_single.sh``, but with libraries that support double precision simulation.
Options:
- ``nreps``: number of repetitions for each circuit size (default: ``10``)

View File

@@ -0,0 +1 @@
{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}

View File

@@ -0,0 +1 @@
{"MPI_enabled": true, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}

View File

@@ -0,0 +1 @@
{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": true, "expectation_enabled": true}

View File

@@ -0,0 +1,33 @@
#! /usr/bin/bash
# Generates data for the evolution scaling with dt using the dense form of the Hamiltonian
# Command-line parameters
: "${nqubits:=10}"
: "${precision:=double}"
: "${filename:=evolution.dat}"
: "${nreps:=5}"
# GPU backends
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
do
for backend in qibojit tensorflow
do
CUDA_VISIBLE_DEVICES=0 python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
--backend $backend --precision $precision --dense
echo
done
done
# CPU backends
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
do
for backend in numpy tensorflow
do
CUDA_VISIBLE_DEVICES="" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
--backend $backend --precision $precision --dense
echo
done
done

View File

@@ -0,0 +1,45 @@
#! /usr/bin/bash
# Generates data for the evolution scaling with dt using the Trotter decomposition
# Command-line parameters
: "${nqubits:=10}"
: "${precision:=double}"
: "${filename:=evolution.dat}"
: "${nreps:=10}"
# GPU qibojit backend
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
do
for platform in cupy cuquantum
do
CUDA_VISIBLE_DEVICES="0" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
--backend qibojit --platform $platform --precision $precision
echo
done
done
# GPU tensorflow and qibotf backends
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
do
for backend in qibotf tensorflow
do
CUDA_VISIBLE_DEVICES="0" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
--backend $backend --precision $precision
echo
done
done
# CPU all backends
for dt in 0.1 0.095 0.09 0.085 0.08 0.075 0.07 0.065 0.06 0.055 0.05 0.045 \
0.04 0.035 0.03 0.025 0.02 0.015 0.01 0.005
do
for backend in qibojit qibotf tensorflow numpy
do
CUDA_VISIBLE_DEVICES="" python evolution.py --nqubits $nqubits --dt $dt --filename $filename --nreps $nreps \
--backend $backend --precision $precision
echo
done
done

View File

@@ -0,0 +1,34 @@
#! /usr/bin/bash
# Generate logs for fusion comparison on different circuits for all qibojit platforms
# Command-line parameters
: "${filename:=qibojit_fusion.dat}"
: "${precision:=double}"
: "${nqubits:=30}"
: "${nreps_cpu:=3}"
: "${nreps_gpu:=5}"
for circuit in qft variational supremacy bv qv
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=cupy,max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=cupy --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=cuquantum,max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=cuquantum --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=numba,max_qubits=2 --nreps $nreps_cpu --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=numba --nreps $nreps_cpu --precision $precision
echo
done

View File

@@ -0,0 +1,24 @@
#! /usr/bin/bash
# Generates data for the bar plot comparing different libraries in double precision
: "${nreps:=10}"
: "${nqubits:=10}"
: "${filename_cpu:=libraries_cpu.dat}"
: "${filename_gpu:=libraries_gpu.dat}"
for circuit in qft variational bv supremacy qv
do
for library in qibo qiskit qulacs projectq hybridq
do
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library $library --nreps $nreps --precision double
echo
done
for library in qibo qiskit-gpu qulacs-gpu hybridq-gpu
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library $library --nreps $nreps --precision double
echo
done
done

View File

@@ -0,0 +1,42 @@
#! /usr/bin/bash
# Generate logs for library comparison on different circuits with gate fusion enabled
# Command-line parameters
: "${filename_cpu:=libraries_fusion_cpu.dat}"
: "${filename_gpu:=libraries_fusion_gpu.dat}"
: "${precision:=single}"
: "${nqubits:=30}"
: "${nreps_cpu:=3}"
: "${nreps_gpu:=5}"
for circuit in qft variational supremacy bv qv
do
# GPU benchmarks
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qibo \
--library-options backend=qibojit,platform=cupy,max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qibo \
--library-options backend=qibojit,platform=cuquantum,max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qsim-gpu \
--library-options max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qsim-cuquantum \
--library-options max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu --library qiskit-gpu \
--library-options max_qubits=2 --nreps $nreps_gpu --precision $precision
echo
# CPU benchmarks
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu --library qibo \
--library-options backend=qibojit,platform=numba,max_qubits=2 --nreps $nreps_cpu --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu --library qsim \
--library-options max_qubits=2 --nreps $nreps_cpu --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu --library qiskit \
--library-options max_qubits=2 --nreps $nreps_cpu --precision $precision
echo
done

View File

@@ -0,0 +1,24 @@
#! /usr/bin/bash
# Generates data for the bar plot comparing different libraries in single precision
: "${nreps:=10}"
: "${nqubits:=20}"
: "${filename_cpu:=libraries_cpu.dat}"
: "${filename_gpu:=libraries_gpu.dat}"
for circuit in qft variational bv supremacy qv
do
for library in qibo qiskit qsim hybridq
do
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library $library --nreps $nreps --precision single
echo
done
for library in qibo qiskit-gpu qsim-gpu qsim-cuquantum qcgpu hybridq-gpu
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library $library --nreps $nreps --precision single
echo
done
done

View File

@@ -0,0 +1,34 @@
# Generates the multigpu bar plot
# Assumes a machine with four GPUs
: "${filename:=multigpu.dat}"
: "${precision:=double}"
: "${nreps:=1}"
export CUDA_VISIBLE_DEVICES=0,1,2,3
for circuit in qft variational supremacy qv bv
do
for backend in qibojit qibotf
do
python compare.py --circuit $circuit --nqubits 32 --filename $filename \
--library-options backend=$backend,accelerators=1/GPU:0+1/GPU:1+1/GPU:2+1/GPU:3 \
--nreps $nreps --precision $precision
echo
done
for backend in qibojit qibotf
do
python compare.py --circuit $circuit --nqubits 32 --filename $filename \
--library-options backend=$backend,accelerators=2/GPU:2+2/GPU:3 \
--nreps $nreps --precision $precision
echo
done
for backend in qibojit qibotf
do
python compare.py --circuit $circuit --nqubits 32 --filename $filename \
--library-options backend=$backend,accelerators=4/GPU:3 \
--nreps $nreps --precision $precision
echo
done
done

View File

@@ -0,0 +1,85 @@
#! /usr/bin/bash
# Generates data for the scaling plot (vs nqubits) using all qibo backends
# Command-line parameters
: "${circuit:=qft}"
: "${precision:=double}"
: "${nreps_a:=20}" # for nqubits < 25
: "${nreps_b:=3}" # for nqubits >= 25
: "${filename_cpu:=qibo_scaling_cpu.dat}"
: "${filename_gpu:=qibo_scaling_gpu.dat}"
# Qibojit backend
for nqubits in {3..24}
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library-options backend=qibojit,platform=cupy \
--nreps $nreps_a --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library-options backend=qibojit,platform=cuquantum \
--nreps $nreps_a --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library-options backend=qibojit,platform=numba \
--nreps $nreps_a --precision $precision
echo
done
for nqubits in {25..31}
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library-options backend=qibojit,platform=cupy \
--nreps $nreps_b --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library-options backend=qibojit,platform=cuquantum \
--nreps $nreps_b --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library-options backend=qibojit,platform=numba \
--nreps $nreps_b --precision $precision
echo
done
# TensorFlow and QiboTF backends
for nqubits in {3..24}
do
for backend in tensorflow qibotf
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library-options backend=$backend --nreps $nreps_a --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library-options backend=$backend --nreps $nreps_a --precision $precision
echo
done
done
for nqubits in {25..31}
do
for backend in tensorflow qibotf
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_gpu \
--library-options backend=$backend --nreps $nreps_b --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library-options backend=$backend --nreps $nreps_b --precision $precision
echo
done
done
# NumPy backend
for nqubits in {3..24}
do
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library-options backend=numpy --nreps $nreps_a --precision $precision
echo
done
for nqubits in {25..28}
do
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename_cpu \
--library-options backend=numpy --nreps $nreps_b --precision $precision
echo
done

View File

@@ -0,0 +1,23 @@
#! /usr/bin/bash
# Generates data for qibojit breakdown bar plot with dry run vs simulation
# Command-line parameters
: "${filename:=qibojit_breakdown.dat}"
: "${precision:=double}"
: "${circuit:=supremacy}"
: "${nreps_cpu:=5}"
: "${nreps_gpu:=10}"
for nqubits in 16 18 20 22 24 26 28
do
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=cupy --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES=0 python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=cuquantum --nreps $nreps_gpu --precision $precision
echo
CUDA_VISIBLE_DEVICES="" python compare.py --circuit $circuit --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=numba --nreps $nreps_cpu --precision $precision
echo
done

View File

@@ -0,0 +1,36 @@
#! /usr/bin/bash
# Script for 2-nodes-4-GPUs (2x4) configuration
# Command-line parameters
: "${circuit:=variational}"
: "${precision:=double}"
: "${nreps:=3}"
: "${filename:=qibotn_expectation_double_2x4.dat}"
node_list=/nodelist_2x4 #file containing the IP address of the resources, omit this if it is running on single-node-multi-gpu
for (nqubits = 10; nqubits <= 8000; nqubits += 100)
do
#echo '{"MPI_enabled": true, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}' > cu_tensornet_mpi_expectation.json #can be pre-generated or can include it in script. Here is using pre-generated.
mpirun -np 8 -hostfile $node_list python compare.py --circuit variational --circuit-options nlayers=3 --nqubits 4$nqubits --filename $filename \
--library-options backend=qibotn,platform=cutensornet,computation_settings=cu_tensornet_mpi_expectation.json \
--nreps $nreps --precision $precision
echo
#echo '{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": true, "expectation_enabled": true}' > cu_tensornet_nccl_expectation.json
mpirun -np 8 -hostfile $node_list python compare.py --circuit variational --circuit-options nlayers=3 --nqubits $nqubits --filename $filename \
--library-options backend=qibotn,platform=cutensornet,computation_settings=cu_tensornet_nccl_expectation.json \
--nreps $nreps --precision $precision
echo
#echo '{"MPI_enabled": false, "MPS_enabled": false, "NCCL_enabled": false, "expectation_enabled": true}' > cu_tensornet_expectation.json
python compare.py --circuit variational --circuit-options nlayers=3 --nqubits $nqubits --filename $filename \
--library-options backend=qibotn,platform=cutensornet,computation_settings=cu_tensornet_expectation.json \
--nreps $nreps --precision $precision
echo
python compare.py --circuit variational --circuit-options nlayers=3 --nqubits $nqubits --filename $filename \
--library-options backend=qibojit,platform=numba,expectation="XXXZ" \
--nreps $nreps --precision $precision
echo
done
: <<'END_COMMENT'
END_COMMENT

View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Lightweight local benchmark script (single node, small sweep)
set -euo pipefail
: "${circuit:=variational}"
: "${precision:=complex128}"
: "${nreps:=1}"
: "${filename:=qibotn_expectation_local.dat}"
: "${np:=2}"
: "${nlayers:=2}"
: "${nqubits_list:=8 12 16}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "${script_dir}/.." && pwd)"
cd "${repo_root}"
# On Prism, Intel MPI may need shared-memory fabric for local runs.
if [[ -z "${I_MPI_FABRICS:-}" ]]; then
export I_MPI_FABRICS=shm
fi
for nqubits in ${nqubits_list}; do
echo "===== nqubits=${nqubits} ====="
# MPI-enabled cutensornet expectation
mpirun -np "${np}" python compare.py \
--circuit "${circuit}" \
--circuit-options "nlayers=${nlayers}" \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibotn,platform=cutensornet,computation_settings=scripts/cu_tensornet_mpi_expectation.json \
--nreps "${nreps}" \
--precision "${precision}"
# Single-process cutensornet expectation
python compare.py \
--circuit "${circuit}" \
--circuit-options "nlayers=${nlayers}" \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibotn,platform=cutensornet,computation_settings=scripts/cu_tensornet_expectation.json \
--nreps "${nreps}" \
--precision "${precision}"
# qibojit reference
python compare.py \
--circuit "${circuit}" \
--circuit-options "nlayers=${nlayers}" \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibojit,platform=numba,expectation=XXXZ \
--nreps "${nreps}" \
--precision "${precision}"
echo
done

View File

@@ -0,0 +1,214 @@
# Quimb Benchmark Suite
Local (single-process) tensor network simulation benchmarking using quimb backend.
## Files
- **quimb_local.sh** — Main benchmark sweep script (no MPI)
- **expectation_mps.json** — Expectation mode with MPS (default for expectation)
- **expectation_dense.json** — Expectation mode, dense tensor network
- **dense_vector_mps.json** — State extraction with MPS (default for state)
- **dense_vector_dense.json** — State extraction, dense tensor network
## Configuration Files
### Expectation Modes (computing Hamiltonian expectation values)
- **expectation_mps.json**: Uses Matrix Product State (MPS) tensor network ansatz; good for larger systems with limited bond dimension
- **expectation_dense.json**: Uses dense tensor network; full contraction without MPS truncation
### State Modes (full state vector computation)
- **dense_vector_mps.json**: Extracts full state using MPS contraction (faster, bounded memory)
- **dense_vector_dense.json**: Extracts full state using dense tensor (maximum memory usage)
## Usage
```bash
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb
# Run with defaults (all matching dense_vector*.json and expectation*.json configs)
./quimb_local.sh
# Test only expectation mode, custom qubit sizes
modes="expectation" nqubits_list="8 10 12" ./quimb_local.sh
# Test dense vector only with one explicit config
state_cfg=dense_vector_dense.json modes="dense_vector" ./quimb_local.sh
# Restrict the sweep to a chosen subset of configs
EXPECTATION_CONFIGS="expectation_mps.json expectation_dense.json" ./quimb_local.sh
# Test variational and BV circuits
circuits="variational bv" nqubits_list="6 8 10" nreps=3 ./quimb_local.sh
```
## Supported Circuits
### ✓ Fully Supported (Numerically Validated)
| Circuit | Alias | Parameters | Status | Notes |
|---------|-------|------------|--------|-------|
| **qft** | — | none | ✓ Works | Quantum Fourier Transform; aligned with qibojit |
| **supremacy** | — | depth, seed | ✓ Works | Verified locally after environment repair; requires Cirq import path to be healthy |
| **variational** | — | nlayers | ✓ Works | Parameterized circuit; aligned with qibojit |
| **bv** | bernstein-vazirani | none | ✓ Works | Bernstein-Vazirani algorithm; aligned with qibojit |
| **hs** | hidden-shift | none | ✓ Works | Hidden-shift problem; aligned with qibojit |
| **qaoa** | — | nlayers | ✓ Works | QAOA with RZZ gate support; aligned with qibojit |
### ❌ Not Supported
| Circuit | Issue | Notes |
|---------|-------|-------|
| **qv** | Qiskit API compatibility | quantum-volume uses deprecated qiskit `.qasm()` method (v3.0+); not specific to quimb |
### Implementation Notes
- **RZZ Gate:** Full support for QAOA and algorithms using two-qubit Ising rotations
- **cu1 Gate:** Fully supported in expectation value mode (QFT compatible)
- **Numerical Alignment:** All benchmarks automatically include qibojit (numba) reference with identical observable for validation
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `nqubits_list` | `6 8 10` | Space-separated qubit counts to benchmark |
| `circuits` | `supremacy qft variational bv qaoa` | Space-separated circuit names |
| `modes` | `dense_vector expectation` | Benchmark modes (dense_vector, expectation) |
| `nlayers` | `2` | Layers for layered circuits (variational, qaoa) |
| `nreps` | `1` | Repetitions per benchmark |
| `filename` | `quimb_benchmark_local.dat` | Output log file |
| `precision` | `complex128` | NumPy dtype (complex128 or complex64) |
| `exp_cfg` | unset | Optional single expectation config; when unset, all `expectation*.json` files are swept |
| `state_cfg` | unset | Optional single dense-vector config; when unset, all `dense_vector*.json` files are swept |
| `EXPECTATION_CONFIGS` | unset | Optional space-separated subset of expectation configs to run |
| `STATE_CONFIGS` | unset | Optional space-separated subset of dense-vector configs to run |
## Results
Results are logged to `/qibojit-benchmarks/benchmarks/results/` with filename `quimb_benchmark_local.dat` (configurable).
Each benchmark includes:
- **import_time** — Backend initialization time
- **creation_time** — Circuit creation time
- **dry_run_time** — First execution time (warm-up)
- **simulation_times** — Execution times for nreps runs
- **expectation_result** — Observable expectation values (for expectation mode)
## Observable
By default, expectation uses:
- **X on qubit 0**, identity on remaining qubits
- Configurable via `pauli_pattern` in JSON config (e.g., `"XIIII"` for 5 qubits)
## Reference Validation
Each benchmark run automatically includes a **qibojit (numba) reference** with the same observable configuration, enabling direct numerical comparison for validation.
Example:
```
[expectation MPI] quimb + qft @ 6q: 0.2019...
[qibojit ref] numba + qft @ 6q: 0.2019... ✓ aligned
```
## MPI Support
For MPI-enabled benchmarking (multiple processes), see the parallel suite in `/scripts/quimb_mpi/`:
```bash
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb_mpi
./quimb_mpi.sh # runs with mpirun -np 2
```
## Tensor Network Options
Quimb supports both MPS (Matrix Product State) and dense tensor network contractions. By default the script sweeps every matching JSON file in this folder, or you can target individual configs:
```bash
# Compare MPS vs dense at same nqubits
exp_cfg=expectation_mps.json nqubits_list="12" ./quimb_local.sh
exp_cfg=expectation_dense.json nqubits_list="12" ./quimb_local.sh
```
MPS is typically faster and uses bounded memory, while dense provides full accuracy without truncation.
## Installation
Preferred path: create a fresh environment from the benchmark spec.
```bash
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks
conda env create -f environment.yml
conda activate benchmarks
```
If you are using an existing environment instead of recreating it, check that it is aligned with the benchmark stack:
```bash
python -c "import numpy, qibo, qibojit; print('numpy', numpy.__version__); print('qibo', qibo.__version__); print('qibojit', qibojit.__version__)"
```
## Dependency Recovery
```bash
pip install cirq==0.8.2
```
This is the recovery path that eventually made `./quimb_local.sh` work for `supremacy` in the existing `qibotn-py311-test` environment.
### Symptom 1: `cirq` failed with `ModuleNotFoundError: No module named 'pkg_resources'`
Cause:
- the existing environment had `setuptools 82.0.1`
- that install did not expose `pkg_resources`
- the installed `cirq` package still imported `pkg_resources` during startup
Fix:
```bash
/home/tankya2/miniforge3/envs/qibotn-py311-test/bin/python -m pip install "setuptools<81"
```
Working result:
- `setuptools` was changed to `80.10.2`
- `import pkg_resources` worked again
- the Quimb `supremacy` path could construct the Cirq-generated circuit
### Symptom 2: `qibojit` reference crashed with `TypeError: asarray() got an unexpected keyword argument 'copy'`
Cause:
- the same environment had `numpy 1.26.4`
- but `qibo 0.3.1` requires `numpy >= 2.0.0`
- the `qibojit` reference backend was therefore running against an incompatible NumPy version
Fix:
```bash
/home/tankya2/miniforge3/envs/qibotn-py311-test/bin/python -m pip install numpy==2.2.6
```
Working result:
- `numpy` was changed to `2.2.6`
- the `qibojit` reference backend started working again
- both the Quimb and qibojit sides of the `supremacy` benchmark completed successfully
### Final verified state
The existing repaired environment was verified with:
```bash
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb
nqubits_list="6" circuits="supremacy" nreps=1 modes="dense_vector expectation" ./quimb_local.sh
```
That smoke test completed all three stages:
- Quimb `dense_vector`
- Quimb `expectation`
- qibojit reference
Notes:
- `environment.yml` remains the preferred source of truth for a clean install
- the repaired environment may still emit a `pkg_resources` deprecation warning from the older Cirq stack, but the benchmark run succeeds
- if an environment has drifted far from `environment.yml`, recreating it is usually safer than incremental repair
## Notes
- **Intel MPI Fabric:** On Prism cluster, shared-memory fabric (`I_MPI_FABRICS=shm`) is automatically enabled for single-node runs
- **QFT Support:** Fixed cu1 gate compatibility in quimb backend; no platform-specific gate limitations
- **Bond Dimension:** MPS modes use max_bond_dimension=20 by default; adjust in JSON for memory/accuracy tradeoff

View File

@@ -0,0 +1 @@
{"expectation_enabled": false, "use_mps": false}

View File

@@ -0,0 +1 @@
{"expectation_enabled": false, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10}

View File

@@ -0,0 +1 @@
{"expectation_enabled": true, "use_mps": false, "pauli_pattern": "XIIII"}

View File

@@ -0,0 +1,6 @@
{
"expectation_enabled": true,
"use_mps": false,
"pauli_pattern_auto": true,
"pauli_pattern_style": "mixed"
}

View File

@@ -0,0 +1 @@
{"expectation_enabled": true, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10, "pauli_pattern": "XIIII"}

View File

@@ -0,0 +1,215 @@
#!/usr/bin/env bash
# Local quimb benchmark sweep.
# Tests both dense vector (non-expectation) and expectation across multiple
# qubit sizes and circuit types.
#
# Usage examples:
# ./quimb_local.sh
# nqubits_list="6 8 10" circuits="variational bv" ./quimb_local.sh
# modes="expectation" nreps=3 ./quimb_local.sh
# state_cfg=dense_vector_dense.json modes="dense_vector" ./quimb_local.sh
set -euo pipefail
: "${precision:=complex128}"
: "${nreps:=3}"
: "${filename:=quimb_benchmark_local.dat}"
: "${nlayers:=2}"
: "${nqubits_list:=6 8 10}"
: "${circuits:=supremacy qft variational qaoa}"
: "${modes:=dense_vector expectation}"
: "${exp_cfg:=}"
: "${state_cfg:=}"
: "${EXPECTATION_CONFIGS:=}"
: "${STATE_CONFIGS:=}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "${script_dir}/../.." && pwd)"
cd "${repo_root}"
config_list_from_prefix() {
local prefix="$1"
local single_cfg="$2"
local override_list="$3"
if [[ -n "${override_list}" ]]; then
for cfg in ${override_list}; do
printf '%s\n' "${cfg}"
done
return
fi
if [[ -n "${single_cfg}" ]]; then
printf '%s\n' "${single_cfg}"
return
fi
shopt -s nullglob
local matches=( "${script_dir}/${prefix}"*.json )
shopt -u nullglob
for path in "${matches[@]}"; do
basename "${path}"
done
}
require_existing_configs() {
local mode="$1"
shift
for cfg in "$@"; do
if [[ ! -f "${script_dir}/${cfg}" ]]; then
echo "Missing ${mode} config: ${script_dir}/${cfg}" >&2
exit 1
fi
done
}
read_pauli_pattern() {
local cfg_path="$1"
python - "${cfg_path}" <<'PY'
import json
import sys
try:
with open(sys.argv[1], "r") as f:
data = json.load(f)
print(data.get("pauli_pattern", ""))
except Exception:
print("")
PY
}
build_ref_pattern() {
local base_pauli_pattern="$1"
local nqubits="$2"
python - "${base_pauli_pattern}" "${nqubits}" <<'PY'
import sys
p = sys.argv[1].upper()
n = int(sys.argv[2])
if not p:
p = "X" + "I" * max(n - 1, 0)
if len(p) < n:
p = p + ("I" * (n - len(p)))
else:
p = p[:n]
print(p)
PY
}
run_qibojit_reference() {
local nqubits="$1"
local circuit="$2"
local circuit_opts="$3"
local exp_cfg_name="$4"
local exp_cfg_path="${script_dir}/${exp_cfg_name}"
local base_pauli_pattern
local ref_pattern
base_pauli_pattern="$(read_pauli_pattern "${exp_cfg_path}")"
ref_pattern="$(build_ref_pattern "${base_pauli_pattern}" "${nqubits}")"
echo " [qibojit reference] cfg=${exp_cfg_name}"
python compare.py \
--circuit "${circuit}" \
${circuit_opts:+--circuit-options "${circuit_opts}"} \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibojit,platform=numba,expectation=${ref_pattern} \
--nreps "${nreps}" \
--precision "${precision}"
}
mapfile -t expectation_cfgs < <(
config_list_from_prefix "expectation" "${exp_cfg}" "${EXPECTATION_CONFIGS}"
)
mapfile -t state_cfgs < <(
config_list_from_prefix "dense_vector" "${state_cfg}" "${STATE_CONFIGS}"
)
run_dense_mode=false
run_expectation_mode=false
if echo "${modes}" | grep -Eqw "dense_vector|statevector"; then
run_dense_mode=true
fi
if echo "${modes}" | grep -qw "expectation"; then
run_expectation_mode=true
fi
if [[ "${run_dense_mode}" == true && ${#state_cfgs[@]} -eq 0 ]]; then
echo "No dense-vector JSON configs found in ${script_dir}" >&2
exit 1
fi
if [[ "${run_expectation_mode}" == true && ${#expectation_cfgs[@]} -eq 0 ]]; then
echo "No expectation JSON configs found in ${script_dir}" >&2
exit 1
fi
require_existing_configs "dense-vector" "${state_cfgs[@]}"
require_existing_configs "expectation" "${expectation_cfgs[@]}"
# On Prism, Intel MPI needs shared-memory fabric for single-node runs.
if [[ -z "${I_MPI_FABRICS:-}" ]]; then
export I_MPI_FABRICS=shm
fi
echo "Dense-vector configs : ${state_cfgs[*]:-none}"
echo "Expectation configs : ${expectation_cfgs[*]:-none}"
for nqubits in ${nqubits_list}; do
for circuit in ${circuits}; do
circuit_opts="nlayers=${nlayers}"
# These circuits do not use nlayers — omit it to avoid unknown-option errors.
if [[ "${circuit}" == "qft" || "${circuit}" == "QFT" || \
"${circuit}" == "supremacy" || "${circuit}" == "Supremacy" || \
"${circuit}" == "bv" || "${circuit}" == "bernstein-vazirani" || \
"${circuit}" == "hs" || "${circuit}" == "hidden-shift" || \
"${circuit}" == "qaoa" || "${circuit}" == "qv" || \
"${circuit}" == "quantum-volume" ]]; then
circuit_opts=""
fi
echo "===== nqubits=${nqubits} circuit=${circuit} ====="
# dense_vector is the preferred name; statevector is kept as a legacy alias.
if [[ "${run_dense_mode}" == true ]]; then
for cfg_name in "${state_cfgs[@]}"; do
state_cfg_path="${script_dir}/${cfg_name}"
echo " [dense_vector] cfg=${cfg_name}"
python compare.py \
--circuit "${circuit}" \
${circuit_opts:+--circuit-options "${circuit_opts}"} \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibotn,platform=quimb,computation_settings=${state_cfg_path} \
--nreps "${nreps}" \
--precision "${precision}"
done
fi
if [[ "${run_expectation_mode}" == true ]]; then
for cfg_name in "${expectation_cfgs[@]}"; do
exp_cfg_path="${script_dir}/${cfg_name}"
echo " [expectation] cfg=${cfg_name}"
python compare.py \
--circuit "${circuit}" \
${circuit_opts:+--circuit-options "${circuit_opts}"} \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibotn,platform=quimb,computation_settings=${exp_cfg_path} \
--nreps "${nreps}" \
--precision "${precision}"
run_qibojit_reference "${nqubits}" "${circuit}" "${circuit_opts}" "${cfg_name}"
done
fi
echo
done
done

View File

@@ -0,0 +1,167 @@
# Quimb MPI Benchmark Suite
Demonstrates MPI-enabled tensor network simulation using quimb with 2 MPI processes.
## Files
- **quimb_mpi.sh** — Main benchmark sweep script using `mpirun -np 2`
- **expectation_mps_mpi.json** — Expectation mode with MPS (default for expectation)
- **expectation_dense_mpi.json** — Expectation mode, dense tensor network
- **dense_vector_mps_mpi.json** — State extraction with MPS (default for state)
- **dense_vector_dense_mpi.json** — State extraction, dense tensor network
## Key Differences from `/scripts/quimb/`
- Each `python compare.py` call wrapped with `mpirun -np 2` to enable MPI parallelization
- All JSON configs include `"MPI_enabled": true`
- Default file names include `_mpi` suffix to distinguish from single-process configs
- Filenames in logs clearly show MPI mode (e.g., `expectation_mps_mpi.json`)
## Configuration Files
### Expectation Modes (computing Hamiltonian expectation values)
- **expectation_mps_mpi.json**: MPI-enabled, uses Matrix Product State (MPS) tensor network ansatz; good for larger systems with limited bond dimension
- **expectation_dense_mpi.json**: MPI-enabled, uses dense tensor network; full contraction without MPS truncation
### State Modes (full state vector computation)
- **dense_vector_mps_mpi.json**: MPI-enabled, extracts full state using MPS contraction (faster, bounded memory)
- **dense_vector_dense_mpi.json**: MPI-enabled, extracts full state using dense tensor (maximum memory usage)
## Usage
```bash
cd /ssd_data/tankya2/code/ASC_2026_prism/ASC-2026/qibojit-benchmarks/scripts/quimb_mpi
# Run with defaults (all matching dense_vector*.json and expectation*.json configs)
./quimb_mpi.sh
# Test only expectation mode, custom qubit sizes
modes="expectation" nqubits_list="8 10 12" ./quimb_mpi.sh
# Test dense vector only with one explicit config
state_cfg=dense_vector_dense_mpi.json modes="dense_vector" ./quimb_mpi.sh
# Restrict the sweep to a chosen subset of configs
EXPECTATION_CONFIGS="expectation_mps_mpi.json expectation_dense_mpi.json" ./quimb_mpi.sh
# Use 4 MPI processes (if testing scalability)
np=4 ./quimb_mpi.sh
```
## Supported Circuits
### ✓ Fully Supported (Numerically Validated)
| Circuit | Alias | Parameters | Status | Notes |
|---------|-------|------------|--------|-------|
| **qft** | — | none | ✓ Works | Quantum Fourier Transform; aligned with qibojit |
| **variational** | — | nlayers | ✓ Works | Parameterized circuit; aligned with qibojit |
| **bv** | bernstein-vazirani | none | ✓ Works | Bernstein-Vazirani algorithm; aligned with qibojit |
| **hs** | hidden-shift | none | ✓ Works | Hidden-shift problem; aligned with qibojit |
| **qaoa** | — | nlayers | ✓ Works | QAOA with RZZ gate support; aligned with qibojit |
### ❌ Not Supported
| Circuit | Issue | Notes |
|---------|-------|-------|
| **qv** | Qiskit API compatibility | quantum-volume uses deprecated qiskit `.qasm()` method (v3.0+); not specific to quimb |
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `nqubits_list` | `6 8 10` | Space-separated qubit counts to benchmark |
| `circuits` | `qaoa` | Space-separated circuit names |
| `modes` | `dense_vector expectation` | Benchmark modes (dense_vector, expectation) |
| `nlayers` | `2` | Layers for layered circuits (variational, qaoa) |
| `np` | `2` | Number of MPI processes (mpirun -np) |
| `nreps` | `1` | Repetitions per benchmark |
| `filename` | `quimb_benchmark_mpi.dat` | Output log file |
| `precision` | `complex128` | NumPy dtype (complex128 or complex64) |
| `exp_cfg` | unset | Optional single expectation config; when unset, all `expectation*.json` files are swept |
| `state_cfg` | unset | Optional single dense-vector config; when unset, all `dense_vector*.json` files are swept |
| `EXPECTATION_CONFIGS` | unset | Optional space-separated subset of expectation configs to run |
| `STATE_CONFIGS` | unset | Optional space-separated subset of dense-vector configs to run |
## Results
Results are stored in `/qibojit-benchmarks/benchmarks/results/` with filename prefix `quimb_benchmark_mpi.dat` by default (configurable via `filename=` env var).
Each benchmark includes:
- **import_time** — Backend initialization time
- **creation_time** — Circuit creation time
- **dry_run_time** — First execution time (warm-up)
- **simulation_times** — Execution times for nreps runs
- **expectation_result** — Observable expectation values (for expectation mode)
## Observable
By default, expectation uses:
- **X on qubit 0**, identity on remaining qubits
- Configurable via `pauli_pattern` in JSON config (e.g., `"XIIII"` for 5 qubits)
## Reference Validation
Each benchmark run automatically includes a **qibojit (numba) reference** with the same observable configuration, enabling direct numerical comparison for validation.
Example:
```
[expectation MPI] quimb + variational @ 6q: 0.2019...
[qibojit ref] numba + variational @ 6q: 0.2019... ✓ aligned
```
## Supported Circuits
### ✓ Fully Supported (Numerically Validated)
| Circuit | Alias | Parameters | Status | Notes |
|---------|-------|------------|--------|-------|
| **qft** | — | none | ✓ Works | Quantum Fourier Transform; aligned with qibojit |
| **variational** | — | nlayers | ✓ Works | Parameterized circuit; aligned with qibojit |
| **bv** | bernstein-vazirani | none | ✓ Works | Bernstein-Vazirani algorithm; aligned with qibojit |
| **hs** | hidden-shift | none | ✓ Works | Hidden-shift problem; aligned with qibojit |
| **qaoa** | — | nlayers | ✓ Works | QAOA with RZZ gate support; aligned with qibojit |
### ❌ Not Supported
| Circuit | Issue | Notes |
|---------|-------|-------|
| **qv** | Qiskit API compatibility | quantum-volume uses deprecated qiskit `.qasm()` method (v3.0+); not specific to quimb |
## Notes
- **Intel MPI Fabric:** On Prism, automatically sets `I_MPI_FABRICS=shm` (shared-memory fabric) for single-node local runs
- **Observable:** X on first qubit, identity on rest (configurable via `pauli_pattern` in JSON)
- **Reference:** qibojit (numba backend) included automatically with aligned observable for validation
- **RZZ Gate:** Full support for QAOA and algorithms using two-qubit Ising rotations
- **cu1 Gate:** Fully supported in expectation value mode (QFT compatible)
- **Numerical Alignment:** All benchmarks automatically include qibojit reference with identical observable for validation
## MPI Enable/Disable
To test without MPI, use configs from `/scripts/quimb/` instead:
```bash
# Compare: MPI vs no MPI
./quimb_mpi.sh # with MPI (2 processes)
cd ../quimb && ./quimb_local.sh # without MPI (single process)
```
## Tensor Network Options
Quimb supports both MPS (Matrix Product State) and dense tensor network contractions. By default the script sweeps every matching JSON file in this folder, or you can target individual configs:
```bash
# Compare MPS vs dense at same nqubits with MPI
exp_cfg=expectation_mps_mpi.json nqubits_list="12" ./quimb_mpi.sh
exp_cfg=expectation_dense_mpi.json nqubits_list="12" ./quimb_mpi.sh
```
MPS is typically faster and uses bounded memory, while dense provides full accuracy without truncation.
## Additional Notes
- **Bond Dimension:** MPS modes use max_bond_dimension=20 by default; adjust in JSON for memory/accuracy tradeoff
- **SVD Cutoff:** Set to 1e-10 for high accuracy; increase for faster execution with acceptable loss tolerance
- **Scaling:** MPI parallelization enables larger systems; test with np=4, np=8, etc. for scaling studies
- **Single-Node MPI:** Default `-np 2` demonstrates MPI capability on local machine; for cluster runs, adjust `-np` and node configuration

View File

@@ -0,0 +1 @@
{"MPI_enabled": true, "expectation_enabled": false, "use_mps": false}

View File

@@ -0,0 +1 @@
{"MPI_enabled": true, "expectation_enabled": false, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10}

View File

@@ -0,0 +1 @@
{"MPI_enabled": true, "expectation_enabled": true, "use_mps": false, "pauli_pattern": "XIIII"}

View File

@@ -0,0 +1 @@
{"MPI_enabled": true, "expectation_enabled": true, "use_mps": true, "max_bond_dimension": 20, "svd_cutoff": 1e-10, "pauli_pattern": "XIIII"}

View File

@@ -0,0 +1,216 @@
#!/usr/bin/env bash
# MPI-enabled quimb benchmark sweep (2 processes).
# Tests both dense vector (non-expectation) and expectation across multiple
# qubit sizes and circuit types, using mpirun -np 2 to demonstrate MPI capability.
#
# Usage examples:
# ./quimb_mpi.sh
# nqubits_list="6 8 10" circuits="variational bv" ./quimb_mpi.sh
# modes="expectation" nreps=3 ./quimb_mpi.sh
# state_cfg=dense_vector_dense_mpi.json modes="dense_vector" ./quimb_mpi.sh
set -euo pipefail
: "${precision:=complex128}"
: "${nreps:=3}"
: "${filename:=quimb_benchmark_mpi.dat}"
: "${nlayers:=2}"
: "${nqubits_list:=6 8 10}"
: "${circuits:=supremacy qft variational qaoa}"
: "${modes:=dense_vector expectation}"
: "${np:=2}"
: "${exp_cfg:=}"
: "${state_cfg:=}"
: "${EXPECTATION_CONFIGS:=}"
: "${STATE_CONFIGS:=}"
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo_root="$(cd "${script_dir}/../.." && pwd)"
cd "${repo_root}"
config_list_from_prefix() {
local prefix="$1"
local single_cfg="$2"
local override_list="$3"
if [[ -n "${override_list}" ]]; then
for cfg in ${override_list}; do
printf '%s\n' "${cfg}"
done
return
fi
if [[ -n "${single_cfg}" ]]; then
printf '%s\n' "${single_cfg}"
return
fi
shopt -s nullglob
local matches=( "${script_dir}/${prefix}"*.json )
shopt -u nullglob
for path in "${matches[@]}"; do
basename "${path}"
done
}
require_existing_configs() {
local mode="$1"
shift
for cfg in "$@"; do
if [[ ! -f "${script_dir}/${cfg}" ]]; then
echo "Missing ${mode} config: ${script_dir}/${cfg}" >&2
exit 1
fi
done
}
read_pauli_pattern() {
local cfg_path="$1"
python - "${cfg_path}" <<'PY'
import json
import sys
try:
with open(sys.argv[1], "r") as f:
data = json.load(f)
print(data.get("pauli_pattern", ""))
except Exception:
print("")
PY
}
build_ref_pattern() {
local base_pauli_pattern="$1"
local nqubits="$2"
python - "${base_pauli_pattern}" "${nqubits}" <<'PY'
import sys
p = sys.argv[1].upper()
n = int(sys.argv[2])
if not p:
p = "X" + "I" * max(n - 1, 0)
if len(p) < n:
p = p + ("I" * (n - len(p)))
else:
p = p[:n]
print(p)
PY
}
run_qibojit_reference() {
local nqubits="$1"
local circuit="$2"
local circuit_opts="$3"
local exp_cfg_name="$4"
local exp_cfg_path="${script_dir}/${exp_cfg_name}"
local base_pauli_pattern
local ref_pattern
base_pauli_pattern="$(read_pauli_pattern "${exp_cfg_path}")"
ref_pattern="$(build_ref_pattern "${base_pauli_pattern}" "${nqubits}")"
echo " [qibojit reference] cfg=${exp_cfg_name}"
python compare.py \
--circuit "${circuit}" \
${circuit_opts:+--circuit-options "${circuit_opts}"} \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibojit,platform=numba,expectation=${ref_pattern} \
--nreps "${nreps}" \
--precision "${precision}"
}
mapfile -t expectation_cfgs < <(
config_list_from_prefix "expectation" "${exp_cfg}" "${EXPECTATION_CONFIGS}"
)
mapfile -t state_cfgs < <(
config_list_from_prefix "dense_vector" "${state_cfg}" "${STATE_CONFIGS}"
)
run_dense_mode=false
run_expectation_mode=false
if echo "${modes}" | grep -Eqw "dense_vector|statevector"; then
run_dense_mode=true
fi
if echo "${modes}" | grep -qw "expectation"; then
run_expectation_mode=true
fi
if [[ "${run_dense_mode}" == true && ${#state_cfgs[@]} -eq 0 ]]; then
echo "No dense-vector JSON configs found in ${script_dir}" >&2
exit 1
fi
if [[ "${run_expectation_mode}" == true && ${#expectation_cfgs[@]} -eq 0 ]]; then
echo "No expectation JSON configs found in ${script_dir}" >&2
exit 1
fi
require_existing_configs "dense-vector" "${state_cfgs[@]}"
require_existing_configs "expectation" "${expectation_cfgs[@]}"
# On Prism, Intel MPI needs shared-memory fabric for single-node runs.
if [[ -z "${I_MPI_FABRICS:-}" ]]; then
export I_MPI_FABRICS=shm
fi
echo "Dense-vector configs : ${state_cfgs[*]:-none}"
echo "Expectation configs : ${expectation_cfgs[*]:-none}"
for nqubits in ${nqubits_list}; do
for circuit in ${circuits}; do
circuit_opts="nlayers=${nlayers}"
# These circuits do not use nlayers — omit it to avoid unknown-option errors.
if [[ "${circuit}" == "qft" || "${circuit}" == "QFT" || \
"${circuit}" == "supremacy" || "${circuit}" == "Supremacy" || \
"${circuit}" == "bv" || "${circuit}" == "bernstein-vazirani" || \
"${circuit}" == "hs" || "${circuit}" == "hidden-shift" || \
"${circuit}" == "qaoa" || "${circuit}" == "qv" || \
"${circuit}" == "quantum-volume" ]]; then
circuit_opts=""
fi
echo "===== nqubits=${nqubits} circuit=${circuit} np=${np} ====="
# dense_vector is the preferred name; statevector is kept as a legacy alias.
if [[ "${run_dense_mode}" == true ]]; then
for cfg_name in "${state_cfgs[@]}"; do
state_cfg_path="${script_dir}/${cfg_name}"
echo " [dense_vector MPI] cfg=${cfg_name}"
mpirun -np "${np}" python compare.py \
--circuit "${circuit}" \
${circuit_opts:+--circuit-options "${circuit_opts}"} \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibotn,platform=quimb,computation_settings=${state_cfg_path} \
--nreps "${nreps}" \
--precision "${precision}"
done
fi
if [[ "${run_expectation_mode}" == true ]]; then
for cfg_name in "${expectation_cfgs[@]}"; do
exp_cfg_path="${script_dir}/${cfg_name}"
echo " [expectation MPI] cfg=${cfg_name}"
mpirun -np "${np}" python compare.py \
--circuit "${circuit}" \
${circuit_opts:+--circuit-options "${circuit_opts}"} \
--nqubits "${nqubits}" \
--filename "${filename}" \
--library-options backend=qibotn,platform=quimb,computation_settings=${exp_cfg_path} \
--nreps "${nreps}" \
--precision "${precision}"
run_qibojit_reference "${nqubits}" "${circuit}" "${circuit_opts}" "${cfg_name}"
done
fi
echo
done
done