Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MORE-ADAPT VQE (Consistent with new refprep conventions.) #265

Open
wants to merge 103 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
6bbaeae
Fixed seg fault line
Feb 16, 2023
8e2e86b
Merge branch 'evangelistalab:master' into seg_fault
hrgrimsl Jun 20, 2023
d051327
working on saving integrals
Jun 23, 2023
24e8f94
json stuff
Jun 23, 2023
cec4703
saving
Jun 26, 2023
4bd375a
Merge pull request #1 from evangelistalab/master
hrgrimsl Jun 26, 2023
20b1e2e
sparse matrices, hamiltonian saving
Jun 27, 2023
c840979
beginning multi state stuff
Jun 27, 2023
b969cc5
Saving more progress
Jun 28, 2023
f5360f1
Gate counting fixed (I think...)
Jun 28, 2023
53bd583
Gate counting fixed (I think...) p2
Jun 28, 2023
c3f5735
saving
Jun 28, 2023
5b2ef5a
state-averaging works
Jun 29, 2023
3497c68
SA test added
Jun 30, 2023
ce87719
q_sc_eom
Jul 3, 2023
735efd7
still tweaking
Jul 3, 2023
096c1ea
Much, much faster SA-ADAPT
Jul 5, 2023
e4de92a
Excited states, IPEA
Jul 7, 2023
3151ace
here
Jul 13, 2023
cec8656
corrections
Jul 13, 2023
05eccc2
Dipoles
Jul 13, 2023
e94d0e9
Dipole loading
Jul 13, 2023
3189f9d
dipole spins fixed
Jul 13, 2023
898ca6e
Dipoles
Jul 14, 2023
b77bde6
misc
Jul 17, 2023
ef6bb31
saving
Jul 19, 2023
63581c8
fixed ritz_eigh
Jul 20, 2023
f59498a
Merge branch 'excited_states' of https://github.com/hrgrimsl/qforte i…
Jul 20, 2023
1671c8e
improved testing of excited state methods
Jul 20, 2023
b51f7fc
Cleaned up tests
Jul 21, 2023
654aed3
Partially completed Ilias changes
Jul 25, 2023
4b71305
saving, still fixing
Jul 26, 2023
aa39f1e
debugging
Jul 28, 2023
b5bd453
even more changes
Aug 1, 2023
e1d2736
even more saving
Aug 2, 2023
965379b
debugging
Aug 3, 2023
5c852ef
Finally fixed?
Aug 3, 2023
a65b756
Fixed indexing issue in test_sa_adapt_vqe
Aug 4, 2023
0ae90ba
removed print statement
Aug 7, 2023
49a8444
added kwarg to freeze specific irreps in psi
Aug 7, 2023
9e3894f
fixed psi4 frozen_uocc
Aug 7, 2023
0983ebf
removed unnecessary dependency in a test
Aug 7, 2023
8aa664d
broke adapter, fixed adapter
Aug 7, 2023
cbc11e4
Fixed spin-orbital convention on symmetry saving
Aug 7, 2023
73fdd85
updating
Aug 14, 2023
f48f7b3
fixed a test
Aug 24, 2023
f084239
fixed test
Aug 24, 2023
815b968
Merge branch 'master' of https://github.com/evangelistalab/qforte int…
Sep 11, 2023
cd791e9
scf_docc kwarg
Sep 12, 2023
af0453d
Added saving/loading of hf_reference for non-Aufbau situations
Sep 15, 2023
16782c7
no_reorient
Sep 21, 2023
70f44e9
Merge remote-tracking branch 'upstream/master' into excited_states
Sep 22, 2023
9f3525b
loosening tests
Sep 22, 2023
01ac3b1
looser testing
Sep 25, 2023
5b62a61
Made ADAPT able to be setup with no iterations
Sep 26, 2023
043dea1
fixed last commit
Sep 26, 2023
14a155a
fixed?
Sep 28, 2023
5c4114b
Fixed
Sep 28, 2023
0f312f3
SA CIS
Oct 31, 2023
b577496
Fixed test
Oct 31, 2023
bfb3665
exit sa_cis
Nov 8, 2023
92e14c9
spin check fixed
Nov 8, 2023
4fbb77d
casscf
Dec 6, 2023
40e1c83
CASSCF working
Dec 11, 2023
2c02c19
Fixed everything I broke along the way
Dec 11, 2023
7e20556
fixed psi4 import?
Dec 12, 2023
4db20e5
conda
Dec 12, 2023
9b1cc3f
Tests would be nice but apparently works
Dec 13, 2023
6cf0b50
load tamps
Dec 28, 2023
358533f
tamps
Dec 28, 2023
e623115
tests passing
Dec 29, 2023
a017027
Merge branch 'excited_state_temp' of https://github.com/hrgrimsl/qfor…
Dec 29, 2023
53ce822
scf_docc
Jan 24, 2024
93c2c01
fixed tests
Jan 24, 2024
d837dbb
tracking diagonalized energies
Jan 26, 2024
3e540cb
stuff
Jan 27, 2024
8050c53
printing
Jan 29, 2024
a82df8e
stuff
Feb 1, 2024
c6015ca
flush
Feb 27, 2024
684f818
manifold stuff
Mar 21, 2024
78f703a
fixed yaml?
Apr 23, 2024
20d2d9f
yaml
Apr 23, 2024
29e0b54
the work must flow
Apr 23, 2024
6f3ac4b
pulled
Apr 23, 2024
7dc226c
Removed cH
Apr 30, 2024
f9a514a
Accounting for Jonathans changes
Jul 10, 2024
b985a7b
black
Jul 10, 2024
3c379b1
downgraded black
Jul 10, 2024
b740444
removed Uprep
Jul 10, 2024
00cef14
tests passing
Jul 12, 2024
1db95a9
black
Jul 12, 2024
6ec89cc
black old version
Jul 12, 2024
bef8b13
removed print
Jul 12, 2024
02d038d
tweaks
Jul 12, 2024
85c246a
black
Jul 12, 2024
ee52ef9
needs more robust testing for sa_adapt but I think it is working again
Jul 12, 2024
a60bf52
black
Jul 15, 2024
3cbbcd3
fixed indent that I think black messed up somehow
Jul 15, 2024
f88a38f
adding more comprehensive more_adapt testing
Jul 15, 2024
99c2194
smaller beh2 test, fixed diag energy printing
Jul 16, 2024
cc35134
black
Jul 16, 2024
a0a3fe8
cleaning psi4 quick fix
Jul 17, 2024
8e73fd5
cleaning psi4 quick fix
Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/qforte/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from qforte.adapters import *
from qforte.helper import *
from qforte.maths import *
from qforte.expansions import *
from qforte.experiment import *
from qforte.ite import *
from qforte.qkd import *
Expand Down
306 changes: 240 additions & 66 deletions src/qforte/abc/algorithm.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/qforte/abc/qsdabc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
The abstract base classes inheritied by any quantum subspace diagonalizaiton (QSD)
variant.
"""

from abc import abstractmethod
from qforte.abc.algorithm import Algorithm
from qforte.maths.eigsolve import canonical_geig_solve
Expand Down
302 changes: 205 additions & 97 deletions src/qforte/abc/uccvqeabc.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,111 +142,180 @@ def measure_gradient(self, params=None):
else:
Utot = self.build_Uvqc(params)

qc_psi = self.get_initial_computer()
qc_psi.apply_circuit(Utot)
qc_sig = qf.Computer(qc_psi)
qc_sig.apply_operator(self._qb_ham)
qc_temp = qf.Computer(qc_psi)

mu = M - 1

# find <sing_N | K_N | psi_N>
Kmu_prev = self._pool_obj[self._tops[mu]][1].jw_transform(
self._qubit_excitations
)
Kmu_prev.mult_coeffs(self._pool_obj[self._tops[mu]][0])

qc_temp.apply_operator(Kmu_prev)
grads[mu] = 2.0 * np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec())
)

for mu in reversed(range(M - 1)):
if not self._is_multi_state:
qc_psi = self.get_initial_computer()
qc_psi.apply_circuit(Utot)
qc_sig = qf.Computer(qc_psi)
qc_sig.apply_operator(self._qb_ham)
qc_temp = qf.Computer(qc_psi)
# mu => N-1 => M-2
# mu+1 => N => M-1
# Kmu => KN-1
# Kmu_prev => KN

if params is None:
tamp = self._tamps[mu + 1]
else:
tamp = params[mu + 1]

Kmu = self._pool_obj[self._tops[mu]][1].jw_transform(
mu = M - 1
# find <sig_N | K_N | psi_N>
Kmu_prev = self._pool_obj[self._tops[mu]][1].jw_transform(
self._qubit_excitations
)
Kmu.mult_coeffs(self._pool_obj[self._tops[mu]][0])

if self._compact_excitations:
if self._pool_type == "sa_SD":
sa_sq_op = self._pool_obj[self._tops[mu + 1]][1].terms()
half_length = len(sa_sq_op) // 2
Umu = qf.Circuit()
for coeff, cr, ann in sa_sq_op[:half_length]:
Kmu_prev.mult_coeffs(self._pool_obj[self._tops[mu]][0])

qc_temp.apply_operator(Kmu_prev)
grads[mu] = 2.0 * np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec())
)

for mu in reversed(range(M - 1)):
qc_temp = qf.Computer(qc_psi)
# mu => N-1 => M-2
# mu+1 => N => M-1
# Kmu => KN-1
# Kmu_prev => KN

if params is None:
tamp = self._tamps[mu + 1]
else:
tamp = params[mu + 1]

Kmu = self._pool_obj[self._tops[mu]][1].jw_transform(
self._qubit_excitations
)
Kmu.mult_coeffs(self._pool_obj[self._tops[mu]][0])

if self._compact_excitations:
if self._pool_type == "sa_SD":
sa_sq_op = self._pool_obj[self._tops[mu + 1]][1].terms()
half_length = len(sa_sq_op) // 2
Umu = qf.Circuit()
for coeff, cr, ann in sa_sq_op[:half_length]:
# The minus sign is dictated by the recursive algorithm used to compute the analytic gradient
# (see original ADAPT-VQE paper)
# In this particular case, the minus sign is already incorporated
Umu.add(
compact_excitation_circuit(
tamp * coeff, ann, cr, self._qubit_excitations
)
)
else:
Umu = qf.Circuit()
# The minus sign is dictated by the recursive algorithm used to compute the analytic gradient
# (see original ADAPT-VQE paper)
# In this particular case, the minus sign is already incorporated
Umu.add(
compact_excitation_circuit(
tamp * coeff, ann, cr, self._qubit_excitations
-tamp
* self._pool_obj[self._tops[mu + 1]][1].terms()[1][0],
self._pool_obj[self._tops[mu + 1]][1].terms()[1][1],
self._pool_obj[self._tops[mu + 1]][1].terms()[1][2],
self._qubit_excitations,
)
)
else:
if self._pool_type == "sa_SD":
sa_sq_op = self._pool_obj[self._tops[mu + 1]][1].terms()
half_length = len(sa_sq_op) // 2
Umu = qf.Circuit()
for coeff, cr, ann in sa_sq_op[:half_length]:
sq_op = qf.SQOperator()
sq_op.add_term(coeff, cr, ann)
sq_op.add_term(-coeff, ann, cr)
q_op = sq_op.jw_transform(self._qubit_excitations)
U, p = trotterize(
q_op, factor=-tamp, trotter_number=self._trotter_number
)
if p != 1.0 + 0.0j:
raise ValueError(
"Encountered phase change, phase not equal to (1.0 + 0.0i)"
)
Umu.add(U)
else:
# The minus sign is dictated by the recursive algorithm used to compute the analytic gradient
# (see original ADAPT-VQE paper)
Umu, pmu = trotterize(
Kmu_prev, factor=-tamp, trotter_number=self._trotter_number
)

if pmu != 1.0 + 0.0j:
raise ValueError(
"Encountered phase change, phase not equal to (1.0 + 0.0i)"
)

qc_sig.apply_circuit(Umu)
qc_psi.apply_circuit(Umu)
qc_temp = qf.Computer(qc_psi)

qc_temp.apply_operator(Kmu)
grads[mu] = 2.0 * np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec())
)

# reset Kmu |psi_i> -> |psi_i>
Kmu_prev = Kmu

else:
# TODO add sa-SD
try:
assert self._pool_type != "sa_SD"
except:
raise ValueError("sa SD not implemented for multireference ADAPT")
# Build all Kmus and Umus in advance.
Kmus = []
Umus = []
for mu in range(len(self._tops)):
Kmu = self._pool_obj[self._tops[mu]][1].jw_transform(
self._qubit_excitations
)
Kmus.append(Kmu)
if params is None:
tamp = self._tamps[mu]
else:
tamp = params[mu]
if self._compact_excitations:
Umu = qf.Circuit()
# The minus sign is dictated by the recursive algorithm used to compute the analytic gradient
# (see original ADAPT-VQE paper)
Umu.add(
compact_excitation_circuit(
-tamp * self._pool_obj[self._tops[mu + 1]][1].terms()[1][0],
self._pool_obj[self._tops[mu + 1]][1].terms()[1][1],
self._pool_obj[self._tops[mu + 1]][1].terms()[1][2],
-tamp * self._pool_obj[self._tops[mu]][1].terms()[1][0],
self._pool_obj[self._tops[mu]][1].terms()[1][1],
self._pool_obj[self._tops[mu]][1].terms()[1][2],
self._qubit_excitations,
)
)
else:
if self._pool_type == "sa_SD":
sa_sq_op = self._pool_obj[self._tops[mu + 1]][1].terms()
half_length = len(sa_sq_op) // 2
Umu = qf.Circuit()
for coeff, cr, ann in sa_sq_op[:half_length]:
sq_op = qf.SQOperator()
sq_op.add_term(coeff, cr, ann)
sq_op.add_term(-coeff, ann, cr)
q_op = sq_op.jw_transform(self._qubit_excitations)
U, p = trotterize(
q_op, factor=-tamp, trotter_number=self._trotter_number
)
if p != 1.0 + 0.0j:
raise ValueError(
"Encountered phase change, phase not equal to (1.0 + 0.0i)"
)
Umu.add(U)
else:
# The minus sign is dictated by the recursive algorithm used to compute the analytic gradient
# (see original ADAPT-VQE paper)
Umu, pmu = trotterize(
Kmu_prev, factor=-tamp, trotter_number=self._trotter_number
Kmu, factor=-tamp, trotter_number=self._trotter_number
)

if pmu != 1.0 + 0.0j:
raise ValueError(
"Encountered phase change, phase not equal to (1.0 + 0.0i)"
)
Umus.append(Umu)

grads = np.zeros(len(self._tops))
# print('----')
for r in range(len(self._weights)):
qc_psi = self.get_initial_computer()[r]
qc_psi.apply_circuit(Utot[r])
qc_sig = qf.Computer(qc_psi)
qc_sig.apply_operator(self._qb_ham)
qc_temp = qf.Computer(qc_psi)
qc_temp.apply_operator(Kmus[M - 1])
grads[M - 1] += (
2
* self._weights[r]
* np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec()).real
)

for mu in reversed(range(M - 1)):
qc_psi.apply_circuit(Umus[mu])
qc_sig.apply_circuit(Umus[mu])
qc_temp = qf.Computer(qc_psi)
qc_temp.apply_operator(Kmus[mu])
grads[mu] += (
2
* self._weights[r]
* np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec()).real
)

qc_sig.apply_circuit(Umu)
qc_psi.apply_circuit(Umu)
qc_temp = qf.Computer(qc_psi)

qc_temp.apply_operator(Kmu)
grads[mu] = 2.0 * np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec())
)

# reset Kmu |psi_i> -> |psi_i>
Kmu_prev = Kmu

np.testing.assert_allclose(np.imag(grads), np.zeros_like(grads), atol=1e-7)
np.testing.assert_allclose(np.imag(grads), np.zeros_like(grads), atol=1e-12)
# print(f"Gradient: {grads}")
# print(f"Energy: {self.measure_energy(Utot)}")

return grads

Expand All @@ -255,28 +324,63 @@ def measure_gradient3(self):
For antihermitian K_mu, this is equal to <Psi|[H, K_mu]|Psi>.
In ADAPT-VQE, this is the 'residual gradient' used to determine
whether to append exp(t_mu K_mu) to the iterative ansatz.

In the case where _is_multi_state, this will give the weighted average of
these gradients for each reference.
"""

if not self._fast:
raise ValueError("self._fast must be True for gradient measurement.")

Utot = self.build_Uvqc()
qc_psi = self.get_initial_computer()
qc_psi.apply_circuit(Utot)

qc_sig = qforte.Computer(qc_psi)
qc_sig.apply_operator(self._qb_ham)

grads = np.zeros(len(self._pool_obj))

for mu, (coeff, operator) in enumerate(self._pool_obj):
qc_temp = qf.Computer(qc_psi)
Kmu = operator.jw_transform(self._qubit_excitations)
Kmu.mult_coeffs(coeff)
qc_temp.apply_operator(Kmu)
grads[mu] = 2.0 * np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec())
)
if not self._is_multi_state:
Utot = self.build_Uvqc()
qc_psi = self.get_initial_computer()
qc_psi.apply_circuit(Utot)

qc_sig = qforte.Computer(qc_psi)
qc_sig.apply_operator(self._qb_ham)

grads = np.zeros(len(self._pool_obj))

for mu, (coeff, operator) in enumerate(self._pool_obj):
qc_temp = qf.Computer(qc_psi)
Kmu = operator.jw_transform(self._qubit_excitations)
Kmu.mult_coeffs(coeff)
qc_temp.apply_operator(Kmu)
grads[mu] = 2.0 * np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_temp.get_coeff_vec())
)
else:
Kmus = []
for mu, (coeff, operator) in enumerate(self._pool_obj):
Kmu = operator.jw_transform(self._qubit_excitations)
Kmu.mult_coeffs(coeff)
Kmus.append(Kmu)

U_ansatz = self.ansatz_circuit()
grads = np.zeros(len(self._pool_obj))

for r in range(len(self._ref)):
qc_psi = self.get_initial_computer()[r]
qc_psi.apply_circuit(self._Uprep[r])
qc_psi.apply_circuit(U_ansatz)
psi_i = qc_psi.get_coeff_vec()

qc_sig = qforte.Computer(self._nqb)
qc_sig.set_coeff_vec(psi_i)
qc_sig.apply_operator(self._qb_ham)

for mu, (coeff, operator) in enumerate(self._pool_obj):
Kmu = Kmus[mu]
qc_psi.apply_operator(Kmu)
grads[mu] += (
self._weights[r]
* 2.0
* np.real(
np.vdot(qc_sig.get_coeff_vec(), qc_psi.get_coeff_vec())
)
)
qc_psi.set_coeff_vec(psi_i)

np.testing.assert_allclose(np.imag(grads), np.zeros_like(grads), atol=1e-7)

Expand All @@ -291,9 +395,13 @@ def gradient_ary_feval(self, params):
for grad_m in grads
]

if not self._is_multi_state:
factor = 1
else:
factor = len(self._ref)
self._curr_grad_norm = np.linalg.norm(grads)
self._res_vec_evals += 1
self._res_m_evals += len(self._tamps)
self._res_vec_evals += factor
self._res_m_evals += factor * len(self._tamps)

return np.asarray(grads)

Expand Down
1 change: 1 addition & 0 deletions src/qforte/abc/vqeabc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
The abstract base classes inheritied by any projective variational quantum
eigensolver (VQE) variant.
"""

from abc import abstractmethod
from qforte.abc.algorithm import AnsatzAlgorithm

Expand Down
Loading
Loading