Nota
Esta página foi gerada a partir do tutorials/chemistry/01_electronic_structure.ipynb.
Execute interativamente no IBM Quantum lab.
Estrutura eletrônica¶
Introdução¶
O Hamiltoniano molecular é
Porque os núcleos são muito mais pesados que os elétrons eles não se movem na mesma escala de tempo e, portanto, o comportamento de núcleos e elétrons pode ser desacoplado. Esta é a aproximação Born-Oppenheimer.
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 independent Schroedinger equation,
onde
Em particular a energia do estado fundamental é dada por:
onde \(\Psi_0\) é o estado fundamental do sistema.
No entanto, a dimensionalidade desse problema cresce exponencialmente com o número de graus de liberdade. Para enfrentar esta questão gostaríamos de preparar \(\Psi_0\) em um computador quântico e medir o valor esperado do Hamiltoniano (ou \(E_0\)) diretamente.
Então, como fazer isso concretamente?
O estado inicial de Hartree-Fock¶
Um bom ponto de partida para resolver esse problema é o método de Hartree-Fock (HF). Este método aproxima um problema de N corpos em N problemas de um corpo onde cada elétron evolui no campo médio dos outros. Resolver classicamente as equações de HF é eficiente e leva à energia de troca exata mas não inclui nenhuma correlação dos elétrons. Portanto, geralmente é um bom ponto de partida para começar a adicionar correlação.
The Hamiltonian can then be re-expressed in the basis of the solutions of the HF method, also called Molecular Orbitals (MOs):
com as integrais de 1 corpo
e integrais de 2 corpos
Os MOs (\(\phi_u\)) podem ser ocupados ou virtuais (desocupados). Um MO pode conter 2 elétrons. No entanto, a seguir nós na verdade trabalhamos com Orbitais de Spin que estão associados a um elétron com spin up (\(\alpha\)) ou spin down (\(\beta\)). Assim Orbitais de Spin podem conter um elétron ou ser desocupados.
We now show how to concretely realise these steps with Qiskit.
O Qiskit faz interface com diferentes códigos clássicos que são capazes de encontrar as soluções de HF. A interface entre o Qiskit e os códigos a seguir já está disponível: * Gaussian * Psi4 * PyQuante * PySCF
A seguir, montamos um driver PySCF, para a molécula de hidrogênio com comprimento de ligação em equilíbrio (0,735 angstrom) no estado singleto e sem carga nenhuma.
[4]:
from qiskit.chemistry.drivers import PySCFDriver, UnitsType, Molecule
molecule = Molecule(geometry=[['H', [0., 0., 0.]],
['H', [0., 0., 0.735]]],
charge=0, multiplicity=1)
driver = PySCFDriver(molecule = molecule, unit=UnitsType.ANGSTROM, basis='sto3g')
Para mais informações sobre os drivers consulte https://qiskit.org/documentation/apidoc/qiskit.chemistry.drivers.html
O mapeamento de fermions a qubits¶
O Hamiltoniano dado na seção anterior é expresso em termos de operadores fermiônicos. Para codificar o problema no estado de um computador quântico, esses operadores devem ser mapeados para operadores de spin (na verdade, os qubits seguem estatísticas de spin).
Existem diferentes tipos de mapeamento com propriedades diferentes. O Qiskit já suporta os seguintes mapeamentos: * O mapeamento Jordan-Wigner ‘jordan_wigner’ mapping (über das paulische äquivalenzverbot. In The Collected Works of Eugene Paul Wigner (pp. 109-129). Springer, Berlin, Heidelberg (1993)). * A paridade ‘parity’ (The Journal of chemical physics, 137(22), 224109 (2012)) * O Bravyi-Kitaev ‘bravyi_kitaev’ (Annals of Physics, 298(1), 210-226 (2002)) * The Bravyi-Kitaev Super Fast ‘bksf’ (Annals of Physics, 298(1), 210-226 (2002))
O mapeamento Jordan-Wigner é particularmente interessante já que mapeia cada Orbital de Spin a um qubit (como mostrado na Figura acima).
Aqui montamos um objeto que contém todas as informações sobre qualquer transformação do Hamiltoniano fermiônico para o Hamiltoniano do qubit. Neste exemplo simplesmente pedimos o mapeamento Jordan-Wigner.
[3]:
from qiskit.chemistry.transformations import (FermionicTransformation,
FermionicTransformationType,
FermionicQubitMappingType)
fermionic_transformation = FermionicTransformation(
transformation=FermionicTransformationType.FULL,
qubit_mapping=FermionicQubitMappingType.JORDAN_WIGNER,
two_qubit_reduction=False,
freeze_core=False)
Se agora transformarmos este Hamiltoniano para o determinado driver definido acima obtemos nosso operador de qubit:
[4]:
qubit_op, _ = fermionic_transformation.transform(driver)
print(qubit_op)
print(fermionic_transformation.molecule_info)
SummedOp([
-0.8105479805373266 * IIII,
0.17218393261915552 * IIIZ,
-0.22575349222402472 * IIZI,
0.1721839326191556 * IZII,
-0.22575349222402466 * ZIII,
0.1209126326177663 * IIZZ,
0.16892753870087912 * IZIZ,
0.045232799946057854 * XXYY,
0.045232799946057854 * YYYY,
0.045232799946057854 * XXXX,
0.045232799946057854 * YYXX,
0.16614543256382414 * ZIIZ,
0.16614543256382414 * IZZI,
0.17464343068300453 * ZIZI,
0.1209126326177663 * ZZII
])
{'num_particles': [1, 1], 'num_orbitals': 4, 'two_qubit_reduction': False, 'z2_symmetries': <qiskit.aqua.operators.legacy.weighted_pauli_operator.Z2Symmetries object at 0x123f6d940>}
No conjunto base mínimo (STO-3G) 4 qubits são necessários. Poderíamos reduzir ainda mais a contagem de qubits utilizando o mapeamento de Paridade, que permite que nos livermos de qubits ao considerar as simetrias.
[5]:
fermionic_transformation_2 = FermionicTransformation(
transformation=FermionicTransformationType.FULL,
qubit_mapping=FermionicQubitMappingType.PARITY,
two_qubit_reduction=True,
freeze_core=False)
qubit_op_2, _ = fermionic_transformation_2.transform(driver)
print(qubit_op_2)
SummedOp([
-1.052373245772859 * II,
0.39793742484318007 * IZ,
-0.39793742484318007 * ZI,
-0.01128010425623538 * ZZ,
0.18093119978423136 * XX
])
Desta vez apenas 2 qubits são necessários.
Another possibility is to use the Particle-Hole transformation (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.
[6]:
fermionic_transformation_3 = FermionicTransformation(
transformation=FermionicTransformationType.PARTICLE_HOLE,
qubit_mapping=FermionicQubitMappingType.JORDAN_WIGNER,
two_qubit_reduction=False,
freeze_core=False)
qubit_op_3, _ = fermionic_transformation_3.transform(driver)
print(qubit_op_3)
SummedOp([
1.0264200106656571 * IIII,
0.17218393261915554 * IIIZ,
-0.22575349222402463 * IIZI,
0.17218393261915554 * IZII,
-0.22575349222402458 * ZIII,
0.16892753870087912 * IZIZ,
0.045232799946057854 * YYYY,
0.045232799946057854 * XXYY,
0.045232799946057854 * YYXX,
0.045232799946057854 * XXXX,
0.1209126326177663 * IIZZ,
0.16614543256382414 * IZZI,
0.16614543256382414 * ZIIZ,
0.17464343068300453 * ZIZI,
0.1209126326177663 * ZZII
])
A lista de mapeamentos e transformações disponíveis são
[7]:
print('*Transformations')
for fer_transform in FermionicTransformationType:
print(fer_transform)
print('\n*Mappings')
for fer_mapping in FermionicQubitMappingType:
print(fer_mapping)
*Transformations
FermionicTransformationType.FULL
FermionicTransformationType.PARTICLE_HOLE
*Mappings
FermionicQubitMappingType.JORDAN_WIGNER
FermionicQubitMappingType.PARITY
FermionicQubitMappingType.BRAVYI_KITAEV
Agora que o Hamiltoniano está pronto, ele pode ser usado em um algoritmo quântico para encontrar informações sobre a estrutura eletrônica da molécula correspondente. Confira nossos tutoriais em Cálculo do Estado Fundamental e Cálculo dos Estados Excitados para saber mais sobre como fazer isso no Qiskit!
[1]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | 0.23.0 |
Terra | 0.16.0 |
Aer | 0.7.0 |
Ignis | 0.5.0 |
Aqua | 0.8.0 |
IBM Q Provider | 0.11.0 |
System information | |
Python | 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 13:42:17) [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] |
OS | Darwin |
CPUs | 2 |
Memory (Gb) | 16.0 |
Tue Oct 20 18:02:17 2020 CEST |
This code is a part of Qiskit
© Copyright IBM 2017, 2020.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: