diff --git a/docs/hfvqe/quickstart.ipynb b/docs/hfvqe/quickstart.ipynb index a613ea58..d8ce69e4 100644 --- a/docs/hfvqe/quickstart.ipynb +++ b/docs/hfvqe/quickstart.ipynb @@ -1,5 +1,36 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "IafxybMjKfBO" + }, + "source": [ + "##### Copyright 2020 Google" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "pc1aHcGvKmHe" + }, + "outputs": [], + "source": [ + "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# https://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License." + ] + }, { "cell_type": "markdown", "metadata": { @@ -11,6 +42,42 @@ "This code tutorial shows how to estimate a 1-RDM and perform variational optimization" ] }, + { + "cell_type": "markdown", + "metadata": { + "id": "FQEYY3gnK51d" + }, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " View on QuantumLib\n", + " \n", + " Run in Google Colab\n", + " \n", + " View source on GitHub\n", + " \n", + " Download notebook\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "8625de3d3c0d" + }, + "outputs": [], + "source": [ + "try:\n", + " import recirq\n", + "except ImportError:\n", + " !pip install --quiet git+https://github.com/quantumlib/ReCirq" + ] + }, { "cell_type": "code", "execution_count": null, @@ -19,19 +86,17 @@ }, "outputs": [], "source": [ - "# Import library functions and define a helper function\n", "import numpy as np\n", "import cirq\n", "\n", "from recirq.hfvqe.gradient_hf import rhf_func_generator\n", "from recirq.hfvqe.opdm_functionals import OpdmFunctional\n", - "from recirq.hfvqe.analysis import (compute_opdm,\n", - " mcweeny_purification,\n", - " resample_opdm,\n", - " fidelity_witness,\n", - " fidelity)\n", + "from recirq.hfvqe.analysis import (\n", + " compute_opdm, mcweeny_purification,\n", + " resample_opdm, fidelity_witness,\n", + " fidelity)\n", "from recirq.hfvqe.third_party.higham import fixed_trace_positive_projection\n", - "from recirq.hfvqe.molecular_example import make_h6_1_3\n" + "from recirq.hfvqe.molecular_example import make_h6_1_3" ] }, { @@ -64,7 +129,8 @@ " constant=molecule.nuclear_repulsion,\n", " one_body_integrals=obi,\n", " two_body_integrals=tbi,\n", - " num_electrons=molecule.n_electrons // 2, # only simulate spin-up electrons\n", + " # only simulate spin-up electrons:\n", + " num_electrons=molecule.n_electrons // 2,\n", " clean_xxyy=True,\n", " purification=True\n", " )" @@ -103,8 +169,7 @@ "measurement_data = opdm_func.calculate_data(parameters)\n", "\n", "# 2.\n", - "opdm, var_dict = compute_opdm(measurement_data,\n", - " return_variance=True)\n", + "opdm, var_dict = compute_opdm(measurement_data, return_variance=True)\n", "opdm_pure = mcweeny_purification(opdm)\n", "\n", "# 3.\n", @@ -117,7 +182,9 @@ "nocc = molecule.n_electrons // 2\n", "nvirt = molecule.n_orbitals - nocc\n", "initial_fock_state = [1] * nocc + [0] * nvirt\n", - "for _ in range(1000): # 1000 repetitions of the measurement\n", + "\n", + "# 1000 repetitions of the measurement\n", + "for _ in range(1000): \n", " new_opdm = resample_opdm(opdm, var_dict)\n", " raw_energies.append(opdm_func.energy_from_opdm(new_opdm))\n", " raw_fidelity_witness.append(\n", @@ -142,7 +209,6 @@ " fidelity(target_unitary=true_unitary,\n", " measured_opdm=new_opdm_pure)\n", " )\n", - "print('\\n\\n\\n\\n')\n", "print(\"Canonical Hartree-Fock energy \", molecule.hf_energy)\n", "print(\"True energy \", energy(parameters))\n", "print(\"Raw energy \", opdm_func.energy_from_opdm(opdm),\n", @@ -154,7 +220,7 @@ "print(\"Purified fidelity witness \", np.mean(purified_fidelity_witness).real,\n", " \"+- \", np.std(purified_fidelity_witness))\n", "print(\"Purified fidelity \", np.mean(purified_fidelity).real,\n", - " \"+- \", np.std(purified_fidelity))\n" + " \"+- \", np.std(purified_fidelity))" ] }, { @@ -163,7 +229,7 @@ "id": "669a320cb246" }, "source": [ - "This should print out the various energies estimated from the 1-RDM along with error bars. Generated from resampling the 1-RDM based on the estimated covariance." + "This prints out the various energies estimated from the 1-RDM along with error bars. Generated from resampling the 1-RDM based on the estimated covariance." ] }, { @@ -202,7 +268,7 @@ "source": [ "from recirq.hfvqe.mfopt import moving_frame_augmented_hessian_optimizer\n", "from recirq.hfvqe.opdm_functionals import RDMGenerator\n", - "import matplotlib.pyplot as plt\n", + "\n", "rdm_generator = RDMGenerator(opdm_func, purification=True)\n", "opdm_generator = rdm_generator.opdm_generator\n", "\n", @@ -213,7 +279,7 @@ " verbose=True, delta=0.03,\n", " max_iter=20,\n", " hessian_update='diagonal',\n", - " rtol=0.50E-2)\n" + " rtol=0.50E-2)" ] }, { @@ -235,13 +301,15 @@ }, "outputs": [], "source": [ + "import matplotlib.pyplot as plt\n", + "\n", "plt.semilogy(range(len(result.func_vals)),\n", " np.abs(np.array(result.func_vals) - energy(parameters)),\n", " 'C0o-')\n", "plt.xlabel(\"Optimization Iterations\", fontsize=18)\n", "plt.ylabel(r\"$|E - E^{*}|$\", fontsize=18)\n", "plt.tight_layout()\n", - "plt.show()\n" + "plt.show()" ] } ], @@ -253,18 +321,6 @@ "kernelspec": { "display_name": "Python 3", "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.6.12" } }, "nbformat": 4, diff --git a/recirq/hfvqe/analysis_test.py b/recirq/hfvqe/analysis_test.py index 5b251c7f..538162dd 100644 --- a/recirq/hfvqe/analysis_test.py +++ b/recirq/hfvqe/analysis_test.py @@ -19,8 +19,7 @@ from recirq.hfvqe.analysis import (trace_distance, kdelta, energy_from_opdm, fidelity_witness, fidelity, mcweeny_purification) -from recirq.hfvqe.molecular_example import make_h6_1_3 -from recirq.hfvqe.molecular_example_odd_qubits import (make_h3_2_5) +from recirq.hfvqe.molecular_example import make_h6_1_3, make_h3_2_5 from recirq.hfvqe.gradient_hf import rhf_func_generator diff --git a/recirq/hfvqe/molecular_example.py b/recirq/hfvqe/molecular_example.py index 2921c307..564f7f8c 100644 --- a/recirq/hfvqe/molecular_example.py +++ b/recirq/hfvqe/molecular_example.py @@ -23,16 +23,17 @@ from recirq.hfvqe.objective import (RestrictedHartreeFockObjective, generate_hamiltonian) +_MOLECULAR_DATA_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) + '/molecular_data' -def make_h6_1_3() -> Tuple[RestrictedHartreeFockObjective, of.MolecularData, np. - ndarray, np.ndarray, np.ndarray]: - # load the molecule from moelcular data - import recirq.hfvqe as hfvqe - h6_1_3_path = os.path.join( - hfvqe.__path__[0], - 'molecular_data/hydrogen_chains/h_6_sto-3g/bond_distance_1.3') - molfile = os.path.join(h6_1_3_path, 'H6_sto-3g_singlet_linear_r-1.3.hdf5') +def make_h6_1_3(molecular_data_directory=None) \ + -> Tuple[RestrictedHartreeFockObjective, of.MolecularData, + np.ndarray, np.ndarray, np.ndarray]: + if molecular_data_directory is None: + molecular_data_directory = _MOLECULAR_DATA_DIRECTORY + + h6_1_3_path = f'{molecular_data_directory}/hydrogen_chains/h_6_sto-3g/bond_distance_1.3' + molfile = f'{h6_1_3_path}/H6_sto-3g_singlet_linear_r-1.3.hdf5' molecule = of.MolecularData(filename=molfile) molecule.load() @@ -52,3 +53,31 @@ def make_h6_1_3() -> Tuple[RestrictedHartreeFockObjective, of.MolecularData, np. scipy_result = rhf_minimization(rhf_objective) return rhf_objective, molecule, scipy_result.x, obi, tbi + + +def make_h3_2_5(molecular_data_directory=None) \ + -> Tuple[RestrictedHartreeFockObjective, of.MolecularData, + np.ndarray, np.ndarray, np.ndarray]: + if molecular_data_directory is None: + molecular_data_directory = _MOLECULAR_DATA_DIRECTORY + + h3_2_5_path = f'{molecular_data_directory}/hydrogen_chains/h_3_p_sto-3g/bond_distance_2.5' + molfile = f'{h3_2_5_path}/H3_plus_sto-3g_singlet_linear_r-2.5.hdf5' + molecule = of.MolecularData(filename=molfile) + molecule.load() + + S = np.load(os.path.join(h3_2_5_path, 'overlap.npy')) + Hcore = np.load(os.path.join(h3_2_5_path, 'h_core.npy')) + TEI = np.load(os.path.join(h3_2_5_path, 'tei.npy')) + + _, X = sp.linalg.eigh(Hcore, S) + obi = of.general_basis_change(Hcore, X, (1, 0)) + tbi = np.einsum('psqr', of.general_basis_change(TEI, X, (1, 0, 1, 0))) + molecular_hamiltonian = generate_hamiltonian(obi, tbi, + molecule.nuclear_repulsion) + + rhf_objective = RestrictedHartreeFockObjective(molecular_hamiltonian, + molecule.n_electrons) + + scipy_result = rhf_minimization(rhf_objective) + return rhf_objective, molecule, scipy_result.x, obi, tbi diff --git a/recirq/hfvqe/molecular_example_odd_qubits.py b/recirq/hfvqe/molecular_example_odd_qubits.py deleted file mode 100644 index e7066b1c..00000000 --- a/recirq/hfvqe/molecular_example_odd_qubits.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2020 Google -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -from typing import Tuple - -import numpy as np -import openfermion as of -import scipy as sp -import recirq.hfvqe as hfvqe - -from recirq.hfvqe.gradient_hf import rhf_minimization -from recirq.hfvqe.objective import (RestrictedHartreeFockObjective, - generate_hamiltonian) - - -def make_h3_2_5() -> Tuple[RestrictedHartreeFockObjective, of.MolecularData, np. - ndarray, np.ndarray, np.ndarray]: - # load the molecule from moelcular data - h3_2_5_path = os.path.join( - hfvqe.__path__[0], - 'molecular_data/hydrogen_chains/h_3_p_sto-3g/bond_distance_2.5') - - molfile = os.path.join(h3_2_5_path, - 'H3_plus_sto-3g_singlet_linear_r-2.5.hdf5') - molecule = of.MolecularData(filename=molfile) - molecule.load() - - S = np.load(os.path.join(h3_2_5_path, 'overlap.npy')) - Hcore = np.load(os.path.join(h3_2_5_path, 'h_core.npy')) - TEI = np.load(os.path.join(h3_2_5_path, 'tei.npy')) - - _, X = sp.linalg.eigh(Hcore, S) - obi = of.general_basis_change(Hcore, X, (1, 0)) - tbi = np.einsum('psqr', of.general_basis_change(TEI, X, (1, 0, 1, 0))) - molecular_hamiltonian = generate_hamiltonian(obi, tbi, - molecule.nuclear_repulsion) - - rhf_objective = RestrictedHartreeFockObjective(molecular_hamiltonian, - molecule.n_electrons) - - scipy_result = rhf_minimization(rhf_objective) - return rhf_objective, molecule, scipy_result.x, obi, tbi diff --git a/setup.py b/setup.py index 3c6a0218..5e5bbfa5 100644 --- a/setup.py +++ b/setup.py @@ -33,4 +33,8 @@ description="", long_description=open('README.md', encoding='utf-8').read(), packages=find_packages(), + package_data={'recirq': [ + # https://github.com/quantumlib/ReCirq/issues/101 + 'hfvqe/molecular_data/hydrogen_chains/*/*/*', + ]}, )