From 4945d91a1f3dfa00fa3b039a1b57ffad96a588ba Mon Sep 17 00:00:00 2001
From: Matthew Harrigan <mpharrigan@google.com>
Date: Fri, 20 Nov 2020 14:16:13 -0800
Subject: [PATCH 1/2] Install dependencies and format hfvqe/quickstart

Partially address #101. Re-work `molecular_exmaple.py` to
support putting these data files elsewhere in the future.
---
 docs/hfvqe/quickstart.ipynb                  | 114 ++++++++++++++-----
 recirq/hfvqe/analysis_test.py                |   3 +-
 recirq/hfvqe/molecular_example.py            |  45 ++++++--
 recirq/hfvqe/molecular_example_odd_qubits.py |  54 ---------
 setup.py                                     |   4 +
 5 files changed, 127 insertions(+), 93 deletions(-)
 delete mode 100644 recirq/hfvqe/molecular_example_odd_qubits.py

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": [
+    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
+    "  <td>\n",
+    "    <a target=\"_blank\" href=\"https://www.example.org/cirq/experiments/hfvqe/quickstart\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />View on QuantumLib</a>\n",
+    "  </td>\n",
+    "  <td>\n",
+    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/ReCirq/blob/master/docs/hfvqe/quickstart.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
+    "  </td>\n",
+    "  <td>\n",
+    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/ReCirq/blob/master/docs/hfvqe/quickstart.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
+    "  </td>\n",
+    "  <td>\n",
+    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/ReCirq/docs/hfvqe/quickstart.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
+    "  </td>\n",
+    "</table>"
+   ]
+  },
+  {
+   "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/*/*/*',
+      ]},
       )

From 6cb6b0d9e683a8febf2b6b4e814e50dca501f11c Mon Sep 17 00:00:00 2001
From: Matthew Harrigan <mpharrigan@google.com>
Date: Fri, 20 Nov 2020 14:28:44 -0800
Subject: [PATCH 2/2] Spruce up headings

---
 docs/hfvqe/quickstart.ipynb | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/docs/hfvqe/quickstart.ipynb b/docs/hfvqe/quickstart.ipynb
index d8ce69e4..0f0f8b5a 100644
--- a/docs/hfvqe/quickstart.ipynb
+++ b/docs/hfvqe/quickstart.ipynb
@@ -105,7 +105,9 @@
     "id": "09752498051c"
    },
    "source": [
-    "### Generate the input files, set up quantum resources, and set up the OpdmFunctional to make measurements. "
+    "## Set up the experiment\n",
+    "\n",
+    "Generate the input files, set up quantum resources, and set up the OpdmFunctional to make measurements. "
    ]
   },
   {
@@ -142,8 +144,16 @@
     "id": "61f9277513fe"
    },
    "source": [
-    "The displayed text is the output of the gradient based restricted Hartree-Fock.  We define the gradient in `rhf_objective` and use the conjugate-gradient optimizer to optimize the basis rotation parameters.  This is equivalent to doing Hartree-Fock theory from the canonical transformation perspective.\n",
-    "\n",
+    "The displayed text is the output of the gradient based restricted Hartree-Fock.  We define the gradient in `rhf_objective` and use the conjugate-gradient optimizer to optimize the basis rotation parameters.  This is equivalent to doing Hartree-Fock theory from the canonical transformation perspective."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "id": "61f9277513fe"
+   },
+   "source": [
+    "## Estimate Quantities\n",
     "\n",
     "Next, we will do the following:\n",
     "\n",