def test_solver_via_rdms(): molecule = build_lih_moleculardata() n_electrons = molecule.n_electrons sz = 0 oei, tei = molecule.get_integrals() elec_hamil = fqe.restricted_hamiltonian.RestrictedHamiltonian( (oei, np.einsum("ijlk", -0.5 * tei))) soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) molecular_hamiltonian = of.InteractionOperator(0, soei, 0.25 * astei) reduced_ham = of.chem.make_reduced_hamiltonian(molecular_hamiltonian, molecule.n_electrons) fqe_wf = fqe.Wavefunction([[n_electrons, sz, molecule.n_orbitals]]) graph = fqe_wf.sector((n_electrons, sz)).get_fcigraph() fci_coeffs = np.zeros((graph.lena(), graph.lenb()), dtype=np.complex128) fci_coeffs[0, 0] = 1.0 fqe_wf.set_wfn(strategy="from_data", raw_data={(n_electrons, sz): fci_coeffs}) bcsolve = BrillouinCondition(molecule, run_parallel=False) assert bcsolve.reduced_ham == reduced_ham for pp, qq in zip(elec_hamil.tensors(), bcsolve.elec_hamil.tensors()): assert np.allclose(pp, qq) bcsolve.iter_max = 1 bcsolve.bc_solve_rdms(fqe_wf) assert np.allclose(bcsolve.acse_energy, [-8.957417182801088, -8.969256797233033])
def test_get_l_m(): molecule = build_lih_moleculardata() oei, tei = molecule.get_integrals() lrt_obj = LowRankTrotter(oei=oei, tei=tei) num_l, m_list = lrt_obj.get_l_and_m(1.0e-8, 1.0e-8) assert isinstance(num_l, int) assert isinstance(m_list, list) assert len(m_list) == num_l
def test_initialization(): empty = LowRankTrotter() obj_attributes = ["molecule", "oei", "tei", "icut", "lmax", "mcut", "mmax"] for oa in obj_attributes: assert hasattr(empty, oa) molecule = build_lih_moleculardata() oei, tei = molecule.get_integrals() molecule_load = LowRankTrotter(molecule=molecule) assert np.allclose(molecule_load.oei, oei) assert np.allclose(molecule_load.tei, tei) assert np.isclose(molecule_load.icut, 1.0e-8) assert np.isclose(molecule_load.mcut, 1.0e-8)
def test_second_factorization(): molecule = build_lih_moleculardata() oei, tei = molecule.get_integrals() lrt_obj = LowRankTrotter(oei=oei, tei=tei) eigenvalues, one_body_squares, _ = lrt_obj.first_factorization() s_rho_rho, basis_changes = lrt_obj.second_factorization( eigenvalues, one_body_squares) true_basis_changes = [] for l in range(one_body_squares.shape[0]): w, v = np.linalg.eigh(one_body_squares[l][::2, ::2]) true_basis_changes.append(v.conj().T) assert np.allclose(v.conj().T, basis_changes[l]) assert np.allclose(s_rho_rho[l], eigenvalues[l] * np.outer(w, w))
def test_vbc(): molecule = build_lih_moleculardata() n_electrons = molecule.n_electrons oei, tei = molecule.get_integrals() nalpha = molecule.n_electrons // 2 nbeta = nalpha sz = nalpha - nbeta fqe_wf = fqe.Wavefunction([[n_electrons, sz, molecule.n_orbitals]]) fqe_wf.set_wfn(strategy='hartree-fock') adapt = VBC(oei, tei, nalpha, nbeta, iter_max=1, verbose=False) adapt.vbc(fqe_wf) assert np.isclose(adapt.energies[0], -8.957417182801091) assert np.isclose(adapt.energies[-1], -8.97304439380826)
def test_trotter_prep(): times = [0.1, 0.2, 0.3] molecule = build_lih_moleculardata() oei, tei = molecule.get_integrals() lrt_obj = LowRankTrotter(oei=oei, tei=tei) ( eigenvalues, one_body_squares, one_body_correction, ) = lrt_obj.first_factorization() ( scaled_density_density_matrices, basis_change_matrices, ) = lrt_obj.second_factorization(eigenvalues, one_body_squares) for tt in times: # get values from function to test test_tbasis, test_srr = lrt_obj.prepare_trotter_sequence(tt) # compute true values trotter_basis_change = [ basis_change_matrices[0] @ expm( -1j * tt * (lrt_obj.oei + one_body_correction[::2, ::2])) ] time_scaled_rho_rho_matrices = [] for ii in range(len(basis_change_matrices) - 1): trotter_basis_change.append(basis_change_matrices[ii + 1] @ basis_change_matrices[ii].conj().T) time_scaled_rho_rho_matrices.append( tt * scaled_density_density_matrices[ii]) time_scaled_rho_rho_matrices.append(tt * scaled_density_density_matrices[-1]) trotter_basis_change.append(basis_change_matrices[ii + 1].conj().T) assert len(trotter_basis_change) == len(test_tbasis) assert len(time_scaled_rho_rho_matrices) == len(test_srr) # check against true values for t1, t2 in zip(trotter_basis_change, test_tbasis): assert np.allclose(t1, t2) assert np.allclose(t1.conj().T @ t1, np.eye(t1.shape[0])) for t1, t2 in zip(test_srr, time_scaled_rho_rho_matrices): assert np.allclose(t1, t2) assert of.is_hermitian(t1)
def test_adapt(): molecule = build_lih_moleculardata() n_electrons = molecule.n_electrons oei, tei = molecule.get_integrals() norbs = molecule.n_orbitals nalpha = molecule.n_electrons // 2 nbeta = nalpha sz = nalpha - nbeta occ = list(range(nalpha)) virt = list(range(nalpha, norbs)) soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) molecular_hamiltonian = of.InteractionOperator(0, soei, 0.25 * astei) reduced_ham = of.chem.make_reduced_hamiltonian(molecular_hamiltonian, molecule.n_electrons) fqe_wf = fqe.Wavefunction([[n_electrons, sz, molecule.n_orbitals]]) fqe_wf.set_wfn(strategy='hartree-fock') sop = OperatorPool(norbs, occ, virt) sop.two_body_sz_adapted() # initialize pool adapt = ADAPT(oei, tei, sop, nalpha, nbeta, iter_max=1, verbose=False) assert np.isclose( np.linalg.norm(adapt.reduced_ham.two_body_tensor - reduced_ham.two_body_tensor), 0) adapt.adapt_vqe(fqe_wf) assert np.isclose(adapt.energies[0], -8.957417182801091) assert np.isclose(adapt.energies[-1], -8.970532463968661) sop = OperatorPool(norbs, occ, virt) sop.one_body_sz_adapted() adapt = ADAPT(oei, tei, sop, nalpha, nbeta, iter_max=10, stopping_epsilon=10, verbose=True) adapt.adapt_vqe(fqe_wf) assert np.isclose(adapt.energies[-1], -8.957417182801091) assert np.isclose(adapt.energies[0], -8.95741717733075)
def test_first_factorization(): molecule = build_lih_moleculardata() oei, tei = molecule.get_integrals() lrt_obj = LowRankTrotter(oei=oei, tei=tei) ( eigenvalues, one_body_squares, one_body_correction, ) = lrt_obj.first_factorization() # get true op n_qubits = molecule.n_qubits fermion_tei = of.FermionOperator() test_tei_tensor = np.zeros((n_qubits, n_qubits, n_qubits, n_qubits)) for p, q, r, s in product(range(oei.shape[0]), repeat=4): if np.abs(tei[p, q, r, s]) < EQ_TOLERANCE: coefficient = 0.0 else: coefficient = tei[p, q, r, s] / 2.0 for sigma, tau in product(range(2), repeat=2): if 2 * p + sigma == 2 * q + tau or 2 * r + tau == 2 * s + sigma: continue term = ( (2 * p + sigma, 1), (2 * q + tau, 1), (2 * r + tau, 0), (2 * s + sigma, 0), ) fermion_tei += of.FermionOperator(term, coefficient=coefficient) test_tei_tensor[2 * p + sigma, 2 * q + tau, 2 * r + tau, 2 * s + sigma] = coefficient mol_ham = of.InteractionOperator( one_body_tensor=np.zeros((n_qubits, n_qubits)), two_body_tensor=test_tei_tensor, constant=0, ) # check induced norm on operator checked_op = of.FermionOperator() for ( p, q, ) in product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_correction[p, q] checked_op += of.FermionOperator(term, coefficient) # Build back two-body component. for l in range(one_body_squares.shape[0]): one_body_operator = of.FermionOperator() for p, q in product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_squares[l, p, q] one_body_operator += of.FermionOperator(term, coefficient) checked_op += eigenvalues[l] * (one_body_operator**2) true_fop = of.normal_ordered(of.get_fermion_operator(mol_ham)) difference = of.normal_ordered(checked_op - true_fop) assert np.isclose(0, difference.induced_norm())
def test_generalized_doubles_takagi(): molecule = build_lih_moleculardata() oei, tei = molecule.get_integrals() nele = 4 nalpha = 2 nbeta = 2 sz = 0 norbs = oei.shape[0] nso = 2 * norbs fqe_wf = fqe.Wavefunction([[nele, sz, norbs]]) fqe_wf.set_wfn(strategy='hartree-fock') fqe_wf.normalize() _, tpdm = fqe_wf.sector((nele, sz)).get_openfermion_rdms() d3 = fqe_wf.sector((nele, sz)).get_three_pdm() soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) molecular_hamiltonian = of.InteractionOperator(0, soei, 0.25 * astei) reduced_ham = make_reduced_hamiltonian(molecular_hamiltonian, nalpha + nbeta) acse_residual = two_rdo_commutator_symm(reduced_ham.two_body_tensor, tpdm, d3) for p, q, r, s in product(range(nso), repeat=4): if p == q or r == s: continue assert np.isclose(acse_residual[p, q, r, s], -acse_residual[s, r, q, p].conj()) Zlp, Zlm, _, one_body_residual = doubles_factorization_takagi(acse_residual) test_fop = get_fermion_op(one_body_residual) # test the first four factors for ll in range(4): test_fop += 0.25 * get_fermion_op(Zlp[ll])**2 test_fop += 0.25 * get_fermion_op(Zlm[ll])**2 op1mat = Zlp[ll] op2mat = Zlm[ll] w1, v1 = sp.linalg.schur(op1mat) w1 = np.diagonal(w1) assert np.allclose(v1 @ np.diag(w1) @ v1.conj().T, op1mat) v1c = v1.conj() w2, v2 = sp.linalg.schur(op2mat) w2 = np.diagonal(w2) assert np.allclose(v2 @ np.diag(w2) @ v2.conj().T, op2mat) oww1 = np.outer(w1, w1) fqe_wf = fqe.Wavefunction([[nele, sz, norbs]]) fqe_wf.set_wfn(strategy='hartree-fock') fqe_wf.normalize() nfqe_wf = fqe.get_number_conserving_wavefunction(nele, norbs) nfqe_wf.sector((nele, sz)).coeff = fqe_wf.sector((nele, sz)).coeff this_generatory = np.einsum('pi,si,ij,qj,rj->pqrs', v1, v1c, oww1, v1, v1c) fop = of.FermionOperator() for p, q, r, s in product(range(nso), repeat=4): op = ((p, 1), (s, 0), (q, 1), (r, 0)) fop += of.FermionOperator(op, coefficient=this_generatory[p, q, r, s]) fqe_fop = build_hamiltonian(1j * fop, norb=norbs, conserve_number=True) exact_wf = fqe.apply_generated_unitary(nfqe_wf, 1, 'taylor', fqe_fop) test_wf = fqe.algorithm.low_rank.evolve_fqe_givens_unrestricted( nfqe_wf, v1.conj().T) test_wf = fqe.algorithm.low_rank.evolve_fqe_charge_charge_unrestricted( test_wf, -oww1.imag) test_wf = fqe.algorithm.low_rank.evolve_fqe_givens_unrestricted( test_wf, v1) assert np.isclose(abs(fqe.vdot(test_wf, exact_wf))**2, 1)