Skip to content
This repository was archived by the owner on Aug 21, 2023. It is now read-only.

Commit efb6121

Browse files
chemistry tutorials (#1058)
* tutorials on electronic/vibronic structure calculations and ground/excited states calculations * renaming 1 -> 01 * implemented comments * renaming * qiskit version at the end with qiskit.tools * kernel name * comments non-capitalized * added Molecule and ignore swp * renaming, numpy deprecation warnings and section labelling Co-authored-by: Paul Nation <nonhermitian@gmail.com>
1 parent da27f91 commit efb6121

File tree

11 files changed

+2583
-616
lines changed

11 files changed

+2583
-616
lines changed
Lines changed: 383 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Electronic structure"
8+
]
9+
},
10+
{
11+
"cell_type": "markdown",
12+
"metadata": {},
13+
"source": [
14+
"## Introduction \n",
15+
"\n",
16+
"The molecular Hamiltonian is \n",
17+
"\n",
18+
"$$\n",
19+
"\\mathcal{H} = - \\sum_I \\frac{\\nabla_{R_I}^2}{M_I} - \\sum_i \\frac{\\nabla_{r_i}^2}{m_e} - \\sum_I\\sum_i \\frac{Z_I e^2}{|R_I-r_i|} + \\sum_i \\sum_{j>i} \\frac{e^2}{|r_i-r_j|} + \\sum_I\\sum_{J>I} \\frac{Z_I Z_J e^2}{|R_I-R_J|}\n",
20+
"$$\n",
21+
"\n",
22+
"Because the nuclei are much heavier than the electrons they do not move on the same time scale and therefore, the behavior of nuclei and electronc can be decoupled. This is the Born-Oppenheimer approximation.\n",
23+
"\n",
24+
"Therefore, one can first tackle the electronic problem with nuclear coordinate entering only as parameters. The energy levels of the electrons in the molecule can be found by solving the non-relativistic time independant Schroedinger equation,\n",
25+
"\n",
26+
"$$\n",
27+
"\\mathcal{H}_{\\text{el}} |\\Psi_{n}\\rangle = E_{n} |\\Psi_{n}\\rangle\n",
28+
"$$\n",
29+
"\n",
30+
"where \n",
31+
"\n",
32+
"$$\n",
33+
"\\mathcal{H}_{\\text{el}} = - \\sum_i \\frac{\\nabla_{r_i}^2}{m_e} - \\sum_I\\sum_i \\frac{Z_I e^2}{|R_I-r_i|} + \\sum_i \\sum_{j>i} \\frac{e^2}{|r_i-r_j|}.\n",
34+
"$$\n",
35+
"\n",
36+
"In particular the ground state energy is given by:\n",
37+
"$$\n",
38+
"E_0 = \\frac{\\langle \\Psi_0 | H_{\\text{el}} | \\Psi_0 \\rangle}{\\langle \\Psi_0 | \\Psi_0 \\rangle}\n",
39+
"$$\n",
40+
"where $\\Psi_0$ is the ground state of the system. \n",
41+
"\n",
42+
"However, the dimensionality of this problem grows exponentially with the number of degrees of freedom. To tackle this issue we would like to prepare $\\Psi_0$ on a quantum computer and measure the Hamiltonian expectation value (or $E_0$) directly. \n",
43+
"\n",
44+
"So how do we do that concretely? \n"
45+
]
46+
},
47+
{
48+
"cell_type": "markdown",
49+
"metadata": {},
50+
"source": [
51+
"## The Hartree-Fock initial state \n",
52+
"\n",
53+
"A good starting point for solving this problem is the Hartree-Fock (HF) method. This method approximates a N-body problem into N one-body problems where each electron evolves in the mean-field of the others. Classically solving the HF equations is efficient and leads to the exact exchange energy but does not include any electron correlation. Therefore, it is usually a good starting point to start adding correlation. \n",
54+
"\n",
55+
"The Hamtiltonian can then be re-expressed in the basis of the solutions of the HF method, also called Molecular Orbitals (MOs):\n",
56+
"\n",
57+
"$$\n",
58+
"\\hat{H}_{elec}=\\sum_{pq} h_{pq} \\hat{a}^{\\dagger}_p \\hat{a}_q + \n",
59+
"\\frac{1}{2} \\sum_{pqrs} h_{pqrs} \\hat{a}^{\\dagger}_p \\hat{a}^{\\dagger}_q \\hat{a}_r \\hat{a}_s\n",
60+
"$$\n",
61+
"with the 1-body integrals\n",
62+
"$$\n",
63+
"h_{pq} = \\int \\phi^*_p(r) \\left( -\\frac{1}{2} \\nabla^2 - \\sum_{I} \\frac{Z_I}{R_I- r} \\right) \\phi_q(r)\n",
64+
"$$\n",
65+
"and 2-body integrals\n",
66+
"$$\n",
67+
"h_{pqrs} = \\int \\frac{\\phi^*_p(r_1) \\phi^*_q(r_2) \\phi_r(r_2) \\phi_s(r_1)}{|r_1-r_2|}.\n",
68+
"$$\n",
69+
"\n",
70+
"The MOs ($\\phi_u$) can be occupied or virtual (unoccupied). One MO can contain 2 electrons. However, in what follows we actually work with Spin Orbitals which are associated with a spin up ($\\alpha$) of spin down ($\\beta$) electron. Thus Spin Orbitals can contain one electron or be unoccupied. \n",
71+
"\n",
72+
"We now show how to concreatly realise these steps with Qiskit."
73+
]
74+
},
75+
{
76+
"cell_type": "markdown",
77+
"metadata": {},
78+
"source": [
79+
"Qiskit is interfaced with different classical codes which are able to find the HF solutions. Interfacing between Qiskit and the following codes is already available:\n",
80+
"* Gaussian\n",
81+
"* Psi4\n",
82+
"* PyQuante\n",
83+
"* PySCF\n",
84+
"\n",
85+
"In the following we set up a PySCF driver, for the hydrogen molecule at equilibrium bond length (0.735 angstrom) in the singlet state and with no charge. "
86+
]
87+
},
88+
{
89+
"cell_type": "code",
90+
"execution_count": 4,
91+
"metadata": {},
92+
"outputs": [],
93+
"source": [
94+
"from qiskit.chemistry.drivers import PySCFDriver, UnitsType, Molecule\n",
95+
"molecule = Molecule(geometry=[['H', [0., 0., 0.]],\n",
96+
" ['H', [0., 0., 0.735]]],\n",
97+
" charge=0, multiplicity=1)\n",
98+
"driver = PySCFDriver(molecule = molecule, unit=UnitsType.ANGSTROM, basis='sto3g')"
99+
]
100+
},
101+
{
102+
"cell_type": "markdown",
103+
"metadata": {},
104+
"source": [
105+
"For further information about the drivers see https://qiskit.org/documentation/apidoc/qiskit.chemistry.drivers.html"
106+
]
107+
},
108+
{
109+
"cell_type": "markdown",
110+
"metadata": {},
111+
"source": [
112+
"## The mapping from fermions to qubits \n",
113+
"\n",
114+
"<img src=\"aux_files/jw_mapping.png\" width=\"500\">\n",
115+
"\n",
116+
"The Hamiltonian given in the previous section is expressed in terms of fermionic operators. To encode the problem into the state of a quantum computer, these operators must be mapped to spin operators (indeed the qubits follow spin statistics). \n",
117+
"\n",
118+
"There exist different mapping types with different properties. Qiskit already supports the following mappings:\n",
119+
"* The Jordan-Wigner 'jordan_wigner' mapping (über das paulische äquivalenzverbot. In The Collected Works of Eugene Paul Wigner (pp. 109-129). Springer, Berlin, Heidelberg (1993)).\n",
120+
"* The Parity 'parity' (The Journal of chemical physics, 137(22), 224109 (2012))\n",
121+
"* The Bravyi-Kitaev 'bravyi_kitaev' (Annals of Physics, 298(1), 210-226 (2002))\n",
122+
"* The Bravyi-Kitaev Super Fast 'bksf' (Annals of Physics, 298(1), 210-226 (2002))\n",
123+
"\n",
124+
"The Jordan-Wigner mapping is particularly interesting as it maps each Spin Orbital to a qubit (as shown on the Figure above). \n",
125+
"\n",
126+
"Here we set up an object which contains all the information about any transformation of the fermionic Hamiltonian to the qubits Hamiltonian. In this example we simply ask for the Jordan-Wigner mapping. "
127+
]
128+
},
129+
{
130+
"cell_type": "code",
131+
"execution_count": 3,
132+
"metadata": {},
133+
"outputs": [],
134+
"source": [
135+
"from qiskit.chemistry.transformations import (FermionicTransformation, \n",
136+
" FermionicTransformationType, \n",
137+
" FermionicQubitMappingType)\n",
138+
"\n",
139+
"fermionic_transformation = FermionicTransformation(\n",
140+
" transformation=FermionicTransformationType.FULL,\n",
141+
" qubit_mapping=FermionicQubitMappingType.JORDAN_WIGNER,\n",
142+
" two_qubit_reduction=False,\n",
143+
" freeze_core=False)"
144+
]
145+
},
146+
{
147+
"cell_type": "markdown",
148+
"metadata": {},
149+
"source": [
150+
"If we now transform this Hamiltonian for the given driver defined above we get our qubit operator:"
151+
]
152+
},
153+
{
154+
"cell_type": "code",
155+
"execution_count": 4,
156+
"metadata": {},
157+
"outputs": [
158+
{
159+
"name": "stdout",
160+
"output_type": "stream",
161+
"text": [
162+
"SummedOp([\n",
163+
" -0.8105479805373266 * IIII,\n",
164+
" 0.17218393261915552 * IIIZ,\n",
165+
" -0.22575349222402472 * IIZI,\n",
166+
" 0.1721839326191556 * IZII,\n",
167+
" -0.22575349222402466 * ZIII,\n",
168+
" 0.1209126326177663 * IIZZ,\n",
169+
" 0.16892753870087912 * IZIZ,\n",
170+
" 0.045232799946057854 * XXYY,\n",
171+
" 0.045232799946057854 * YYYY,\n",
172+
" 0.045232799946057854 * XXXX,\n",
173+
" 0.045232799946057854 * YYXX,\n",
174+
" 0.16614543256382414 * ZIIZ,\n",
175+
" 0.16614543256382414 * IZZI,\n",
176+
" 0.17464343068300453 * ZIZI,\n",
177+
" 0.1209126326177663 * ZZII\n",
178+
"])\n",
179+
"{'num_particles': [1, 1], 'num_orbitals': 4, 'two_qubit_reduction': False, 'z2_symmetries': <qiskit.aqua.operators.legacy.weighted_pauli_operator.Z2Symmetries object at 0x123f6d940>}\n"
180+
]
181+
}
182+
],
183+
"source": [
184+
"qubit_op, _ = fermionic_transformation.transform(driver)\n",
185+
"print(qubit_op)\n",
186+
"print(fermionic_transformation.molecule_info)"
187+
]
188+
},
189+
{
190+
"cell_type": "markdown",
191+
"metadata": {},
192+
"source": [
193+
"In the minimal (STO-3G) basis set 4 qubits are required. We could even lower the qubit count by using the Parity mapping which allows to get rid of to qubits by symmetry considerations. "
194+
]
195+
},
196+
{
197+
"cell_type": "code",
198+
"execution_count": 5,
199+
"metadata": {},
200+
"outputs": [
201+
{
202+
"name": "stdout",
203+
"output_type": "stream",
204+
"text": [
205+
"SummedOp([\n",
206+
" -1.052373245772859 * II,\n",
207+
" 0.39793742484318007 * IZ,\n",
208+
" -0.39793742484318007 * ZI,\n",
209+
" -0.01128010425623538 * ZZ,\n",
210+
" 0.18093119978423136 * XX\n",
211+
"])\n"
212+
]
213+
}
214+
],
215+
"source": [
216+
"fermionic_transformation_2 = FermionicTransformation(\n",
217+
" transformation=FermionicTransformationType.FULL,\n",
218+
" qubit_mapping=FermionicQubitMappingType.PARITY,\n",
219+
" two_qubit_reduction=True,\n",
220+
" freeze_core=False)\n",
221+
"qubit_op_2, _ = fermionic_transformation_2.transform(driver)\n",
222+
"print(qubit_op_2)"
223+
]
224+
},
225+
{
226+
"cell_type": "markdown",
227+
"metadata": {},
228+
"source": [
229+
"This time only 2 qubits are needed. \n",
230+
"\n",
231+
"Another possibility is to use the Particle-Hole tranformation (Physical Review A, 98(2), 022322 (2018)). This shifts the vacuum state to a state lying in the N-particle Fock space. In this representation the HF (reference) state has a null energy and the optimization procedure is more faster. "
232+
]
233+
},
234+
{
235+
"cell_type": "code",
236+
"execution_count": 6,
237+
"metadata": {},
238+
"outputs": [
239+
{
240+
"name": "stdout",
241+
"output_type": "stream",
242+
"text": [
243+
"SummedOp([\n",
244+
" 1.0264200106656571 * IIII,\n",
245+
" 0.17218393261915554 * IIIZ,\n",
246+
" -0.22575349222402463 * IIZI,\n",
247+
" 0.17218393261915554 * IZII,\n",
248+
" -0.22575349222402458 * ZIII,\n",
249+
" 0.16892753870087912 * IZIZ,\n",
250+
" 0.045232799946057854 * YYYY,\n",
251+
" 0.045232799946057854 * XXYY,\n",
252+
" 0.045232799946057854 * YYXX,\n",
253+
" 0.045232799946057854 * XXXX,\n",
254+
" 0.1209126326177663 * IIZZ,\n",
255+
" 0.16614543256382414 * IZZI,\n",
256+
" 0.16614543256382414 * ZIIZ,\n",
257+
" 0.17464343068300453 * ZIZI,\n",
258+
" 0.1209126326177663 * ZZII\n",
259+
"])\n"
260+
]
261+
}
262+
],
263+
"source": [
264+
"fermionic_transformation_3 = FermionicTransformation(\n",
265+
" transformation=FermionicTransformationType.PARTICLE_HOLE,\n",
266+
" qubit_mapping=FermionicQubitMappingType.JORDAN_WIGNER,\n",
267+
" two_qubit_reduction=False,\n",
268+
" freeze_core=False)\n",
269+
"qubit_op_3, _ = fermionic_transformation_3.transform(driver)\n",
270+
"print(qubit_op_3)"
271+
]
272+
},
273+
{
274+
"cell_type": "markdown",
275+
"metadata": {},
276+
"source": [
277+
"The list of available mappings and transformations are"
278+
]
279+
},
280+
{
281+
"cell_type": "code",
282+
"execution_count": 7,
283+
"metadata": {},
284+
"outputs": [
285+
{
286+
"name": "stdout",
287+
"output_type": "stream",
288+
"text": [
289+
"*Transformations\n",
290+
"FermionicTransformationType.FULL\n",
291+
"FermionicTransformationType.PARTICLE_HOLE\n",
292+
"\n",
293+
"*Mappings\n",
294+
"FermionicQubitMappingType.JORDAN_WIGNER\n",
295+
"FermionicQubitMappingType.PARITY\n",
296+
"FermionicQubitMappingType.BRAVYI_KITAEV\n"
297+
]
298+
}
299+
],
300+
"source": [
301+
"print('*Transformations')\n",
302+
"for fer_transform in FermionicTransformationType:\n",
303+
" print(fer_transform)\n",
304+
"\n",
305+
"print('\\n*Mappings')\n",
306+
"for fer_mapping in FermionicQubitMappingType:\n",
307+
" print(fer_mapping)"
308+
]
309+
},
310+
{
311+
"cell_type": "markdown",
312+
"metadata": {},
313+
"source": [
314+
"Now that the Hamiltonian is ready, it can be used in a quantum algorithm to find information about the electronic structure of the corresponding molecule. Check out our tutorials on Ground State Calculation and Excited States Calculation to learn more about how to do that in Qiskit!"
315+
]
316+
},
317+
{
318+
"cell_type": "code",
319+
"execution_count": 1,
320+
"metadata": {},
321+
"outputs": [
322+
{
323+
"data": {
324+
"text/html": [
325+
"<h3>Version Information</h3><table><tr><th>Qiskit Software</th><th>Version</th></tr><tr><td>Qiskit</td><td>0.23.0</td></tr><tr><td>Terra</td><td>0.16.0</td></tr><tr><td>Aer</td><td>0.7.0</td></tr><tr><td>Ignis</td><td>0.5.0</td></tr><tr><td>Aqua</td><td>0.8.0</td></tr><tr><td>IBM Q Provider</td><td>0.11.0</td></tr><tr><th>System information</th></tr><tr><td>Python</td><td>3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 13:42:17) \n",
326+
"[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]</td></tr><tr><td>OS</td><td>Darwin</td></tr><tr><td>CPUs</td><td>2</td></tr><tr><td>Memory (Gb)</td><td>16.0</td></tr><tr><td colspan='2'>Tue Oct 20 18:02:17 2020 CEST</td></tr></table>"
327+
],
328+
"text/plain": [
329+
"<IPython.core.display.HTML object>"
330+
]
331+
},
332+
"metadata": {},
333+
"output_type": "display_data"
334+
},
335+
{
336+
"data": {
337+
"text/html": [
338+
"<div style='width: 100%; background-color:#d5d9e0;padding-left: 10px; padding-bottom: 10px; padding-right: 10px; padding-top: 5px'><h3>This code is a part of Qiskit</h3><p>&copy; Copyright IBM 2017, 2020.</p><p>This code is licensed under the Apache License, Version 2.0. You may<br>obtain a copy of this license in the LICENSE.txt file in the root directory<br> of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.<p>Any modifications or derivative works of this code must retain this<br>copyright notice, and modified files need to carry a notice indicating<br>that they have been altered from the originals.</p></div>"
339+
],
340+
"text/plain": [
341+
"<IPython.core.display.HTML object>"
342+
]
343+
},
344+
"metadata": {},
345+
"output_type": "display_data"
346+
}
347+
],
348+
"source": [
349+
"import qiskit.tools.jupyter\n",
350+
"%qiskit_version_table\n",
351+
"%qiskit_copyright"
352+
]
353+
},
354+
{
355+
"cell_type": "code",
356+
"execution_count": null,
357+
"metadata": {},
358+
"outputs": [],
359+
"source": []
360+
}
361+
],
362+
"metadata": {
363+
"kernelspec": {
364+
"display_name": "Python 3",
365+
"language": "python",
366+
"name": "python3"
367+
},
368+
"language_info": {
369+
"codemirror_mode": {
370+
"name": "ipython",
371+
"version": 3
372+
},
373+
"file_extension": ".py",
374+
"mimetype": "text/x-python",
375+
"name": "python",
376+
"nbconvert_exporter": "python",
377+
"pygments_lexer": "ipython3",
378+
"version": "3.6.10"
379+
}
380+
},
381+
"nbformat": 4,
382+
"nbformat_minor": 4
383+
}

0 commit comments

Comments
 (0)