Skip to content

Molecule Eigensolver (VQE method)

View on GitHub

Evaluating the ground state of a molecular Hamiltonian allows us to understand the chemical properties of the molecule. In this demo, we demonstrate the usage of Variational Quantum Eigensolver (VQE) for finding the ground states and energies of several molecules: 𝐻2 , 𝐻2𝑂 and 𝐿𝑖𝐻 .

VQE is a leading method for finding approximate values of ground state wavefuncions and energies for complicated quantum systems, and as such can give solutions for complex molecular structures. The overview of the VQE method is as following: a problem (i.e. a molecule) is defined by a Hamiltonian which ground state is sought. Then, a choice of a parameterized ansatz is made. Using a hybrid quantum-classical algorithm, a solution for the defined parameters which minimize the expectation value for the energy is found. A clever ansatz will lead to an estimated ground state solution.

Within the scope of Classiq's VQE algorithm, the user defines a Molecule which is being translated to a concise Hamiltonian. Then, a choice between several types of well studied ansatz is given, which can be carefully picked to fit your Molecule type. In the last stage, the Hamiltonian and ansatz are sent to a classical optimizer. During this tutorial we will demonstrate the steps and user options in Classiq's VQE algorithm. Furthermore, the demonstration will present the optimization strength Classiq's VQE algorithm holds, and it's state of the art results in term of efficient quantum circuit - with ultimate combination of low depth and high accuracy, while minimizing the number of CX gates.

RESULTS

Comparison of different molecules in terms of width and depth. The more atoms in a molecule, the more qubits/circuit depth are necessary. System overload when more than 3 atoms.

h2

hw-eff ansatz: width 4/depth34

ucc ansatz: , width 1/depth 6, width 4, depth 3

total en -1.1342995783232035, exact result: -1.8572750302023786, vqe result: -1.854268572772183

h2o

hw-eff. ansatz: width 12/depth 375, (conn map 0-1..10-11, reps 11)

ucc ansatz: width 8/depth 1218, width 12/depth 1048

total energy -71.7605079203085, exact result: -23.544497240443615, vqe result: -80.95442108093192

co2

hw-eff ansatz: width 24/depth 175

ucc ansatz: width 20/depth 19767, width 24/depth 16968

Error number 90001 occurred. The resources needed to execute this request are insufficient. This may be due to computational limitations, or high load on Classiq's servers.

0. Pre-requirments

The model is using several Classiq's libraries.

# !pip install classiq
from classiq import *
# import classiq
# classiq.authenticate()
import numpy as np

from classiq import QuantumProgram, construct_chemistry_model, execute, show, synthesize
from classiq.applications.chemistry import (
    ChemistryExecutionParameters,
    HEAParameters,
    Molecule,
    MoleculeProblem,
    UCCParameters,
)
from classiq.execution import (
    ClassiqBackendPreferences,
    ClassiqSimulatorBackendNames,
    ExecutionPreferences,
    OptimizerType,
)
from classiq.synthesis import set_execution_preferences

1. Generate Qubit Hamiltonian

The first step is to define the molecule we wish to simulate. We hereby declare the class Molecule and insert a list of atoms and their spacial positions. The algorithm will automatically regard relevant attributes such as the atom's mass, charge and spin.

As mentioned above, during this tutorial, we demonstrate how to define and find the ground state and energies for 3 molecules:

# hydrogen
molecule_H2 = Molecule(atoms=[("H", (0.0, 0.0, 0)), ("H", (0.0, 0.0, 0.735))])

# oxygen
molecule_O2 = Molecule(atoms=[("O", (0.0, 0.0, 0)), ("O", (0.0, 0.0, 1.16))])

# lithium hydride
molecule_LiH = Molecule(atoms=[("H", (0.0, 0.0, 0.0)), ("Li", (0.0, 0.0, 1.596))])

# water
molecule_H2O = Molecule(
    atoms=[("O", (0.0, 0.0, 0.0)), ("H", (0, 0.586, 0.757)), ("H", (0, 0.586, -0.757))]
)
# beryllium hydride
molecule_BeH2 = Molecule(
    atoms=[("Be", (0.0, 0.0, 0.0)), ("H", (0, 0, 1.334)), ("H", (0, 0, -1.334))]
)
# carbon dioxide
molecule_CO2 = Molecule(
    atoms=[("C", (0.0, 0.0, 0.0)), ("O", (0, 0, 1.1693)), ("O", (0, 0, -1.1693))]
)

# ethyne, acetylene
molecule_C2H2 = Molecule(
    atoms=[
        ("C", (0, 0, -0.5977)),
        ("C", (0, 0, 0.5977)),
        ("H", (0, 0, -1.6692)),
        ("H", (0, 0, 1.6692)),
    ]
)

# chloroform
molecule_CH3Cl = Molecule(
    atoms=[
        ("C", (0, 0, -1.1401)),
        ("Cl", (0, 0, 0.6645)),
        ("H", (0, 1.0343, -1.4855)),
        ("H", (0.8957, -0.5171, -1.4855)),
        ("H", (-0.8957, -0.5171, -1.4855)),
    ]
)

# ethylene
molecule_C2H4 = Molecule(
    atoms=[
        ("C", (0, 0, 0.6673)),
        ("C", (0, 0, -0.6673)),
        ("H", (0, 0.9239, 1.2411)),
        ("H", (0, -0.9239, 1.2411)),
        ("H", (0, -0.9239, -1.2411)),
        ("H", (0, 0.9239, -1.2411)),
    ]
)

Similarly, the user is able to construct any valid essambly of atoms. The distances are recived in Å (\(10^{-10} m\)). We will continue this demonstration with a specific molecule. The user can change the molecule below to study other cases.

molecule = molecule_H2O

Next, we define the parameters of the Hamiltonian generation program. The user has a choice over the following options:

  • mapping (str): the mapping between the fermionic Hamiltonian and an qubits Hamiltonian. Supported types:

    - "jordan_wigner"
    
    - "parity"
    
    - "bravyi_kitaev"
    
    - "fast_bravyi_kitaev"
    
  • freeze_core (bool): remove the "core" orbitals of the atoms defining the molecule.

  • z2_symmetries (bool): whether to perform z2 symmetries reduction. If symmetries in the molecules exist, this option will decrease the number of qubits used and will efficient the Hamiltonian and thus the calculations.

Finally, the Hamiltonian is generated from MoleculeProblem.

chemistry_problem = MoleculeProblem(
    molecule=molecule,
    mapping="jordan_wigner",  #'bravyi_kitaev'
    z2_symmetries=True,
    freeze_core=True,
)

operator = chemistry_problem.generate_hamiltonian()
gs_problem = chemistry_problem.update_problem(operator.num_qubits)
print("Your Hamiltonian is", operator.show(), sep="\n")
Your Hamiltonian is
-18.374 * IIIIIIII
+1.169 * ZIZIZIZZ
-0.061 * IIZIIZZX
+0.061 * ZIIIZZIX
+0.139 * IIIIIZXI
-0.139 * ZIZIZZXZ
+0.813 * ZIIIZZII
+0.192 * ZIZIZXZZ
-0.192 * IIZIIXZZ
+0.823 * IIIIIIIZ
-0.114 * IIZIIIYY
-0.114 * IIZIIIXX
+1.640 * IIZIIIII
+0.385 * IIIIIIZI
+0.377 * IIIIIZII
+1.169 * ZZZZZIII
-0.061 * ZZZXIIII
+0.061 * IIIXZIII
+0.139 * ZXIIIIII
-0.139 * IXZZZIII
+0.813 * IIIIZIII
-0.192 * YZZZYIII
-0.192 * XZZZXIII
+0.823 * IIIZIIII
-0.114 * IYZYIIII
-0.114 * IXZXIIII
+0.385 * IZIIIIII
+0.377 * ZIIIIIII
+0.125 * IIZIIZZZ
+0.024 * IIIIIXII
-0.024 * ZIIIZXII
+0.138 * ZIZIZIZI
+0.019 * ZIIIZIXX
+0.019 * ZIIIZIYY
+0.338 * ZIIIZIZZ
+0.128 * ZIZIZIIZ
+0.141 * ZIZIZZZZ
-0.003 * ZIZIZIZX
+0.003 * IIIIIIIX
+0.029 * ZIIIZIXI
-0.029 * IIZIIIXZ
-0.011 * ZIIIZYIY
-0.011 * IIIIIXIX
-0.000 * IIIIIYIY
-0.000 * IIZIIYZY
-0.011 * IIZIIXZX
-0.011 * ZIZIZYZY
+0.010 * ZIZIZYYZ
+0.016 * IIZIIXXZ
+0.005 * IIZIIYYZ
+0.005 * IIIIIYYI
+0.016 * IIIIIXXI
+0.010 * ZIIIZYYI
+0.030 * IIIIIZXZ
-0.030 * ZIZIZZXI
-0.023 * IIIIIZZX
+0.023 * ZIZIZZIX
-0.001 * IIZIIZIX
+0.001 * ZIIIZZZX
+0.001 * IIZIIIZX
-0.001 * ZIIIZIIX
+0.065 * IIZIIZXI
-0.065 * ZIIIZZXZ
+0.020 * IIIIIIXI
-0.020 * ZIZIZIXZ
+0.182 * IZIZIIZZ
+0.001 * ZZIZZZZX
-0.001 * IZZZIZIX
+0.036 * ZZZZZZXI
-0.036 * IZIZIZXZ
+0.036 * ZZIZXZZZ
-0.036 * IIZIXZZZ
-0.036 * ZZZZXIII
+0.036 * IIIIXIII
+0.010 * ZZZZXXII
-0.010 * IIIIXXII
+0.010 * IZIZYYZZ
-0.010 * ZIZIYYZZ
+0.001 * IZIXZIZZ
-0.001 * ZIZXIIZZ
+0.031 * ZZIXIZZX
-0.031 * IIZXZZZX
-0.031 * IZZXZZIX
+0.031 * ZIIXIZIX
+0.005 * ZZZXIZXI
-0.005 * IIIXZZXI
-0.005 * IZIXZZXZ
+0.005 * ZIZXIZXZ
+0.036 * ZZXIIZZI
-0.036 * IIXZZZZI
-0.036 * IZXIZZIZ
+0.036 * ZIXZIZIZ
+0.036 * IXZIZIZZ
-0.036 * ZXIZIIZZ
+0.005 * ZXZIIZZX
-0.005 * IXIZZZZX
-0.005 * IXIIZZIX
+0.005 * ZXZZIZIX
+0.025 * ZXIIIZXI
-0.025 * IXZZZZXI
-0.025 * IXZIZZXZ
+0.025 * ZXIZIZXZ
+0.010 * XIZIIZZZ
-0.010 * XZIZZZZZ
-0.010 * XIIIIIII
+0.010 * XZZZZIII
+0.015 * XIIIIXII
-0.015 * XZZZZXII
+0.015 * YIZIZYZZ
-0.015 * YZIZIYZZ
+0.161 * ZIZIIIZZ
+0.002 * IIZIZZZX
-0.002 * ZIIIIZIX
+0.019 * IIIIZZXI
-0.019 * ZIZIIZXZ
-0.005 * IIZYYZZZ
-0.005 * IIZXXZZZ
+0.005 * IIIYYIII
+0.005 * IIIXXIII
+0.009 * IIIYYXII
+0.009 * IIIXXXII
-0.009 * ZIZYXYZZ
+0.009 * ZIZXYYZZ
+0.010 * IYIZYZZZ
+0.010 * IXIZXZZZ
-0.010 * IYZZYIII
-0.010 * IXZZXIII
-0.009 * IYZZYXII
-0.009 * IXZZXXII
+0.009 * ZYIZXYZZ
-0.009 * ZXIZYYZZ
+0.035 * XZIZXIZZ
+0.035 * YZIZYIZZ
+0.019 * YZIZYZZX
+0.019 * XZIZXZZX
+0.019 * XZZZXZIX
+0.019 * YZZZYZIX
-0.019 * YZZZYZXI
-0.019 * XZZZXZXI
-0.019 * XZIZXZXZ
-0.019 * YZIZYZXZ
+0.169 * ZIZZZIZZ
-0.026 * IIZZIZZX
+0.026 * ZIIZZZIX
+0.022 * IIIZIZXI
-0.022 * ZIZZZZXZ
+0.012 * IIYYIZZI
+0.012 * IIXXIZZI
-0.012 * ZIYYZZIZ
-0.012 * ZIXXZZIZ
-0.024 * ZYIYZIZZ
-0.024 * ZXIXZIZZ
+0.008 * IYIYIZZX
+0.008 * IXIXIZZX
-0.008 * ZYZYZZIX
-0.008 * ZXZXZZIX
-0.015 * IYZYIZXI
-0.015 * IXZXIZXI
+0.015 * ZYIYZZXZ
+0.015 * ZXIXZZXZ
+0.019 * YZIYIZZZ
+0.019 * XZIXIZZZ
-0.019 * YZZYIIII
-0.019 * XZZXIIII
+0.004 * YZZYIXII
+0.004 * XZZXIXII
-0.004 * XZIYZYZZ
+0.004 * YZIXZYZZ
-0.015 * IYYIIZZI
-0.015 * IXXIIZZI
+0.015 * ZYYIZZIZ
+0.015 * ZXXIZZIZ
+0.154 * ZZZIZIZZ
+0.015 * IZZIIZZX
-0.015 * ZZIIZZIX
+0.024 * IZIIIZXI
-0.024 * ZZZIZZXZ
-0.025 * YYZIIZZZ
-0.025 * XXZIIZZZ
+0.025 * YYIIIIII
+0.025 * XXIIIIII
+0.002 * YYIIIXII
+0.002 * XXIIIXII
-0.002 * XYZIZYZZ
+0.002 * YXZIZYZZ
+0.156 * IIZIZIZZ
-0.003 * ZIZIIZZX
+0.003 * IIIIZZIX
+0.017 * ZIIIIZXI
-0.017 * IIZIZZXZ
+0.138 * ZIIIZZIZ
-0.018 * ZIZIZZYY
-0.018 * ZIZIZZXX
+0.307 * ZIZIZZII
+0.125 * ZIIIZZZI
+0.229 * ZIIIZIII
+0.039 * ZIZIZXZI
-0.039 * IIZIIXZI
+0.008 * ZIIIZXXX
+0.008 * ZIIIZXYY
+0.001 * ZIIIZYXY
+0.001 * IIIIIYYX
-0.008 * IIIIIXXX
-0.008 * IIIIIXYY
+0.089 * ZIIIZXZZ
-0.089 * IIIIIXZZ
+0.026 * ZIZIZXIZ
-0.026 * IIZIIXIZ
+0.161 * IZZZIZII
+0.035 * IZIZIXZZ
-0.035 * ZZIZZXZZ
-0.005 * IZZZYZIY
+0.005 * ZIIIYZIY
-0.005 * ZZZZXIIX
+0.005 * IIIIXIIX
+0.010 * IZIZYZYZ
-0.010 * ZIZIYZYZ
+0.010 * ZZIZXIXZ
-0.010 * IIZIXIXZ
+0.002 * IZZXZZII
-0.002 * ZIIXIZII
-0.019 * IZIXZXZZ
+0.019 * ZIZXIXZZ
+0.019 * ZZIXIXZZ
-0.019 * IIZXZXZZ
+0.019 * IXIIZZII
-0.019 * ZXZZIZII
+0.019 * IXZIZXZZ
-0.019 * ZXIZIXZZ
-0.019 * ZXZIIXZZ
+0.019 * IXIZZXZZ
+0.009 * YIIIZZIY
-0.009 * YZZZIZIY
+0.009 * XIIIIIIX
-0.009 * XZZZZIIX
-0.009 * YIZIZZYZ
+0.009 * YZIZIZYZ
-0.009 * XIZIIIXZ
+0.009 * XZIZZIXZ
+0.313 * ZIIIIZII
-0.001 * ZIZIIXZZ
+0.001 * IIZIZXZZ
-0.012 * ZIIYXZIY
+0.012 * ZIIXYZIY
+0.012 * IIIYYIIX
+0.012 * IIIXXIIX
+0.007 * ZIZYXZYZ
-0.007 * ZIZXYZYZ
-0.007 * IIZYYIXZ
-0.007 * IIZXXIXZ
+0.007 * ZIXZXZIZ
+0.007 * ZIYZYZIZ
+0.007 * IIYZYIIZ
+0.007 * IIXZXIIZ
+0.007 * ZYZZXZIY
-0.007 * ZXZZYZIY
-0.007 * IYZZYIIX
-0.007 * IXZZXIIX
-0.018 * ZYIZXZYZ
+0.018 * ZXIZYZYZ
+0.018 * IYIZYIXZ
+0.018 * IXIZXIXZ
-0.001 * XZZZXZII
-0.001 * YZZZYZII
+0.076 * XZIZXXZZ
+0.076 * YZIZYXZZ
+0.150 * ZIIZZZII
+0.040 * ZIZZZXZZ
-0.040 * IIZZIXZZ
-0.011 * ZYZYZZII
-0.011 * ZXZXZZII
-0.020 * ZYIYZXZZ
-0.020 * ZXIXZXZZ
+0.020 * IYIYIXZZ
+0.020 * IXIXIXZZ
-0.001 * XZZYZZIY
+0.001 * YZZXZZIY
+0.001 * YZZYIIIX
+0.001 * XZZXIIIX
-0.011 * XZIYZZYZ
+0.011 * YZIXZZYZ
+0.011 * YZIYIIXZ
+0.011 * XZIXIIXZ
+0.006 * XZXIZZIZ
+0.006 * YZYIZZIZ
+0.006 * YZYIIIIZ
+0.006 * XZXIIIIZ
+0.143 * ZZIIZZII
+0.009 * ZZZIZXZZ
-0.009 * IZZIIXZZ
-0.012 * XYIIZZIY
+0.012 * YXIIZZIY
+0.012 * YYIIIIIX
+0.012 * XXIIIIIX
+0.016 * XYZIZZYZ
-0.016 * YXZIZZYZ
-0.016 * YYZIIIXZ
-0.016 * XXZIIIXZ
+0.305 * IIIIZZII
+0.351 * IIZIIIIZ
+0.120 * IIIIIIZZ
+0.135 * IIIIIZIZ
-0.059 * IIIIIIYY
-0.059 * IIIIIIXX
-0.025 * IIZIIZYY
-0.025 * IIZIIZXX
+0.169 * ZZZZZIIZ
-0.024 * ZZIZZIYY
-0.024 * ZZIZZIXX
+0.019 * ZZIZXYZY
-0.019 * IIZIXYZY
+0.019 * ZZIZXXZX
-0.019 * IIZIXXZX
-0.026 * ZZZXIIIZ
+0.026 * IIIXZIIZ
+0.008 * ZZIXIIYY
-0.008 * IIZXZIYY
+0.008 * ZZIXIIXX
-0.008 * IIZXZIXX
+0.012 * ZZYIIIIY
-0.012 * IIYZZIIY
+0.012 * ZZXIIIIX
-0.012 * IIXZZIIX
+0.022 * ZXIIIIIZ
-0.022 * IXZZZIIZ
-0.015 * ZXZIIIYY
+0.015 * IXIZZIYY
-0.015 * ZXZIIIXX
+0.015 * IXIZZIXX
+0.004 * XIZIIYZY
-0.004 * XZIZZYZY
+0.004 * XIZIIXZX
-0.004 * XZIZZXZX
+0.150 * IIIIZIIZ
-0.011 * IIZIZIYY
-0.011 * IIZIZIXX
+0.001 * IIZYYYZY
+0.001 * IIZXXYZY
+0.001 * IIZYYXZX
+0.001 * IIZXXXZX
+0.011 * IYIZYYZY
+0.011 * IXIZXYZY
+0.011 * IYIZYXZX
+0.011 * IXIZXXZX
-0.040 * YZZZYIIZ
-0.040 * XZZZXIIZ
+0.020 * YZIZYIYY
+0.020 * XZIZXIYY
+0.020 * YZIZYIXX
+0.020 * XZIZXIXX
+0.196 * IIIZIIIZ
-0.030 * IIZZIIYY
-0.030 * IIZZIIXX
-0.014 * IIXYIIIY
+0.014 * IIYXIIIY
+0.014 * IIYYIIIX
+0.014 * IIXXIIIX
-0.030 * IYZYIIIZ
-0.030 * IXZXIIIZ
+0.017 * IYIYIIYY
+0.017 * IXIXIIYY
+0.017 * IYIYIIXX
+0.017 * IXIXIIXX
+0.017 * YZIYIYZY
+0.017 * XZIXIYZY
+0.017 * YZIYIXZX
+0.017 * XZIXIXZX
+0.000 * IYXIIIIY
-0.000 * IXYIIIIY
-0.000 * IYYIIIIX
-0.000 * IXXIIIIX
+0.137 * IZIIIIIZ
-0.011 * IZZIIIYY
-0.011 * IZZIIIXX
-0.014 * YYZIIYZY
-0.014 * XXZIIYZY
-0.014 * YYZIIXZX
-0.014 * XXZIIXZX
+0.152 * ZIIIIIIZ
-0.010 * ZIZIIIYY
-0.010 * ZIZIIIXX
+0.285 * IIZIIIZI
+0.306 * IIZIIZII
+0.338 * ZZIZZIII
-0.023 * ZZIXIIII
+0.023 * IIZXZIII
-0.015 * ZZYIIIYI
+0.015 * IIYZZIYI
-0.015 * ZZXIIIXI
+0.015 * IIXZZIXI
+0.065 * ZXZIIIII
-0.065 * IXIZZIII
+0.307 * IIZIZIII
-0.006 * IIXZYYZI
+0.006 * IIYZXYZI
+0.006 * IIYZYXZI
+0.006 * IIXZXXZI
-0.089 * YZIZYIII
-0.089 * XZIZXIII
+0.351 * IIZZIIII
+0.000 * IIXYIIYI
-0.000 * IIYXIIYI
-0.000 * IIYYIIXI
-0.000 * IIXXIIXI
-0.059 * IYIYIIII
-0.059 * IXIXIIII
-0.010 * IYXIIIYI
+0.010 * IXYIIIYI
+0.010 * IYYIIIXI
+0.010 * IXXIIIXI
-0.006 * YZXIIYZI
+0.006 * XZYIIYZI
+0.006 * YZYIIXZI
+0.006 * XZXIIXZI
+0.285 * IZZIIIII
+0.306 * ZIZIIIII
+0.113 * IIIIIZZI
+0.154 * ZZZZZIZI
-0.025 * ZZZZXYYI
+0.025 * IIIIXYYI
-0.025 * ZZZZXXXI
+0.025 * IIIIXXXI
+0.015 * ZZZXIIZI
-0.015 * IIIXZIZI
+0.024 * ZXIIIIZI
-0.024 * IXZZZIZI
+0.002 * XIIIIYYI
-0.002 * XZZZZYYI
+0.002 * XIIIIXXI
-0.002 * XZZZZXXI
+0.143 * IIIIZIZI
+0.012 * IIIYYYYI
+0.012 * IIIXXYYI
+0.012 * IIIYYXXI
+0.012 * IIIXXXXI
-0.016 * IYZZYYYI
-0.016 * IXZZXYYI
-0.016 * IYZZYXXI
-0.016 * IXZZXXXI
-0.009 * YZZZYIZI
-0.009 * XZZZXIZI
+0.137 * IIIZIIZI
-0.011 * IYZYIIZI
-0.011 * IXZXIIZI
-0.014 * YZZYIYYI
-0.014 * XZZXIYYI
-0.014 * YZZYIXXI
-0.014 * XZZXIXXI
+0.149 * IZIIIIZI
+0.029 * YYIIIYYI
+0.029 * XXIIIYYI
+0.029 * YYIIIXXI
+0.029 * XXIIIXXI
+0.142 * ZIIIIIZI
+0.156 * ZZZZZZII
-0.003 * ZZZXIZII
+0.003 * IIIXZZII
+0.017 * ZXIIIZII
-0.017 * IXZZZZII
+0.152 * IIIZIZII
-0.010 * IYZYIZII
-0.010 * IXZXIZII
+0.142 * IZIIIZII
+0.125 * ZZZZIIII
+0.024 * XIIIXIII
+0.024 * YIIIYIII
+0.138 * ZZZIZIII
+0.019 * ZXIXZIII
+0.019 * ZYIYZIII
+0.128 * ZIZZZIII
+0.141 * IZZZZIII
-0.003 * ZZZXZIII
+0.003 * IIIXIIII
+0.029 * ZXIIZIII
-0.029 * IXZZIIII
-0.011 * XIIYYIII
-0.011 * XIIXXIII
-0.000 * YIIYXIII
-0.000 * YZZYXIII
-0.011 * XZZXXIII
-0.011 * XZZYYIII
+0.010 * XYZZYIII
+0.016 * XXZZXIII
+0.005 * YYZZXIII
+0.005 * YYIIXIII
+0.016 * XXIIXIII
+0.010 * XYIIYIII
+0.030 * ZXIZIIII
-0.030 * IXZIZIII
-0.001 * ZIZXIIII
+0.001 * IZIXZIII
+0.001 * IZZXIIII
-0.001 * ZIIXZIII
+0.020 * IXIIIIII
-0.020 * ZXZZZIII
+0.138 * IIIZZIII
-0.018 * IYZYZIII
-0.018 * IXZXZIII
+0.125 * IZIIZIII
-0.039 * YZZIYIII
-0.039 * XZZIXIII
-0.008 * YXIXYIII
-0.008 * YYIYYIII
+0.001 * XXIYYIII
+0.001 * YYIXXIII
-0.008 * XXIXXIII
-0.008 * XYIYXIII
-0.026 * YIZZYIII
-0.026 * XIZZXIII
+0.120 * IZIZIIII
+0.135 * ZIIZIIII
-0.025 * ZYZYIIII
-0.025 * ZXZXIIII
+0.113 * ZZIIIIII

The output of the above code lines is the Hamiltonian presented as a superposition of Pauli matrices multiplication. One can easily confirm that using z2*symmetries=True, the number of qubits are reduced (compered to z2_symmetries=False): for \(H_2\) - from 4 to 1, for \(LiH\) from 12 to 8, and for \(H*{2}O\) from 14 to 10.

2. Constructing and Synthesizing a Ground State Solver

A ground state solver model consists of a parameterized eigenfunction ("the ansatz"), on which we run a VQE. In addition, a post-process of the result allows to return the total energy (combining the ground state energy of the Hamiltonian, the nuclear repulsion and the static nuclear energy).

Once we've specified an Hamiltonian and a desired Ansatz, we send them to the VQE algorithm in order to find the Hamiltonian's ground state. In the process, the algorithm will send requests to a classical server, which task is to minimize the energy expectation value and return the optimized parameters. The simulator and optimizing parameters are defined as part of the VQE part of the model. The user should control the max_iteration value in a manner so the solution has reached a stable convergence. In addition, the value num_shots sets the number of measurements performed after each iteration, thus influence the accuracy of the solutions.

We demonstrate two different proposal for the wavefunction solution ansatz: (1) Hardware (HW) efficient, and (2) Unitary Coupled Cluster (UCC). For groundstate solvers it is typical to initialize the Ansatz with the Hartree-Fock state.

2.1 HW-Efficient Ansatz

Hardware-efficient ansatz is a suggested solution that is generated to fit a specific hardware [1]. The ansatz creates a state with given number of parameters by user choice (number of qubits, that should fit the Hamiltonian), and creates entanglement between the qubits by the inputed connectivity map. In this example, a 4 qubit map is given, which is specifically made of \(H_2\) with z2_symmetries=False.

After constructing the model, we can synthesize it and view the outputted circuit, in charged on creating the state with an interactive interface.

chemistry_problem = MoleculeProblem(
    molecule=molecule,
    mapping="jordan_wigner",  #'bravyi_kitaev'
    z2_symmetries=False,
    freeze_core=True,
)

hwea_params = HEAParameters(
    num_qubits=12,
    connectivity_map=[
        (0, 1),
        (1, 2),
        (2, 3),
        (3, 4),
        (4, 5),
        (5, 6),
        (6, 7),
        (7, 8),
        (8, 9),
        (9, 10),
    ],
    reps=3,
    one_qubit_gates=["x", "ry"],
    two_qubit_gates=["cx"],
)

qmod = construct_chemistry_model(
    chemistry_problem=chemistry_problem,
    use_hartree_fock=True,
    ansatz_parameters=hwea_params,
    execution_parameters=ChemistryExecutionParameters(
        optimizer=OptimizerType.COBYLA,
        max_iteration=30,
        initial_point=None,
    ),
)

backend_preferences = ClassiqBackendPreferences(
    backend_name=ClassiqSimulatorBackendNames.SIMULATOR
)

qmod = set_execution_preferences(
    qmod,
    execution_preferences=ExecutionPreferences(
        num_shots=1000, backend_preferences=backend_preferences
    ),
)
# optional:

# from classiq import write_qmod
# write_qmod(qmod, name="molecule_eigensolver")
qprog = synthesize(qmod)
# show(qprog) # optional

2.2. UCC Ansatz

Next, we show how to create the commonly used chemistry-inspired UCC ansatz, which is a unitary version of the classical coupled cluster (CC) method [2] .

The parameter that defines the UCC ansatz is:

  • excitations (List[int] or List[str]): list of desired excitations. Allowed excitations:
    - 1 for singles
    
    - 2 for doubles
    
    - 3 for triples
    
    - 4 for quadruples
    

Once again, after the code lines bellow run, the user is able to view the outputted circuit, in charged on creating the state with an interactive interface. In addition, the depth of the circuit is printed.

chemistry_problem = MoleculeProblem(
    molecule=molecule,
    mapping="jordan_wigner",  #'bravyi_kitaev'
    z2_symmetries=True,
    freeze_core=True,
)

serialized_chemistry_model = construct_chemistry_model(
    chemistry_problem=chemistry_problem,
    use_hartree_fock=True,
    ansatz_parameters=UCCParameters(excitations=[1, 2]),
    execution_parameters=ChemistryExecutionParameters(
        optimizer=OptimizerType.COBYLA,
        max_iteration=30,
        initial_point=None,
    ),
)

backend_preferences = ClassiqBackendPreferences(
    backend_name=ClassiqSimulatorBackendNames.SIMULATOR
)

serialized_chemistry_model = set_execution_preferences(
    serialized_chemistry_model,
    execution_preferences=ExecutionPreferences(
        num_shots=1000, backend_preferences=backend_preferences
    ),
)

qprog = synthesize(serialized_chemistry_model)
# show(qprog) # optional

circuit = QuantumProgram.from_qprog(qprog)
print(f"circuit depth: {circuit.transpiled_circuit.depth}")
circuit depth: 1048

Classiq's UCC algorithm provides an highly efficient solution in aspects of circuit depth and number of CX gates. Those ultimately reduce the gate's time and amount of resources needed for its operation.

3. Execute to Find Ground State

Once we've synthesized the model we can execute it.

Uncomment the remaining code lines to run the final part. It will take a few minutes.

# result = execute(qprog).result()
# chemistry_result_dict = result[1].value

Execution of the quantum program returns several useful outputs:

  • energy : the output of the VQE algorithm - the electronic energy simulated.

  • nuclear_repulsion : the electrostatic energy generated by the atom's nuclei.

  • hartree_fock_energy : the Hartree Fock energy.

  • total_energy : this is the ground state energy of the Hamiltonian (combining the energy, the nuclear repulsion and the static nuclear energy).

It also contains the full VQE result from which we can get, for example:

  • optimal_parameters : gives the results for the anzats parameters minimizing that expectation value.

  • eigenstate : gives the ground state wave function.

Note the all energy are presented in units of Hartree.

# chemistry_result_dict["total_energy"]
# chemistry_result_dict["vqe_result"]["optimal_parameters"]

Finally, we can compare the VQE solution to the classical solution by employing exact diagonalization:

# mat = operator.to_matrix()
# w, v = np.linalg.eig(mat)
# print("exact result:", np.real(min(w)))
# print("vqe result:", chemistry_result_dict["energy"])

h2

hw-eff: width 4/depth34

ucc: width 1/depth 6, width 4, depth 3

total en -1.1342995783232035, exact result: -1.8572750302023786, vqe result: -1.854268572772183

h2o

hw-eff.: width 12/depth 375, (conn map 0-1..10-11, reps 11)

ucc: width 8/depth 1218, width 12/depth 1048

total energy -71.7605079203085, exact result: -23.544497240443615, vqe result: -80.95442108093192

co2

hw-eff: width 24/depth 175

ucc: width 20/depth 19767, width 24/depth 16968

[1] Abhinav Kandala, Antonio Mezzacapo, Kristan Temme, Maika Takita, Markus Brink, Jerry M. Chow, Jay M. Gambetta Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets. Nature 549, 242 (2017)

[2] Panagiotis Kl. Barkoutsos, Jerome F. Gonthier, Igor Sokolov, Nikolaj Moll, Gian Salis, Andreas Fuhrer, Marc Ganzhorn, Daniel J. Egger, Matthias Troyer, Antonio Mezzacapo, Stefan Filipp, and Ivano Tavernelli Quantum algorithms for electronic structure calculations: Particle-hole Hamiltonian and optimized wave-function expansions Phys. Rev. A 98, 022322 (2018)