Skip to content

Commit

Permalink
QCQMC notebooks (#357)
Browse files Browse the repository at this point in the history
* Add 3 notebooks outlining how to use the QCQMC code and interpret zenodo data.
  • Loading branch information
fdmalone authored Jul 24, 2024
1 parent a433644 commit 9d0b7ac
Show file tree
Hide file tree
Showing 9 changed files with 1,128 additions and 135 deletions.
12 changes: 5 additions & 7 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
from recirq.qcqmc.hamiltonian import (
HamiltonianData,
HamiltonianFileParams,
build_hamiltonian_from_file,
)
from recirq.qcqmc.optimize_wf import build_pp_plus_trial_wavefunction
from recirq.qcqmc.trial_wf import (
PerfectPairingPlusTrialWavefunctionParams,
TrialWavefunctionData,
Expand All @@ -45,7 +43,7 @@ def fixture_4_qubit_ham(package_tmp_path) -> HamiltonianData:
path_prefix=str(package_tmp_path),
)

hamiltonian_data = build_hamiltonian_from_file(params)
hamiltonian_data = HamiltonianData.build_hamiltonian_from_file(params)

return hamiltonian_data

Expand All @@ -60,7 +58,7 @@ def fixture_8_qubit_ham(package_tmp_path) -> HamiltonianData:
path_prefix=str(package_tmp_path),
)

hamiltonian_data = build_hamiltonian_from_file(params)
hamiltonian_data = HamiltonianData.build_hamiltonian_from_file(params)

return hamiltonian_data

Expand All @@ -76,7 +74,7 @@ def fixture_12_qubit_ham(package_tmp_path) -> HamiltonianData:
path_prefix=str(package_tmp_path),
)

hamiltonian_data = build_hamiltonian_from_file(params)
hamiltonian_data = HamiltonianData.build_hamiltonian_from_file(params)

return hamiltonian_data

Expand All @@ -94,7 +92,7 @@ def fixture_4_qubit_ham_and_trial_wf(
path_prefix=fixture_4_qubit_ham.params.path_prefix,
)

trial_wf = build_pp_plus_trial_wavefunction(
trial_wf = TrialWavefunctionData.build_pp_plus_trial_from_dependencies(
params, dependencies={fixture_4_qubit_ham.params: fixture_4_qubit_ham}
)

Expand All @@ -115,7 +113,7 @@ def fixture_8_qubit_ham_and_trial_wf(
path_prefix=fixture_8_qubit_ham.params.path_prefix,
)

trial_wf = build_pp_plus_trial_wavefunction(
trial_wf = TrialWavefunctionData.build_pp_plus_trial_from_dependencies(
params, dependencies={fixture_8_qubit_ham.params: fixture_8_qubit_ham}
)

Expand Down
3 changes: 3 additions & 0 deletions dev_tools/check_notebooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def check_notebook(notebook_fn: str):
'docs/hfvqe/quickstart.ipynb',
'docs/fermi_hubbard/publication_results.ipynb',
'docs/fermi_hubbard/experiment_example.ipynb',
'docs/qcqmc/high_level.ipynb',
'docs/qcqmc/full_workflow.ipynb',
'docs/qcqmc/experimental_wavefunctions.ipynb',
]


Expand Down
221 changes: 221 additions & 0 deletions docs/qcqmc/experimental_wavefunctions.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Analyzing the Experimentally Reconstructed Wavefunctions\n",
"\n",
"The experimentally reconstructe wavefunctions from the \n",
"[QCQMC](https://www.nature.com/articles/s41586-021-04351-z) paper are available\n",
"for download from [zenodo](https://zenodo.org/records/10141262)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import urllib.request\n",
"import tarfile\n",
"\n",
"stream = urllib.request.urlopen(\"https://zenodo.org/records/10141262/files/qcqmc_data.tar.gz\")\n",
"\n",
"with tarfile.open(fileobj=stream, mode='r|gz') as tf:\n",
" tf.extractall()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Look at the README from the downloaded data\n",
"from IPython.display import Markdown, display\n",
"display(Markdown('qcqmc_data/README.md'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Loading the wavefunctions\n",
"\n",
"Here we will reproduce some of the results from Section E of the SI from [QCQMC](https://www.nature.com/articles/s41586-021-04351-z).\n",
"\n",
"The variational energy of the trial wavefunction as a function of the number of cliffords used for shadow tomography is reported in Table S1, which we have reproduced here:\n",
"\n",
"| NCliffords | repeat 1 | repeat 2 | repeat 3 | repeat 4 |\n",
"|---|---|---|---|---|\n",
"| 10 | -1.800644 | -1.764747 | -1.813274 | -1.658202 |\n",
"| 16 | -1.823041 | -1.802192 | -1.840494 | -1.730591 |\n",
"| 28 | -1.906644 | -1.839835 | -1.843326 | -1.746749 |\n",
"| 47 | -1.925654 | -1.888527 | -1.860863 | -1.809656 |\n",
"| 80 | -1.909567 | -1.869456 | -1.887139 | -1.846339 |\n",
"| 136 | -1.930880 | -1.902309 | -1.889992 | -1.879164 |\n",
"| 229 | -1.944249 | -1.921523 | -1.903710 | -1.890947 |\n",
"| 387 | -1.947362 | -1.934682 | -1.910477 | -1.901883 |\n",
"| 652 | -1.952416 | -1.939853 | -1.912790 | -1.905250 |\n",
"| 1100 | -1.955544 | -1.944651 | -1.915073 | -1.909122 |\n",
"| 1856 | -1.955028 | -1.945966 | -1.909558 | -1.908038 |\n",
"| 3129 | -1.953877 | -1.947763 | -1.913386 | -1.908835 |\n",
"| 5276 | -1.954697 | -1.947323 | -1.912284 | -1.909315 |\n",
"| 8896 | -1.954930 | -1.947458 | -1.913889 | -1.913068 |\n",
"| 15000 | -1.954356 | -1.948894 | -1.913894 | -1.913082 |\n",
"\n",
"Each column represents an independented partitioned shadow tomography experiment.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can reproduce this table from the data by using [FQE](https://quantumai.google/openfermion/fqe) to read the wavefunctions and Hamiltonian and recompute the variational energy of the shadow trial wavefunction.\n",
"\n",
"First we need to parse the wavefunction and Hamiltonian before computing the energy using FQE:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import fqe\n",
"import h5py\n",
"import numpy as np\n",
"\n",
"def compute_energy(wfn_file: str, ham_file: str) -> float:\n",
" \"\"\"Compute the variational energy of the experimentally reconstructed wavefunction.\n",
"\n",
" Args:\n",
" wfn_file: The path to the FQE wavefunction. \n",
" ham_file: The path to the hamiltonian.\n",
"\n",
" Returns:\n",
" The variational energy\n",
" \"\"\"\n",
" fqe_wfn = fqe.wavefunction.Wavefunction()\n",
" fqe_wfn.read(filename=wfn_file)\n",
" with h5py.File(ham_file, 'r') as fh5:\n",
" ecore = fh5[\"e0\"][()]\n",
" h1e_act = fh5[\"h1\"][:]\n",
" eri_act = fh5[\"h2\"][:]\n",
" # get integrals into openfermion order\n",
" of_eris = np.transpose(eri_act, (0, 2, 3, 1))\n",
" # ... and then into FQE format\n",
" fqe_ham = fqe.hamiltonians.restricted_hamiltonian.RestrictedHamiltonian((h1e_act, np.einsum('ijlk', -0.5 * of_eris)), e_0=ecore)\n",
" return fqe_wfn.expectationValue(fqe_ham)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can glob all of the wavefunctions from the zenodo repo and recompute the variational energy:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import glob\n",
"import pandas as pd\n",
"for column in [1, 2, 3, 4]:\n",
" wavefunctions = glob.glob(f'qcqmc_data/h4_sto3g/fqe_wfns/column{column}/wfn*')\n",
" n_cliffords = [int(x.split('/')[-1].split('_')[-1]) for x in wavefunctions]\n",
" energies = [compute_energy(wfn_file, f'qcqmc_data/h4_sto3g/fqe_hams/column{column}/chem_ham.h5').real for wfn_file in wavefunctions]\n",
" if column == 1:\n",
" df = pd.DataFrame({'n_clifford': n_cliffords, f'repeat {column}': energies})\n",
" else:\n",
" new_df = pd.DataFrame({'n_clifford': n_cliffords, f'repeat {column}': energies})\n",
" df = pd.merge(df, new_df, on='n_clifford', how='outer')\n",
"\n",
"reproduced_table = df.sort_values(by='n_clifford')\n",
"print(reproduced_table)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Given these inputs we can also re-run AFQMC using the shadow wavefunctions as a trial wavefuncktion. To do so, we first need to parse the wavefunction and hamiltonian which is provided in ipie format in the zenodo repo: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ipie.qmc.afqmc import AFQMC\n",
"\n",
"num_elec = (2, 2) # H4 molecule, 4 electrons, ms = 0 \n",
"n_clifford = 15_000\n",
"ham_file = 'qcqmc_data/h4_sto3g/ipie_ham/column3/ham.h5'\n",
"wfn_file = f'qcqmc_data/h4_sto3g/ipie_wfns/column3/wfn_{n_clifford}.h5' \n",
"afqmc = AFQMC.build_from_hdf5(num_elec, ham_file, wfn_file, num_blocks=1_000, num_walkers=100)\n",
"afqmc.trial.calculate_energy(afqmc.system, afqmc.hamiltonian)\n",
"afqmc.run(estimator_filename=f'h4_sto3g_n_clifford_{n_clifford}.h5')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally we can analyze the result and compare it to the literature value which we agree with within error bars."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ipie.analysis.extraction import extract_observable\n",
"import matplotlib.pyplot as plt\n",
"from ipie.analysis.blocking import reblock_minimal \n",
"\n",
"paper_result = -1.96922\n",
"analyzed_result = reblock_minimal(afqmc.estimators.filename, start_block=100)\n",
"notebook_energy = analyzed_result.ETotal_ac.values[0]\n",
"notebook_error = analyzed_result.ETotal_error_ac.values[0]\n",
"\n",
"data = extract_observable(afqmc.estimators.filename)\n",
"plt.plot(data.ETotal, marker='o', label=\"AFQMC\", color=\"C0\")\n",
"plt.axhline(paper_result, label=\"Exact Result\", color=\"C1\")\n",
"plt.axhline(notebook_energy, label=\"Notebook result\", color=\"C2\")\n",
"plt.legend()\n",
"plt.xlabel(\"Block number\")\n",
"plt.ylabel(\"Total Energy (Ha)\")\n",
"print(f\"paper result = {paper_result}\")\n",
"print(f\"notebook result = {notebook_energy} +/ {notebook_error}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading

0 comments on commit 9d0b7ac

Please sign in to comment.