Files
qibotn/tools/qibojit_reference_expectation.py
jaunatisblue 72f95599bb
Some checks failed
Build wheels / build (ubuntu-latest, 3.11) (push) Has been cancelled
Build wheels / build (ubuntu-latest, 3.12) (push) Has been cancelled
Build wheels / build (ubuntu-latest, 3.13) (push) Has been cancelled
Tests / check (push) Has been cancelled
Tests / build (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / build (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / build (ubuntu-latest, 3.13) (push) Has been cancelled
完善mps的vidal机制,多节点并行;补充tn搜索时dask集群搜索的方式
2026-05-12 15:44:19 +08:00

110 lines
3.7 KiB
Python

"""Compute and cache a qibojit state-vector reference for the ring-XZ observable."""
import argparse
import json
import math
import time
from pathlib import Path
import numpy as np
import qibo
from qibo import Circuit, gates
def build_circuit(nqubits, nlayers, seed):
rng = np.random.default_rng(seed)
circuit = Circuit(nqubits)
for _ in range(nlayers):
for qubit in range(nqubits):
circuit.add(gates.RY(qubit, theta=rng.uniform(-math.pi, math.pi)))
circuit.add(gates.RZ(qubit, theta=rng.uniform(-math.pi, math.pi)))
for qubit in range(0, nqubits - 1, 2):
circuit.add(gates.CNOT(qubit, qubit + 1))
for qubit in range(1, nqubits - 1, 2):
circuit.add(gates.CNOT(qubit, qubit + 1))
return circuit
def ring_xz_expectation(state, nqubits, chunk_size):
value = 0.0
for qubit in range(nqubits):
next_qubit = (qubit + 1) % nqubits
x_flip = 1 << (nqubits - 1 - qubit)
z_shift = nqubits - 1 - next_qubit
term = 0.0
for start in range(0, state.size, chunk_size):
stop = min(start + chunk_size, state.size)
indices = np.arange(start, stop, dtype=np.int64)
z_bit = (indices >> z_shift) & 1
z_phase = 1 - 2 * z_bit
term += np.vdot(state[indices ^ x_flip], z_phase * state[start:stop]).real
value += 0.5 * term
return float(value)
def default_output_path(nqubits, nlayers, seed):
return Path("references") / (
f"qibojit_ring_xz_n{nqubits}_l{nlayers}_seed{seed}.json"
)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--nqubits", type=int, default=32)
parser.add_argument("--nlayers", type=int, default=3)
parser.add_argument("--seed", type=int, default=42)
parser.add_argument("--output")
parser.add_argument("--force", action="store_true")
parser.add_argument("--allow-large", action="store_true")
parser.add_argument("--max-state-gb", type=float, default=32.0)
parser.add_argument("--chunk-size", type=int, default=1 << 20)
args = parser.parse_args()
output = Path(args.output) if args.output else default_output_path(
args.nqubits, args.nlayers, args.seed
)
if output.exists() and not args.force:
with open(output, "r", encoding="utf-8") as f:
data = json.load(f)
print(f"loaded {output}")
print(f"expectation={float(data['expectation']):.16e}")
return
state_gb = (2**args.nqubits) * np.dtype(np.complex128).itemsize / (1024**3)
if state_gb > args.max_state_gb and not args.allow_large:
raise MemoryError(
f"Estimated state vector alone is {state_gb:.1f} GiB. "
"Pass --allow-large after confirming the node has enough memory."
)
qibo.set_backend("qibojit")
circuit = build_circuit(args.nqubits, args.nlayers, args.seed)
start = time.perf_counter()
state = circuit().state(numpy=True).reshape(-1)
expectation = ring_xz_expectation(state, args.nqubits, args.chunk_size)
elapsed = time.perf_counter() - start
data = {
"backend": "qibojit",
"observable": "0.5 * sum_i X_i Z_((i+1) mod n)",
"nqubits": args.nqubits,
"nlayers": args.nlayers,
"seed": args.seed,
"expectation": expectation,
"seconds": elapsed,
"state_vector_gib_estimate": state_gb,
}
output.parent.mkdir(parents=True, exist_ok=True)
with open(output, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, sort_keys=True)
f.write("\n")
print(f"saved {output}")
print(f"expectation={expectation:.16e}")
print(f"seconds={elapsed:.3f}")
if __name__ == "__main__":
main()