forked from kottmanj/compact-bases
-
Notifications
You must be signed in to change notification settings - Fork 1
/
h4.py
125 lines (101 loc) · 3.51 KB
/
h4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import tequila as tq
import numpy
from qvalence.utils import Rot, Corr, GNM, gem_fast
"""
Compute the data from Fig.1 in the paper
uses accelerated structures
should take ~30 seconds
"""
data1 = {}
data2 = {}
# define the molecule
# rectangular
geometry1 = "H 1.5 0.0 0.0\nH 0.0 0.0 0.0\nH 1.5 0.0 1.5\nH 0.0 0.0 1.5"
# linear
geometry2 = "H 0.0 0.0 0.0\nH 0.0 0.0 1.5\nH 0.0 0.0 3.0\nH 0.0 0.0 4.5"
mol = tq.Molecule(geometry=geometry1, basis_set="sto-6g")
# replace with "orthonormalize_basis_orbitals()" for tq.version < 1.8.4
mol = mol.use_native_orbitals()
H = mol.make_hamiltonian()
# exact ground state energy
fci = mol.compute_energy("fci")
# define the graphs
edges1 = [(0,1),(2,3)]
edges2 = [(0,2),(1,3)]
edges3 = [(0,3),(1,2)]
graphs = [edges1, edges2, edges3]
# define the circuits to generate the basis
circuits = []
rot_circuits = []
spa_circuits = []
wfns = []
for i,edges in enumerate(graphs):
U = mol.make_ansatz(name="SPA", edges=edges, label="G{}".format(i))
spa_circuits.append(U)
UR = tq.QCircuit()
for e in edges:
UR += Rot(e,mol,i)
rot_circuits.append(UR)
circuits.append(U+UR)
# pre-optimize the circuits
variables_preopt = {}
energies = []
for U in circuits:
E = tq.ExpectationValue(U=U, H=H)
result = tq.minimize(E, silent=True)
variables_preopt = {**variables_preopt, **result.variables}
energies.append(result.energy)
wfn = tq.simulate(U, variables=result.variables)
wfns.append(wfn)
best = min(energies)
data1[(1,0)]=best
variables = {**variables_preopt}
# compute static energies with the pre-optimized basis
v,vv = gem_fast(circuits=circuits[:2], variables=variables, H=H)
data1[(2,0)]=v[0]
v,vv = gem_fast(circuits=circuits[:3], variables=variables, H=H)
data1[(3,0)]=v[0]
# relax circuit parameters
v,vv,variables = GNM(circuits=circuits[:2], variables=variables, H=H, silent=True, M=1)
data1[(2,1)]=v[0]
v,vv,variables = GNM(circuits=circuits[:3], variables=variables, H=H, silent=True, M=1)
data1[(3,1)]=v[0]
v,vv,variables = GNM(circuits=circuits[:2], variables=variables, H=H, silent=True)
data1[(2,2)]=v[0]
v,vv,variables = GNM(circuits=circuits[:3], variables=variables, H=H, silent=True, M=2)
data1[(3,2)]=v[0]
v,vv,variables = GNM(circuits=circuits[:3], variables=variables, H=H, silent=True)
data1[(3,3)]=v[0]
# add more freedeom in orbital rotations
# this is G(N,M)+UR
for i in range(len(circuits)):
e0 = graphs[i][0]
e1 = graphs[i][1]
UR = Rot((e0[0],e1[0]),mol,i)
UR+= Rot((e0[1],e1[1]),mol,i)
UR+= Rot((e0[0],e1[1]),mol,i)
circuits[i] += UR
# reset variables to pre-opt
variables=variables_preopt
# relax circuit parameters
v,vv,variables = GNM(circuits=circuits[:1], variables=variables, H=H, silent=True, M=1)
data2[(1,0)]=v[0]
v,vv,variables = GNM(circuits=circuits[:2], variables=variables, H=H, silent=True, M=1)
data2[(2,1)]=v[0]
v,vv,variables = GNM(circuits=circuits[:3], variables=variables, H=H, silent=True, M=1)
data2[(3,1)]=v[0]
v,vv,variables = GNM(circuits=circuits[:2], variables=variables, H=H, silent=True)
data2[(2,2)]=v[0]
v,vv,variables = GNM(circuits=circuits[:3], variables=variables, H=H, silent=True, M=2)
data2[(3,2)]=v[0]
v,vv,variables = GNM(circuits=circuits[:3], variables=variables, H=H, silent=True)
data2[(3,3)]=v[0]
print("\n\nFinished!\n\n")
print("G(N,M) errors:")
for k,v in data1.items():
error = abs(fci-v)
print("G({},{}): {:+2.5f}".format(k[0],k[1],error))
print("G(N,M)+UR errors:")
for k,v in data2.items():
error = abs(fci-v)
print("G({},{})+UR: {:+2.5f}".format(k[0],k[1],error))