{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# This cell is added by sphinx-gallery\n# It can be customized to whatever you like\n%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Building molecular Hamiltonians\n===============================\n\n*Author: PennyLane dev team. Last updated: 19 July 2021*\n\nThe ultimate goal of computational quantum chemistry is to unravel the\nquantum effects that determine the structure and properties of\nmolecules. Reaching this goal is challenging since the characteristic\nenergies associated with these effects, e.g., the electronic correlation\nenergy, are typically a tiny fraction of the total energy of the\nmolecule.\n\nAccurate molecular properties can be computed from the wave function\ndescribing the interacting electrons in a molecule. The **electronic**\nwave function $\\Psi(r)$ satisfies the [Schr\u00f6dinger\nequation](https://en.wikipedia.org/wiki/Schr%C3%B6dinger_equation)\n\n$$H_e \\Psi(r) = E \\Psi(r),$$\n\nwhere $H_e$ and $E$ denote the electronic Hamiltonian and the total\nenergy of the molecule, respectively. When solving the latter equation,\nthe nuclei of the molecule can be treated as point particles whose\ncoordinates are fixed \\[\\#BornOpp1927\\]\\_. In this approximation, both\nthe total energy and the electronic Hamiltonian depend parametrically on\nthe nuclear coordinates.\n\nIn this tutorial, you will learn how to use PennyLane to build a\nrepresentation of the electronic Hamiltonian $H_e$ that can be used to\nperform **quantum** simulations of molecules \\[\\#yudong2019\\]\\_. First,\nwe show how to define the structure of the molecule in terms of the\nsymbols and the coordinates of the atoms. Next, we describe how to solve\nthe [Hartree-Fock\nequations](https://en.wikipedia.org/wiki/Hartree%E2%80%93Fock_method)\nfor the target molecule by interfacing with classical quantum chemistry\npackages. Then, we outline how to decompose the fermionic Hamiltonian\ninto a set of Pauli operators whose expectation values can be measured\nin a quantum computer to estimate the total energy of the molecule.\nFinally, we discuss some advanced features that can be used to simulate\nmore complicated systems.\n\nLet's get started!\n\nDefining the molecular structure\n--------------------------------\n\nIn this example we construct the electronic Hamiltonian of the water\nmolecule.\n\n![](../demonstrations/quantum_chemistry/water_structure.png){width=\"30%\"}\n\nThe structure of a molecule is defined by the symbols and the nuclear\ncoordinates of its constituent atoms. It can be specified using\ndifferent [chemical file\nformats](https://en.wikipedia.org/wiki/Chemical_file_format). Within\nPennyLane, the molecular structure is defined by providing a list with\nthe atomic symbols and a one-dimensional array with the nuclear\ncoordinates in [atomic\nunits](https://en.wikipedia.org/wiki/Hartree_atomic_units).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n\nsymbols = [\"H\", \"O\", \"H\"]\ncoordinates = np.array([-0.0399, -0.0038, 0.0, 1.5780, 0.8540, 0.0, 2.7909, -0.5159, 0.0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The \\~.pennylane\\_qchem.qchem.read\\_structure function can also be used\nto read the molecular geometry from an external file.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from pennylane import qchem\n\nsymbols, coordinates = qchem.read_structure(\"h2o.xyz\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The xyz format is supported out of the box. If [Open\nBabel](http://openbabel.org/wiki/Main_Page) is installed, any format\nrecognized by Open Babel is also supported by PennyLane.\n\nSolving the Hartree-Fock equations\n==================================\n\nThe molecule's electronic Hamiltonian is commonly represented using the\n[second-quantization](https://en.wikipedia.org/wiki/Second_quantization)\nformalism, which we will explore in more detail in the next section. To\nthat aim, a basis of **single-particle** states needs to be chosen. In\nquantum chemistry these states are the [molecular\norbitals](https://en.wikipedia.org/wiki/Molecular_orbital) which\ndescribe the wave function of a single electron in the molecule.\n\nMolecular orbitals are typically represented as a linear combination of\n**atomic orbitals**. The expansion coefficients in the atomic basis are\ncalculated using the [Hartree-Fock (HF)\nmethod](https://en.wikipedia.org/wiki/Hartree%E2%80%93Fock_method). In\nthe HF approximation, each electron in the molecule is treated as an\n**independent** particle that moves under the influence of the Coulomb\npotential due to the nuclei, and a mean field generated by all other\nelectrons \\[\\#pople1977\\]\\_. The optimized coefficients are precisely\nwhat we need to build the second-quantized Hamiltonian.\n\nWe can call the function \\~.pennylane\\_qchem.qchem.meanfield to perform\nthe Hartree-Fock calculation using either the quantum chemistry package\n[PySCF](https://sunqm.github.io/pyscf/), or\n[Psi4](http://www.psicode.org/). Here we use PySCF, which is the default\noption.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"hf_file = qchem.meanfield(symbols, coordinates)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This function creates a local file that will later be used to compute\nthe Hamiltonian.\n\nBuilding the Hamiltonian\n========================\n\nIn the second quantization formalism, the electronic wave function of\nthe molecule is represented in the occupation number basis. For $M$\n*spin* molecular orbitals, the elements of this basis are labelled as\n$\\vert n_0, n_1, \\dots, n_{M-1} \\rangle$, where $n_i = 0,1$ indicates\nthe occupation of each orbital. In this representation, the electronic\nHamiltonian is given by\n\n$$H = \\sum_{p,q} h_{pq} c_p^\\dagger c_q +\n \\frac{1}{2} \\sum_{p,q,r,s} h_{pqrs} c_p^\\dagger c_q^\\dagger c_r c_s,$$\n\nwhere $c^\\dagger$ and $c$ are the electron creation and annihilation\noperators, respectively, and the coefficients $h_{pq}$ and $h_{pqrs}$\ndenote the one- and two-electron Coulomb integrals\n\\[\\#ref\\_integrals\\]\\_ evaluated using the Hartree-Fock orbitals.\n\nWe can use the states of $M$ qubits to encode any element of the\noccupation number basis\n\n$$\\vert n_0, n_1, \\dots, n_{M-1} \\rangle \\rightarrow \\vert q_0 q_1 \\cdots q_{M-1} \\rangle.$$\n\nThis implies that we need to map the fermionic operators onto operators\nthat act on qubits. This can be done by using the\n[Jordan-Wigner](https://en.wikipedia.org/wiki/Jordan-Wigner_transformation)\ntransformation \\[\\#seeley2012\\]\\_ which allows us to decompose the\nfermionic Hamiltonian into a linear combination of the tensor product of\nPauli operators\n\n$$H = \\sum_j C_j \\otimes_i \\sigma_i^{(j)},$$\n\nwhere $C_j$ is a scalar coefficient and $\\sigma_i$ represents an element\nof the Pauli group $\\{ I, X, Y, Z \\}$.\n\nThis fermionic-to-qubit transformation is done using the\n\\~.pennylane\\_qchem.qchem.decompose function, which uses\n[OpenFermion](https://github.com/quantumlib/OpenFermion) to compute the\nelectron integrals using the previously generated results of the mean\nfield calculation. Then, it builds the fermionic Hamiltonian and maps it\nto the qubit representation.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"qubit_hamiltonian = qchem.decompose(hf_file, mapping=\"jordan_wigner\")\nprint(\"Qubit Hamiltonian of the water molecule\")\nprint(qubit_hamiltonian)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It is often convenient to use the\n\\~.pennylane\\_qchem.qchem.molecular\\_hamiltonian function which\nencapsulates all the steps explained above. It simplifies the process of\nbuilding the electronic Hamiltonian to a single line of code. We just\nneed to input the symbols and the nuclear coordinates of the molecule,\nas shown below:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"H, qubits = qchem.molecular_hamiltonian(symbols, coordinates)\nprint(\"Number of qubits: {:}\".format(qubits))\nprint(\"Qubit Hamiltonian\")\nprint(H)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Additionally, if you have built your electronic Hamiltonian\nindependently using\n[OpenFermion](https://github.com/quantumlib/OpenFermion) tools, it can\nbe readily converted to a PennyLane observable using the\n\\~.pennylane\\_qchem.qchem.convert\\_observable function.\n\nAdvanced features\n=================\n\nThe \\~.pennylane\\_qchem.qchem.meanfield function allows us to define\nadditional keyword arguments to solve the Hartree-Fock equations of more\ncomplicated systems. The net charge of the molecule may be specified to\nsimulate positively or negatively charged molecules. For a neutral\nsystem we choose\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"charge = 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also specify the [spin\nmultiplicity](https://en.wikipedia.org/wiki/Multiplicity_(chemistry)).\nFor the water molecule, which contains ten electrons, the [Slater\ndeterminant](https://en.wikipedia.org/wiki/Slater_determinant) resulting\nfrom occupying the five lowest-energy orbitals with two *paired*\nelectrons per orbital has spin multiplicity one. Alternatively, if we\ndefine an occupation where the first four orbitals are doubly occupied\nand the next two are singly occupied by *unpaired* electrons, the HF\nstate will have multiplicity three.\n\n|\n\n![](../demonstrations/quantum_chemistry/hf_references.png){width=\"50%\"}\n\n|\n\nFor the neutral water molecule we have,\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"multiplicity = 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As mentioned above, molecular orbitals are represented as a linear\ncombination of atomic orbitals which are typically modeled as\n[Gaussian-type\norbitals](https://en.wikipedia.org/wiki/Gaussian_orbital). We can\nspecify different types of [Gaussian atomic\nbases](https://www.basissetexchange.org/). In this example we choose a\n[minimal basis\nset](https://en.wikipedia.org/wiki/Basis_set_(chemistry)#Minimal_basis_sets).\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"basis_set = \"sto-3g\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"PennyLane also allows us to define an active space \\[\\#truhlar2018\\]\\_\nto perform quantum simulations with a reduced number of qubits. This is\ndone by classifying the molecular orbitals as core, active, and external\norbitals:\n\n- Core orbitals are always occupied by two electrons.\n- Active orbitals can be occupied by zero, one, or two electrons.\n- The external orbitals are never occupied.\n\nWithin this approximation, a certain number of **active electrons** are\nallowed to populate a finite set of **active orbitals**.\n\n![](../demonstrations/quantum_chemistry/sketch_active_space.png){width=\"40%\"}\n\n> **note**\n>\n> The number of active **spin-orbitals** determines the **number of qubits** required\n>\n> : to perform the quantum simulations.\n>\nFor the water molecule in a minimal basis set we have a total of ten\nelectrons and seven molecular orbitals. In this example we define an\nsymmetric active space with four electrons and four active orbitals\nusing the \\~.pennylane\\_qchem.qchem.active\\_space function:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"electrons = 10\norbitals = 7\ncore, active = qchem.active_space(electrons, orbitals, active_electrons=4, active_orbitals=4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Viewing the results:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"print(\"List of core orbitals: {:}\".format(core))\nprint(\"List of active orbitals: {:}\".format(active))\nprint(\"Number of qubits: {:}\".format(2 * len(active)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we use the \\~.pennylane\\_qchem.qchem.molecular\\_hamiltonian\nfunction to build the resulting Hamiltonian of the water molecule:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"H, qubits = qchem.molecular_hamiltonian(\n symbols,\n coordinates,\n charge=charge,\n mult=multiplicity,\n basis=basis_set,\n active_electrons=4,\n active_orbitals=4,\n)\n\nprint(\"Number of qubits required to perform quantum simulations: {:}\".format(qubits))\nprint(\"Hamiltonian of the water molecule\")\nprint(H)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this case, since we have truncated the basis of molecular orbitals,\nthe resulting observable is an approximation of the Hamiltonian\ngenerated in the section hamiltonian.\n\nYou have completed the tutorial! Now, select your favorite molecule and\nbuild its electronic Hamiltonian. To see how simple it is to implement\nthe VQE algorithm to compute the ground-state energy of your molecule\nusing PennyLane, take a look at the tutorial tutorial\\_vqe.\n\nReferences\n==========\n"
]
}
],
"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.7.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}