-
Notifications
You must be signed in to change notification settings - Fork 19
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
Enable user-defined MRSQK reference space #210
base: master
Are you sure you want to change the base?
Changes from all commits
ccc66e4
bf017a0
9e73025
ca2017e
311dbee
32eac23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -72,7 +72,7 @@ class MRSQK(QSD): | |||||||||
_nstates_per_ref : int | ||||||||||
The number of states for a generated reference :math:`s+1`. | ||||||||||
|
||||||||||
_reference_generator : {"SRQK"} | ||||||||||
_reference_generator : {"SRQK", "USER"} | ||||||||||
Specifies an algorithm to choose the reference state. | ||||||||||
|
||||||||||
_s : int | ||||||||||
|
@@ -126,6 +126,8 @@ def run(self, | |||||||||
mr_dt=0.5, | ||||||||||
target_root=0, | ||||||||||
reference_generator='SRQK', | ||||||||||
refs_user_defined=None, | ||||||||||
save_qk_matrices=False, | ||||||||||
use_phase_based_selection=False, | ||||||||||
use_spin_adapted_refs=True, | ||||||||||
s_o=4, | ||||||||||
|
@@ -153,6 +155,9 @@ def run(self, | |||||||||
|
||||||||||
self._diagonalize_each_step=diagonalize_each_step | ||||||||||
|
||||||||||
self._sa_ref_lst = [] | ||||||||||
self._save_qk_matrices = save_qk_matrices | ||||||||||
|
||||||||||
if(self._state_prep_type != 'occupation_list'): | ||||||||||
raise ValueError("MRSQK implementation can only handle occupation_list reference.") | ||||||||||
|
||||||||||
|
@@ -178,9 +183,15 @@ def run(self, | |||||||||
self.build_refs_from_srqk() | ||||||||||
|
||||||||||
print('\n ==> SRQK reference selection complete.') | ||||||||||
|
||||||||||
elif reference_generator.lower()=='user': | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
if refs_user_defined == None: | ||||||||||
raise ValueError("User-defined spin-adapted references MISSING; set 'refs_user_defined' option.") | ||||||||||
else: | ||||||||||
self.get_refs_from_user(refs_user_defined) | ||||||||||
|
||||||||||
else: | ||||||||||
raise ValueError("Incorrect value passed for reference_generator, can be 'SRQK'.") | ||||||||||
raise ValueError("Incorrect value passed for reference_generator, can be 'SRQK', 'user'.") | ||||||||||
|
||||||||||
self.common_run() | ||||||||||
|
||||||||||
|
@@ -192,7 +203,8 @@ def set_circuit_variables(self): | |||||||||
if(self._reference_generator=='SRQK'): | ||||||||||
self._n_pauli_trm_measures = self._nstates * self._Nl + self._srqk._n_pauli_trm_measures | ||||||||||
else: | ||||||||||
raise ValueError('Can only count number of paulit term measurements when using SRQK.') | ||||||||||
self._n_pauli_trm_measures = self._nstates * self._Nl | ||||||||||
|
||||||||||
# off-diagonal of Hbar (<X> and <Y> of Hadamard test) | ||||||||||
self._n_pauli_trm_measures += self._nstates*(self._nstates-1) * self._Nl | ||||||||||
# off-diagonal of S (<X> and <Y> of Hadamard test) | ||||||||||
|
@@ -213,8 +225,10 @@ def print_options_banner(self): | |||||||||
print('\n\n ==> MRSQK options <==') | ||||||||||
print('-----------------------------------------------------------') | ||||||||||
# General algorithm options. | ||||||||||
print('Trial reference state: ', ref_string(self._ref, self._nqb)) | ||||||||||
print('Trial state preparation method: ', self._state_prep_type) | ||||||||||
print('Reference space generator ', self._reference_generator.upper()) | ||||||||||
if(self._reference_generator.upper()=='SRQK'): | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
print('Trial reference state: ', ref_string(self._ref, self._nqb)) | ||||||||||
print('Trial state preparation method: ', self._state_prep_type) | ||||||||||
print('Trotter order (rho): ', self._trotter_order) | ||||||||||
print('Trotter number (m): ', self._trotter_number) | ||||||||||
print('Use fast version of algorithm: ', str(self._fast)) | ||||||||||
|
@@ -231,10 +245,11 @@ def print_options_banner(self): | |||||||||
print('Target root: ', str(self._target_root)) | ||||||||||
print('Use det. selection with sign: ', str(self._use_phase_based_selection)) | ||||||||||
print('Use spin adapted references: ', str(self._use_spin_adapted_refs)) | ||||||||||
print('Save final MRSQK matrics: ', str(self._save_qk_matrices)) | ||||||||||
|
||||||||||
print('\n\n ==> Initial QK options (for ref. selection) <==') | ||||||||||
print('-----------------------------------------------------------') | ||||||||||
if(self._reference_generator=='SRQK'): | ||||||||||
print('\n\n ==> Initial QK options (for ref. selection) <==') | ||||||||||
print('-----------------------------------------------------------') | ||||||||||
print('Inital Trotter order (rho_o): ', self._trotter_order_o) | ||||||||||
print('Inital Trotter number (m_o): ', self._trotter_number_o) | ||||||||||
print('Number of initial time evolutions (s_o): ', self._s_o) | ||||||||||
|
@@ -325,7 +340,8 @@ def build_qk_mats_fast(self): | |||||||||
self._n_pauli_trm_measures += k * (k-1) * self._Nl | ||||||||||
self._n_pauli_trm_measures += k * (k-1) | ||||||||||
|
||||||||||
print(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}') | ||||||||||
if len(evals) > self._target_root: | ||||||||||
print(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}') | ||||||||||
|
||||||||||
return s_mat, h_mat | ||||||||||
|
||||||||||
|
@@ -424,15 +440,16 @@ def build_sa_qk_mats(self): | |||||||||
|
||||||||||
k = p+1 | ||||||||||
self._n_classical_params = k | ||||||||||
if(k==1): | ||||||||||
if(k==1) and (self._reference_generator != 'user'): | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
self._n_cnot = self._srqk._n_cnot | ||||||||||
else: | ||||||||||
self._n_cnot = 2 * Um.get_num_cnots() | ||||||||||
self._n_pauli_trm_measures = k * self._Nl + self._srqk._n_pauli_trm_measures | ||||||||||
self._n_pauli_trm_measures = k * self._Nl + self._srqk._n_pauli_trm_measures if self._reference_generator != 'user' else k * self._Nl | ||||||||||
self._n_pauli_trm_measures += k * (k-1) * self._Nl | ||||||||||
self._n_pauli_trm_measures += k * (k-1) | ||||||||||
|
||||||||||
print(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}') | ||||||||||
if len(evals) > self._target_root: | ||||||||||
print(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}') | ||||||||||
|
||||||||||
return s_mat, h_mat | ||||||||||
|
||||||||||
|
@@ -641,7 +658,6 @@ def build_sa_refs(self): | |||||||||
print('\n\n ==> Final MRSQK reference space summary <==') | ||||||||||
print('-----------------------------------------------------------') | ||||||||||
|
||||||||||
self._sa_ref_lst = [] | ||||||||||
for i in range(self._d): | ||||||||||
print('\nRef ', i+1) | ||||||||||
print('---------------------------') | ||||||||||
|
@@ -659,3 +675,38 @@ def build_sa_refs(self): | |||||||||
print(' ', round(temp[0], 4), ' ', basis.str(self._nqb)) | ||||||||||
|
||||||||||
self._sa_ref_lst.append(basis_vec) | ||||||||||
|
||||||||||
|
||||||||||
def set_sa_ref_lst(self, spin_adapted_ref_list): | ||||||||||
""" | ||||||||||
Parameters | ||||||||||
---------- | ||||||||||
spin_adapted_ref_list : list of lists of tuples | ||||||||||
list of spin adapted references defined by user. | ||||||||||
Each term in 'spin_adapted_ref_list' represents a configuration state function (CSF); | ||||||||||
Each CSF comprises a list of tuples, | ||||||||||
while each tuple contains the coefficient and determinant (in the occupation list format). | ||||||||||
As an example: | ||||||||||
The following list contains two CSF, built from one and two determinants, respectively. | ||||||||||
spin_adapted_ref_list = [ [(1.0, [1,1,0,0]), ], | ||||||||||
[(0.7071, [0,1,1,0]), (0.7071, [1,0,0,1])], | ||||||||||
] | ||||||||||
""" | ||||||||||
self._sa_ref_lst = spin_adapted_ref_list | ||||||||||
|
||||||||||
def get_refs_from_user(self, refs_user_defined): | ||||||||||
"""Get a list of spin adapted references from user input to be used in the MRSQK procedure. | ||||||||||
""" | ||||||||||
self.set_sa_ref_lst(refs_user_defined) | ||||||||||
|
||||||||||
print('\n\n ==> MRSQK reference space (User-defined) <==') | ||||||||||
print('-----------------------------------------------------------') | ||||||||||
|
||||||||||
for i, csf in enumerate(refs_user_defined): | ||||||||||
print('\nRef ', i+1) | ||||||||||
Comment on lines
+705
to
+706
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
print('---------------------------') | ||||||||||
for c, det in csf: | ||||||||||
qf_det_idx = ref_to_basis_idx(det) | ||||||||||
basis = qforte.QubitBasis(qf_det_idx) | ||||||||||
print(f'{c:9.4f} {basis.str(self._nqb)}') | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,8 @@ def run(self, | |
s=3, | ||
dt=0.5, | ||
target_root=0, | ||
diagonalize_each_step=True | ||
diagonalize_each_step=True, | ||
save_qk_matrices=False, | ||
): | ||
|
||
if not self._fast: | ||
|
@@ -60,6 +61,8 @@ def run(self, | |
self._n_cnot = 0 | ||
self._n_pauli_trm_measures = 0 | ||
|
||
self._save_qk_matrices = save_qk_matrices | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that |
||
|
||
# Print options banner (should done for all algorithms). | ||
self.print_options_banner() | ||
|
||
|
@@ -181,10 +184,12 @@ def build_qk_mats(self): | |
self._n_pauli_trm_measures = k * self._Nl | ||
self._n_pauli_trm_measures += k * (k-1) * self._Nl | ||
self._n_pauli_trm_measures += k * (k-1) | ||
|
||
print(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {0:10} {self._n_pauli_trm_measures:12}') | ||
if (self._print_summary_file): | ||
f.write(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {0:10} {self._n_pauli_trm_measures:12}\n') | ||
|
||
if len(evals) > self._target_root: | ||
string = f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {0:10} {self._n_pauli_trm_measures:12}' | ||
print(string) | ||
if (self._print_summary_file): | ||
f.write(f'{string}\n') | ||
|
||
if (self._diagonalize_each_step and self._print_summary_file): | ||
f.close() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,7 +45,8 @@ def run(self, | |
s=3, | ||
dt=0.5, | ||
target_root=0, | ||
diagonalize_each_step=True | ||
diagonalize_each_step=True, | ||
save_qk_matrices=False, | ||
): | ||
|
||
self._s = s | ||
|
@@ -58,6 +59,8 @@ def run(self, | |
self._n_cnot = 0 | ||
self._n_pauli_trm_measures = 0 | ||
|
||
self._save_qk_matrices = save_qk_matrices | ||
|
||
# Print options banner (should done for all algorithms). | ||
self.print_options_banner() | ||
|
||
|
@@ -193,10 +196,12 @@ def build_qk_mats_fast(self): | |
self._n_pauli_trm_measures = k * self._Nl | ||
self._n_pauli_trm_measures += k * (k-1) * self._Nl | ||
self._n_pauli_trm_measures += k * (k-1) | ||
|
||
print(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}') | ||
if (self._print_summary_file): | ||
f.write(f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}\n') | ||
|
||
if len(evals) > self._target_root: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this line added? |
||
string = f' {scond:7.2e} {np.real(evals[self._target_root]):+15.9f} {self._n_classical_params:8} {self._n_cnot:10} {self._n_pauli_trm_measures:12}' | ||
print(string) | ||
if (self._print_summary_file): | ||
f.write(f'{string}\n') | ||
|
||
if (self._diagonalize_each_step and self._print_summary_file): | ||
f.close() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from pytest import approx | ||
from qforte import system_factory, MRSQK | ||
|
||
class TestRefSpaceMRSQK: | ||
def test_H4_Root1_user_defined_ref_space(self): | ||
print('\n') | ||
# FCI Root 1 singlet energy for H4 at 1.5 angstrom in sto-6g basis | ||
e_fci_root1 = -1.839569968502 | ||
|
||
Rhh = 1.5 | ||
mol = system_factory(system_type = 'molecule', | ||
build_type = 'psi4', | ||
basis = 'sto-6g', | ||
mol_geometry = [('H', (0, 0, -3*Rhh/2)), | ||
('H', (0, 0, -Rhh/2)), | ||
('H', (0, 0, Rhh/2)), | ||
('H', (0, 0, 3*Rhh/2))], | ||
symmetry = 'd2h', | ||
multiplicity = 1, # Only singlets will work with QForte | ||
charge = 0, | ||
num_frozen_docc = 0, | ||
num_frozen_uocc = 0, | ||
run_mp2=0, | ||
run_ccsd=0, | ||
run_cisd=0, | ||
run_fci=0) | ||
|
||
refs_user_defined = [ | ||
[(1.0, [1,1,0,0,1,1,0,0]), ], # 22 00 | ||
[(1.0, [0,0,1,1,1,1,0,0]), ], # 02 20 | ||
[(1.0, [1,1,0,0,0,0,1,1]), ], # 20 02 | ||
] | ||
target_root = 1 | ||
|
||
alg = MRSQK(mol, trotter_number=100, trotter_order=1, ) | ||
alg.run(d = 3, # num of references | ||
s = 3, # num of time steps per ref | ||
mr_dt = 0.5, | ||
target_root = target_root, | ||
reference_generator = 'user', | ||
refs_user_defined = refs_user_defined, | ||
) | ||
|
||
E1 = alg.get_ts_energy() | ||
|
||
assert E1 == approx(e_fci_root1, abs=1e-5) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please include this keyword in the docstring.