216 lines
6.3 KiB
Bash
Executable File
216 lines
6.3 KiB
Bash
Executable File
#!/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
|