Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies = [
"openfermion>=1.7.1",
"tensorboard>=2.20.0",
"dacite>=1.9.2",
"pyscf>=2.12.1",
]
Comment on lines 16 to 20
requires-python = ">=3.12"
authors = [{ name = "Hao Zhang", email = "hzhangxyz@outlook.com" }]
Expand Down
45 changes: 34 additions & 11 deletions qmp/plugins/pyscf.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ def kernel(
# ------------------------------------------------------------------
# 11. Extract energy and build ci output
# ------------------------------------------------------------------
energy = _extract_energy(data, self.config.action.name)
energy = _extract_energy(data, self.config.action.name, model)
# Strip the random engine state — it is stale by the next call.
full_checkpoint: dict[str, typing.Any] = {k: v for k, v in data.items() if k != "random"}

Expand All @@ -469,7 +469,7 @@ def kernel(
return energy, ci


def _extract_energy(data: dict[str, typing.Any], action_name: str) -> float:
def _extract_energy(data: dict[str, typing.Any], action_name: str, model: ModelProto | None = None) -> float:
"""
Extract the final ground-state energy from algorithm checkpoint data.

Expand All @@ -479,6 +479,8 @@ def _extract_energy(data: dict[str, typing.Any], action_name: str) -> float:
Checkpoint data loaded from the temporary directory.
action_name : str
Name of the algorithm that produced the checkpoint.
model : ModelProto, optional
The model instance for computing energy expectation value if needed.

Returns
-------
Expand All @@ -490,15 +492,36 @@ def _extract_energy(data: dict[str, typing.Any], action_name: str) -> float:
haar_data = data.get("haar")
if haar_data is None:
return 0.0
haar_global_step: int = haar_data.get("global", 0)
# In haar.py, excited states are stored with key = global_step *before*
# the increment, so the last entry key is (global_step - 1).
last_key = haar_global_step - 1
excited: dict[int, list[typing.Any]] = haar_data.get("excited", {})
results = excited.get(last_key)
if results:
# results is list[(energy_tensor, configs, psi)]; index 0 is ground state.
energy_val = results[0][0]

# Try to get the final energy directly if stored
if "final_energy" in haar_data:
energy_val = haar_data["final_energy"]
if hasattr(energy_val, "item"):
return float(energy_val.item())
return float(energy_val)

# Try to compute energy from the pool (configs, psi) if model is available
pool = haar_data.get("pool")
if pool is not None and model is not None:
configs, psi = pool
if configs is not None and psi is not None:
# Compute expectation value <psi|H|psi> / <psi|psi>
h_psi = model.apply_within(configs, psi, configs)
energy = ((psi.conj() @ h_psi) / (psi.conj() @ psi)).real
Comment on lines +508 to +510
if hasattr(energy, "item"):
return float(energy.item())
return float(energy)

Comment on lines +503 to +514
# Fallback: try to get from excited state results (Lanczos energy)
haar_global_step: int = haar_data.get("global", 0)
if haar_global_step > 0:
last_key = haar_global_step - 1
excited: dict[int, list[typing.Any]] = haar_data.get("excited", {})
results = excited.get(last_key)
if results:
# results is list[(energy_tensor, configs, psi)]; index 0 is ground state.
energy_val = results[0][0]
if hasattr(energy_val, "item"):
return float(energy_val.item())

return 0.0
7 changes: 7 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading