def ucc(geometry, basis="sto-3g", multiplicity=1, charge=1, theta_thresh=1e-7, pool=operator_pools.singlet_GSD(), spin_adapt=True, psi4_filename="psi4_%12.12f" % random.random()): # {{{ molecule = openfermion.hamiltonians.MolecularData(geometry, basis, multiplicity) molecule.filename = psi4_filename molecule = openfermionpsi4.run_psi4(molecule, run_scf=1, run_mp2=1, run_cisd=0, run_ccsd=0, run_fci=1, delete_input=1) pool.init(molecule) print(" Basis: ", basis) print(' HF energy %20.16f au' % (molecule.hf_energy)) print(' MP2 energy %20.16f au' % (molecule.mp2_energy)) #print(' CISD energy %20.16f au' %(molecule.cisd_energy)) #print(' CCSD energy %20.16f au' %(molecule.ccsd_energy)) print(' FCI energy %20.16f au' % (molecule.fci_energy)) #Build p-h reference and map it to JW transform reference_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state( list(range(0, molecule.n_electrons)), molecule.n_qubits)).transpose() reference_bra = reference_ket.transpose().conj() #JW transform Hamiltonian computed classically with OFPsi4 hamiltonian_op = molecule.get_molecular_hamiltonian() hamiltonian = openfermion.transforms.get_sparse_operator(hamiltonian_op) #Thetas parameters = [0] * pool.n_ops pool.generate_SparseMatrix() ucc = UCC(hamiltonian, pool.spmat_ops, reference_ket, parameters) opt_result = scipy.optimize.minimize(ucc.energy, parameters, options={ 'gtol': 1e-6, 'disp': True }, method='BFGS', callback=ucc.callback) print(" Finished: %20.12f" % ucc.curr_energy) parameters = opt_result['x'] for p in parameters: print(p)
def test(): r = 1.5 geometry = [('H', (0,0,1*r)), ('H', (0,0,2*r)), ('H', (0,0,3*r)), ('H', (0,0,4*r))] charge = 0 spin = 0 basis = 'sto-3g' [n_orb, n_a, n_b, h, g, mol, E_nuc, E_scf, C, S] = pyscf_helper.init(geometry,charge,spin,basis) print(" n_orb: %4i" %n_orb) print(" n_a : %4i" %n_a) print(" n_b : %4i" %n_b) sq_ham = pyscf_helper.SQ_Hamiltonian() sq_ham.init(h, g, C, S) print(" HF Energy: %12.8f" %(E_nuc + sq_ham.energy_of_determinant(range(n_a),range(n_b)))) ehf = E_nuc + sq_ham.energy_of_determinant(range(n_a),range(n_b)) assert(abs(ehf - -1.82913741) < 1e-7) fermi_ham = sq_ham.export_FermionOperator() hamiltonian = openfermion.transforms.get_sparse_operator(fermi_ham) s2 = vqe_methods.Make_S2(n_orb) #build reference configuration occupied_list = [] for i in range(n_a): occupied_list.append(i*2) for i in range(n_b): occupied_list.append(i*2+1) print(" Build reference state with %4i alpha and %4i beta electrons" %(n_a,n_b), occupied_list) reference_ket = scipy.sparse.csc_matrix(openfermion.jw_configuration_state(occupied_list, 2*n_orb)).transpose() [e,v] = scipy.sparse.linalg.eigsh(hamiltonian.real,1,which='SA',v0=reference_ket.todense()) for ei in range(len(e)): S2 = v[:,ei].conj().T.dot(s2.dot(v[:,ei])) print(" State %4i: %12.8f au <S2>: %12.8f" %(ei,e[ei]+E_nuc,S2)) fermi_ham += FermionOperator((),E_nuc) pyscf.molden.from_mo(mol, "full.molden", sq_ham.C) # Francesco, change this to singlet_GSD() if you want generalized singles and doubles pool = operator_pools.singlet_SD() pool.init(n_orb, n_occ_a=n_a, n_occ_b=n_b, n_vir_a=n_orb-n_a, n_vir_b=n_orb-n_b) [e,v,params] = vqe_methods.adapt_vqe(fermi_ham, pool, reference_ket, theta_thresh=1e-9) print(" Final ADAPT-VQE energy: %12.8f" %e) print(" <S^2> of final state : %12.8f" %(v.conj().T.dot(s2.dot(v))[0,0].real)) assert(abs(-1.99471290 - e) < 1e-7)
def old_setup( geometry, basis="sto-3g", multiplicity=1, #same as george, non-degenerate orbitals charge=1, #doesn't seem to matter in hamiltonian (weird) adapt_conver='norm', #doesn't matter for setup, but looks like daniel used a different method to determine convergence, but only in energy-case adapt_thresh=1e-3, #gradient threshold theta_thresh=1e-7, adapt_maxiter=200, #maximum number of iterations pool=operator_pools.singlet_GS( ), #generalized singles and doubles as default, though he's not sure if he changed it- nick seems to think that he used GS reference='rhf', #is default in MolecularData anyway brueckner=0, #mattered for psi4 but is 0 as default anyway ref_state=None, spin_adapt=True, fci_nat_orb=0, cisd_nat_orb=0, hf_stability='none', single_vqe=False, #will be true in our case chk_ops=[], energy_thresh=1e-6, #threshold for single_vqe fci_overlap=False, psi4_filename="psi4_%12.12f" % random.random()): # designed to set up the problem in the same way as Daniel, did have to substitute openfermionpyscf for psi4 but shouldn't make a difference #still need to investiage versioning for the pool init and singlet GSD methods as these require the current version of MolecularData objects to have: # n_orbitals (y) # get_n_alpha_electrons (y) # get_n_beta_electrons (y) # FermionOperator class (y) # requried attributes? (~) # # # hermitian_conjugate function (~) # normal_ordered function (~) # {{{ start_time = time.time() molecule = openfermion.hamiltonians.MolecularData(geometry, basis, multiplicity) if cisd_nat_orb == 1: cisd = 1 else: cisd = 0 molecule = openfermionpyscf.run_pyscf(molecule, run_fci=True) pool.init(molecule) if fci_overlap == False: print(" Basis: ", basis) print(' HF energy %20.16f au' % (molecule.hf_energy)) #print(' MP2 energy %20.16f au' %(molecule.mp2_energy)) #print(' CISD energy %20.16f au' %(molecule.cisd_energy)) #print(' CCSD energy %20.16f au' %(molecule.ccsd_energy)) if brueckner == 1: print(' BCCD energy %20.16f au' % (molecule.bccd_energy)) if cisd == 1: print(' CISD energy %20.16f au' % (molecule.cisd_energy)) if reference == 'rhf': print(' FCI energy %20.16f au' % (molecule.fci_energy)) # if we are going to transform to FCI NOs, it doesn't make sense to transform to CISD NOs if cisd_nat_orb == 1 and fci_nat_orb == 0: print(' Basis transformed to the CISD natural orbitals') if fci_nat_orb == 1: print(' Basis transformed to the FCI natural orbitals') #Build p-h reference and map it to JW transform if ref_state == None: ref_state = list(range(0, molecule.n_electrons)) reference_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state(ref_state, molecule.n_qubits)).transpose() reference_bra = reference_ket.transpose().conj() #JW transform Hamiltonian computed classically with OFPsi4 hamiltonian_op = molecule.get_molecular_hamiltonian() hamiltonian = openfermion.transforms.get_sparse_operator(hamiltonian_op) if fci_overlap: e, fci_vec = openfermion.get_ground_state(hamiltonian) fci_state = scipy.sparse.csc_matrix(fci_vec).transpose() index = scipy.sparse.find(reference_ket)[0] print(" Basis: ", basis) print(' HF energy %20.16f au' % (molecule.hf_energy)) if brueckner == 1: print(' BCCD energy %20.16f au' % (molecule.bccd_energy)) print(' FCI energy %20.16f au' % e) print(' <FCI|HF> %20.16f' % np.absolute(fci_vec[index])) print(' Orbitals') print(molecule.canonical_orbitals) #Thetas parameters = [] #pool.generate_SparseMatrix() pool.gradient_print_thresh = theta_thresh ansatz_ops = [] #SQ operator strings in the ansatz ansatz_mat = [] #Sparse Matrices for operators in ansatz op_indices = [] parameters = [] #curr_state = 1.0*reference_ket curr_energy = molecule.hf_energy molecule = openfermion.transforms.jordan_wigner(hamiltonian_op) pool_list = [] for op in pool.fermi_ops: pool_list.append(1j * openfermion.transforms.jordan_wigner(op)) pool_list = PauliPool().from_openfermion_qubit_operator_list(pool_list) qiskit_molecule = openfermion_to_qiskit(molecule) return pool_list, qiskit_molecule
n_spinorbitals = int(molecule.n_orbitals*2) print('HF energy %20.16f au' %(molecule.hf_energy)) print('MP2 energy %20.16f au' %(molecule.mp2_energy)) print('CISD energy %20.16f au' %(molecule.cisd_energy)) print('CCSD energy %20.16f au' %(molecule.ccsd_energy)) print('FCI energy %20.16f au' %(molecule.fci_energy)) global global_der global global_energy global global_iter global_der = np.array([]) global_energy = 0.0 global_iter = 0 #Build p-h reference and map it to JW transform reference_ket = scipy.sparse.csc_matrix(openfermion.jw_configuration_state(list(range(0,molecule.n_electrons)), molecule.n_qubits)).transpose() reference_bra = reference_ket.transpose().conj() #JW transform Hamiltonian computed classically with OFPsi4 tensor_hamiltonian = molecule.get_molecular_hamiltonian() singles_hamiltonian = tensor_hamiltonian.one_body_tensor doubles_hamiltonian = tensor_hamiltonian.two_body_tensor hamiltonian = openfermion.transforms.get_sparse_operator(tensor_hamiltonian) #Thetas parameters = [] #Second_quantized operations (not Jordan-Wignered) SQ_CC_ops = [] def ops_pqrs():
def test_lexical(geometry, basis="sto-3g", multiplicity=1, charge=1, adapt_conver='norm', adapt_thresh=1e-3, theta_thresh=1e-7, adapt_maxiter=200, pool=operator_pools.singlet_GSD(), spin_adapt=True, psi4_filename="psi4_%12.12f" % random.random()): # {{{ molecule = openfermion.hamiltonians.MolecularData(geometry, basis, multiplicity) molecule.filename = psi4_filename molecule = openfermionpsi4.run_psi4(molecule, run_scf=1, run_mp2=1, run_cisd=0, run_ccsd=0, run_fci=1, delete_input=1) pool.init(molecule) print(" Basis: ", basis) print(' HF energy %20.16f au' % (molecule.hf_energy)) print(' MP2 energy %20.16f au' % (molecule.mp2_energy)) #print(' CISD energy %20.16f au' %(molecule.cisd_energy)) #print(' CCSD energy %20.16f au' %(molecule.ccsd_energy)) print(' FCI energy %20.16f au' % (molecule.fci_energy)) #Build p-h reference and map it to JW transform reference_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state( list(range(0, molecule.n_electrons)), molecule.n_qubits)).transpose() reference_bra = reference_ket.transpose().conj() #JW transform Hamiltonian computed classically with OFPsi4 hamiltonian_op = molecule.get_molecular_hamiltonian() hamiltonian = openfermion.transforms.get_sparse_operator(hamiltonian_op) #Thetas parameters = [] pool.generate_SparseMatrix() ansatz_ops = [] #SQ operator strings in the ansatz ansatz_mat = [] #Sparse Matrices for operators in ansatz print(" Start ADAPT-VQE algorithm") op_indices = [] parameters = [] curr_state = 1.0 * reference_ket print(" Now start to grow the ansatz") for n_iter in range(0, adapt_maxiter): print("\n\n\n") print( " --------------------------------------------------------------------------" ) print(" ADAPT-VQE iteration: ", n_iter) print( " --------------------------------------------------------------------------" ) next_index = None next_deriv = 0 curr_norm = 0 print(" Check each new operator for coupling") next_term = [] print(" Measure commutators:") sig = hamiltonian.dot(curr_state) for op_trial in range(pool.n_ops): opA = pool.spmat_ops[op_trial] com = 2 * (curr_state.transpose().conj().dot(opA.dot(sig))).real assert (com.shape == (1, 1)) com = com[0, 0] assert (np.isclose(com.imag, 0)) com = com.real opstring = "" for t in pool.fermi_ops[op_trial].terms: opstring += str(t) break if abs(com) > adapt_thresh: print(" %4i %40s %12.8f" % (op_trial, opstring, com)) curr_norm += com * com if abs(com) > abs(next_deriv): next_deriv = com next_index = op_trial next_index = n_iter % pool.n_ops curr_norm = np.sqrt(curr_norm) min_options = {'gtol': theta_thresh, 'disp': False} max_of_com = next_deriv print(" Norm of <[A,H]> = %12.8f" % curr_norm) print(" Max of <[A,H]> = %12.8f" % max_of_com) converged = False if adapt_conver == "norm": if curr_norm < adapt_thresh: converged = True else: print(" FAIL: Convergence criterion not defined") exit() if converged: print(" Ansatz Growth Converged!") print(" Number of operators in ansatz: ", len(ansatz_ops)) print(" *Finished: %20.12f" % trial_model.curr_energy) print(" -----------Final ansatz----------- ") print(" %4s %40s %12s" % ("#", "Term", "Coeff")) for si in range(len(ansatz_ops)): s = ansatz_ops[si] opstring = "" for t in s.terms: opstring += str(t) break print(" %4i %40s %12.8f" % (si, opstring, parameters[si])) break print(" Add operator %4i" % next_index) parameters.insert(0, 0) ansatz_ops.insert(0, pool.fermi_ops[next_index]) ansatz_mat.insert(0, pool.spmat_ops[next_index]) trial_model = tUCCSD(hamiltonian, ansatz_mat, reference_ket, parameters) opt_result = scipy.optimize.minimize(trial_model.energy, parameters, jac=trial_model.gradient, options=min_options, method='BFGS', callback=trial_model.callback) parameters = list(opt_result['x']) curr_state = trial_model.prepare_state(parameters) print(" Finished: %20.12f" % trial_model.curr_energy) print(" -----------New ansatz----------- ") print(" %4s %40s %12s" % ("#", "Term", "Coeff")) for si in range(len(ansatz_ops)): s = ansatz_ops[si] opstring = "" for t in s.terms: opstring += str(t) break print(" %4i %40s %12.8f" % (si, opstring, parameters[si])) return
run_mp2=0, run_cisd=0, run_ccsd=0, run_fci=1, delete_input=0) #molecule = openfermionpsi4.run_psi4(molecule, run_scf = 1, run_mp2=1, run_cisd=1, run_ccsd = 1, run_fci=1, delete_input=0) n_spinorbitals = int(molecule.n_orbitals * 2) print('HF energy %20.16f au' % (molecule.hf_energy)) #print('MP2 energy %20.16f au' %(molecule.mp2_energy)) #print('CISD energy %20.16f au' %(molecule.cisd_energy)) #print('CCSD energy %20.16f au' %(molecule.ccsd_energy)) print('FCI energy %20.16f au' % (molecule.fci_energy)) #Build p-h reference and map it to JW transform reference_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state(list(range(0, molecule.n_electrons)), molecule.n_qubits)).transpose() reference_bra = reference_ket.transpose().conj() #JW transform Hamiltonian computed classically with OFPsi4 hamiltonian_op = molecule.get_molecular_hamiltonian() hamiltonian = openfermion.transforms.get_sparse_operator(hamiltonian_op) print(reference_bra.dot(hamiltonian.dot(reference_ket))) #print(" Reference energy: %12.8f" %reference_bra.dot(hamiltonian).dot(reference_ket)[0,0].real) #Thetas parameters = [] #Second_quantized operations (not Jordan-Wignered) SQ_CC_ops = [] alpha_orbs = list(range(int(n_spinorbitals / 2)))
def __init__(self, molecule, **kwargs): self.ecp = kwargs.get('ecp', 'False') #Associate a Hamiltonian with this system self.molecule = molecule print(self.ecp) if self.ecp == 'False': self.hamiltonian = molecule.get_molecular_hamiltonian() else: core = list(range(0, int(self.ecp))) valence = list(range(int(self.ecp), self.n_orbitals)) self.hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=core, active_indices=valence) wfile = open('CASCI.out', 'a') print('Hi') eigs = ((np.linalg.eigh(self.hamiltonian))[0]) print(eigs) wfile.write(str(sorted(eigs)[0]) + '\n') exit() self.two_index_hamiltonian = self.hamiltonian.one_body_tensor self.four_index_hamiltonian = self.hamiltonian.two_body_tensor self.JW_hamiltonian = openfermion.transforms.get_sparse_operator( self.hamiltonian) #Construct spaces self.aoccs = [ i for i in range(0, self.molecule.n_electrons) if i % 2 == 0 ] self.anoccs = [ i for i in range(self.molecule.n_electrons, self.molecule.n_orbitals * 2) if i % 2 == 0 ] self.boccs = [ i for i in range(0, self.molecule.n_electrons) if i % 2 == 1 ] self.bnoccs = [ i for i in range(self.molecule.n_electrons, self.molecule.n_orbitals * 2) if i % 2 == 1 ] self.alphas = self.aoccs + self.anoccs self.betas = self.boccs + self.bnoccs #Construct reference ket self.HF_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state( list(range(0, molecule.n_electrons)), molecule.n_qubits)).transpose() #Parse kwargs self.include_pqrs = kwargs.get('include_pqrs', 'False') self.screen_commutators = kwargs.get('screen_commutators', 'False') self.sort = kwargs.get('sort', None) self.spin_adapt = kwargs.get('spin_adapt', 'False') #Initialize op list self.SQ_Singles = [] self.SQ_Doubles = [] self.Singles = [] self.Doubles = [] self.Full_JW_Ops = [] #Get unfiltered list if self.include_pqrs == 'True': self.PQRS() else: self.IJAB() self.Full_Ops = self.Singles + self.Doubles self.Full_SQ_Ops = self.SQ_Singles + self.SQ_Doubles #Spin adapt if self.spin_adapt == 'True': print('Spin adapting operators...') self.Spin_Adapt() print(self.Full_Ops) for op in self.Full_SQ_Ops: op = openfermion.normal_ordered(op) if op.many_body_order() > 0: self.Full_JW_Ops.append( (1 / np.sqrt(2)) * openfermion.transforms.get_sparse_operator( op, n_qubits=self.molecule.n_qubits)) #Apply filters if self.screen_commutators == 'True': print('Screening by commutators with Hamiltonian (HF ansatz)...') self.Screen_Commutators() #Apply sorting method if self.sort == None: print('Operators not sorted!') pass elif self.sort == 'commutators': print('Sorting operators by increasing commutators...') self.Sort_Commutators() else: print('Sorting operators by seed ' + str(self.sort) + '...') self.Sort_Random(self.sort)
hamiltonian = openfermion.transforms.get_sparse_operator(fermi_ham) s2 = Make_S2(n_orb) #build reference configuration occupied_list = [] for i in range(n_a): occupied_list.append(i * 2) for i in range(n_b): occupied_list.append(i * 2 + 1) print( " Build reference state with %4i alpha and %4i beta electrons" % (n_a, n_b), occupied_list) reference_ket = scipy.sparse.csc_matrix( openfermion.jw_configuration_state(occupied_list, 2 * n_orb)).transpose() [e, v] = scipy.sparse.linalg.eigsh(hamiltonian.real, 1, which='SA', v0=reference_ket.todense()) for ei in range(len(e)): S2 = v[:, ei].conj().T.dot(s2.dot(v[:, ei])) print(" State %4i: %12.8f au <S2>: %12.8f" % (ei, e[ei] + E_nuc, S2)) fermi_ham += FermionOperator((), E_nuc) pyscf.molden.from_mo(mol, "full.molden", sq_ham.C) pool = operator_pools.singlet_SD() pool.init(n_orb, n_occ_a=n_a, n_occ_b=n_b,