def test_nh_energy(): """Checks total relativistic energy with NH.""" eref = -57.681266930627 norb = 6 nele, h1e, h2e = build_nh_data() elec_hamil = general_hamiltonian.General((h1e, h2e)) maxb = min(norb, nele) minb = nele - maxb ndim = int(binom(norb * 2, nele)) hci = np.zeros((ndim, ndim), dtype=np.complex128) for i in range(0, ndim): wfn = fqe.get_number_conserving_wavefunction(nele, norb) cnt = 0 for nbeta in range(minb, maxb + 1): coeff = wfn.get_coeff((nele, nele - 2 * nbeta)) size = coeff.size if cnt <= i < cnt + size: coeff.flat[i - cnt] = 1.0 cnt += size result = wfn.apply(elec_hamil) cnt = 0 for nbeta in range(minb, maxb + 1): coeff = result.get_coeff((nele, nele - 2 * nbeta)) for j in range(coeff.size): hci[cnt + j, i] = coeff.flat[j] cnt += coeff.size assert np.std(hci - hci.T.conj()) < 1.0e-8 eigenvals, eigenvecs = np.linalg.eigh(hci) assert np.isclose(eref, eigenvals[0], atol=1e-8) orig = eigenvecs[:, 0] wfn = fqe.get_number_conserving_wavefunction(nele, norb) cnt = 0 for nbeta in range(minb, maxb + 1): nalpha = nele - nbeta vdata = np.zeros( (int(binom(norb, nalpha)), int(binom(norb, nbeta))), dtype=np.complex128, ) for i in range(vdata.size): vdata.flat[i] = orig[cnt + i] wfn._civec[(nele, nalpha - nbeta)].coeff += vdata cnt += vdata.size hwfn = wfn.apply(elec_hamil) ecalc = fqe.vdot(wfn, hwfn).real assert np.isclose(eref, ecalc, atol=1e-8)
def test_apply_generated_unitary(self): """APply the generated unitary transformation from the fqe namespace """ norb = 4 nele = 3 time = 0.001 ops = FermionOperator('1^ 3^ 5 0', 2.0 - 2.j) + FermionOperator( '0^ 5^ 3 1', 2.0 + 2.j) wfn = fqe.get_number_conserving_wavefunction(nele, norb) wfn.set_wfn(strategy='random') wfn.normalize() reference = fqe.apply_generated_unitary(wfn, time, 'taylor', ops) h1e = numpy.zeros((2 * norb, 2 * norb), dtype=numpy.complex128) h2e = hamiltonian_utils.nbody_matrix(ops, norb) h2e = hamiltonian_utils.antisymm_two_body(h2e) hamil = general_hamiltonian.General(tuple([h1e, h2e])) compute = wfn.apply_generated_unitary(time, 'taylor', hamil) for key in wfn.sectors(): with self.subTest(key=key): diff = reference._civec[key].coeff - compute._civec[key].coeff err = linalg.norm(diff) self.assertTrue(err < 1.e-8)
def test_fqe_control_dot_vdot(self): """Find the dot product of two wavefunctions. """ wfn1 = fqe.get_number_conserving_wavefunction(4, 8) wfn1.set_wfn(strategy='ones') wfn1.normalize() self.assertAlmostEqual(fqe.vdot(wfn1, wfn1), 1. + .0j) self.assertAlmostEqual(fqe.dot(wfn1, wfn1), 1. + .0j) wfn1.set_wfn(strategy='random') wfn1.normalize() self.assertAlmostEqual(fqe.vdot(wfn1, wfn1), 1. + .0j)
def test_vbc_time_evolve(): molecule = build_h4square_moleculardata() oei, tei = molecule.get_integrals() nele = molecule.n_electrons nalpha = nele // 2 nbeta = nele // 2 sz = 0 norbs = oei.shape[0] nso = 2 * norbs fqe_wf = fqe.Wavefunction([[nele, sz, norbs]]) fqe_wf.set_wfn(strategy='random') fqe_wf.normalize() nfqe_wf = fqe.get_number_conserving_wavefunction(nele, norbs) nfqe_wf.sector((nele, sz)).coeff = fqe_wf.sector((nele, sz)).coeff _, tpdm = nfqe_wf.sector((nele, sz)).get_openfermion_rdms() d3 = nfqe_wf.sector((nele, sz)).get_three_pdm() adapt = VBC(oei, tei, nalpha, nbeta, iter_max=50) acse_residual = two_rdo_commutator_symm(adapt.reduced_ham.two_body_tensor, tpdm, d3) sos_op = adapt.get_takagi_tensor_decomp(acse_residual, None) test_wf = copy.deepcopy(nfqe_wf) test_wf = sos_op.time_evolve(test_wf) true_wf = copy.deepcopy(nfqe_wf) for v, cc in zip(sos_op.basis_rotation, sos_op.charge_charge): vc = v.conj() new_tensor = np.einsum('pi,si,ij,qj,rj->pqrs', v, vc, -1j * cc, v, vc) if np.isclose(np.linalg.norm(new_tensor), 0): continue 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=new_tensor[p, q, r, s]) fqe_op = build_hamiltonian(1j * fop, conserve_number=True) true_wf = true_wf.time_evolve(1, fqe_op) true_wf = evolve_fqe_givens_unrestricted(true_wf, sos_op.one_body_rotation) assert np.isclose(abs(fqe.vdot(true_wf, test_wf))**2, 1)
def test_save_read(self): """Check that the wavefunction can be properly archived and retieved """ numpy.random.seed(seed=409) wfn = get_number_conserving_wavefunction(3, 3) wfn.set_wfn(strategy='random') wfn.save('test_save_read') read_wfn = Wavefunction() read_wfn.read('test_save_read') for key in read_wfn.sectors(): self.assertTrue( numpy.allclose(read_wfn._civec[key].coeff, wfn._civec[key].coeff)) self.assertEqual(read_wfn._symmetry_map, wfn._symmetry_map) self.assertEqual(read_wfn._conserved, wfn._conserved) self.assertEqual(read_wfn._conserve_spin, wfn._conserve_spin) self.assertEqual(read_wfn._conserve_number, wfn._conserve_number) self.assertEqual(read_wfn._norb, wfn._norb) os.remove('test_save_read') wfn = get_spin_conserving_wavefunction(2, 6) wfn.set_wfn(strategy='random') wfn.save('test_save_read') read_wfn = Wavefunction() read_wfn.read('test_save_read') for key in read_wfn.sectors(): self.assertTrue( numpy.allclose(read_wfn._civec[key].coeff, wfn._civec[key].coeff)) self.assertEqual(read_wfn._symmetry_map, wfn._symmetry_map) self.assertEqual(read_wfn._conserved, wfn._conserved) self.assertEqual(read_wfn._conserve_spin, wfn._conserve_spin) self.assertEqual(read_wfn._conserve_number, wfn._conserve_number) self.assertEqual(read_wfn._norb, wfn._norb) os.remove('test_save_read')
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)
def test_random_evolution(): sdim = 2 nele = 2 generator = generate_antisymm_generator(2 * sdim) nso = generator.shape[0] for p, q, r, s in product(range(nso), repeat=4): if p < q and s < r: assert np.isclose(generator[p, q, r, s], -generator[q, p, r, s]) generator_mat = np.reshape(np.transpose(generator, [0, 3, 1, 2]), (nso**2, nso**2)).astype(np.float) _, sigma, _ = np.linalg.svd(generator_mat) ul, vl, _, ul_ops, vl_ops, _ = \ doubles_factorization_svd(generator) rwf = fqe.get_number_conserving_wavefunction(nele, sdim) # rwf = fqe.Wavefunction([[nele, 0, sdim]]) rwf.set_wfn(strategy='random') rwf.normalize() sigma_idx = np.where(sigma > 1.0E-13)[0] for ll in sigma_idx: Smat = ul[ll] + vl[ll] Dmat = ul[ll] - vl[ll] S = ul_ops[ll] + vl_ops[ll] D = ul_ops[ll] - vl_ops[ll] op1 = S + 1j * of.hermitian_conjugated(S) op2 = S - 1j * of.hermitian_conjugated(S) op3 = D + 1j * of.hermitian_conjugated(D) op4 = D - 1j * of.hermitian_conjugated(D) op1mat = Smat + 1j * Smat.T op2mat = Smat - 1j * Smat.T op3mat = Dmat + 1j * Dmat.T op4mat = Dmat - 1j * Dmat.T o1_rwf = rwf.time_evolve(1 / 16, 1j * op1**2) ww, vv = np.linalg.eig(op1mat) assert np.allclose(vv @ np.diag(ww) @ vv.conj().T, op1mat) trwf = evolve_fqe_givens_unrestricted(rwf, vv.conj().T) v_pq = np.outer(ww, ww) for p, q in product(range(nso), repeat=2): fop = of.FermionOperator(((p, 1), (p, 0), (q, 1), (q, 0)), coefficient=-v_pq[p, q].imag) trwf = trwf.time_evolve(1 / 16, fop) trwf = evolve_fqe_givens_unrestricted(trwf, vv) assert np.isclose(fqe.vdot(o1_rwf, trwf), 1) o_rwf = rwf.time_evolve(1 / 16, 1j * op2**2) ww, vv = np.linalg.eig(op2mat) assert np.allclose(vv @ np.diag(ww) @ vv.conj().T, op2mat) trwf = evolve_fqe_givens_unrestricted(rwf, vv.conj().T) v_pq = np.outer(ww, ww) for p, q in product(range(nso), repeat=2): fop = of.FermionOperator(((p, 1), (p, 0), (q, 1), (q, 0)), coefficient=-v_pq[p, q].imag) trwf = trwf.time_evolve(1 / 16, fop) trwf = evolve_fqe_givens_unrestricted(trwf, vv) assert np.isclose(fqe.vdot(o_rwf, trwf), 1) o_rwf = rwf.time_evolve(-1 / 16, 1j * op3**2) ww, vv = np.linalg.eig(op3mat) assert np.allclose(vv @ np.diag(ww) @ vv.conj().T, op3mat) trwf = evolve_fqe_givens_unrestricted(rwf, vv.conj().T) v_pq = np.outer(ww, ww) for p, q in product(range(nso), repeat=2): fop = of.FermionOperator(((p, 1), (p, 0), (q, 1), (q, 0)), coefficient=-v_pq[p, q].imag) trwf = trwf.time_evolve(-1 / 16, fop) trwf = evolve_fqe_givens_unrestricted(trwf, vv) assert np.isclose(fqe.vdot(o_rwf, trwf), 1) o_rwf = rwf.time_evolve(-1 / 16, 1j * op4**2) ww, vv = np.linalg.eig(op4mat) assert np.allclose(vv @ np.diag(ww) @ vv.conj().T, op4mat) trwf = evolve_fqe_givens_unrestricted(rwf, vv.conj().T) v_pq = np.outer(ww, ww) for p, q in product(range(nso), repeat=2): fop = of.FermionOperator(((p, 1), (p, 0), (q, 1), (q, 0)), coefficient=-v_pq[p, q].imag) trwf = trwf.time_evolve(-1 / 16, fop) trwf = evolve_fqe_givens_unrestricted(trwf, vv) assert np.isclose(fqe.vdot(o_rwf, trwf), 1)
def test_wavefunction_print(self): """Check printing routine for the wavefunction. """ numpy.random.seed(seed=409) wfn = get_number_conserving_wavefunction(3, 3) sector_alpha_dim, sector_beta_dim = wfn.sector((3, -3)).coeff.shape coeffs = numpy.arange(1, sector_alpha_dim * sector_beta_dim + 1).reshape( (sector_alpha_dim, sector_beta_dim)) wfn.sector((3, -3)).coeff = coeffs sector_alpha_dim, sector_beta_dim = wfn.sector((3, -1)).coeff.shape coeffs = numpy.arange(1, sector_alpha_dim * sector_beta_dim + 1).reshape( (sector_alpha_dim, sector_beta_dim)) wfn.sector((3, -1)).coeff = coeffs sector_alpha_dim, sector_beta_dim = wfn.sector((3, 1)).coeff.shape coeffs = numpy.arange(1, sector_alpha_dim * sector_beta_dim + 1).reshape( (sector_alpha_dim, sector_beta_dim)) wfn.sector((3, 1)).coeff = coeffs sector_alpha_dim, sector_beta_dim = wfn.sector((3, 3)).coeff.shape coeffs = numpy.arange(1, sector_alpha_dim * sector_beta_dim + 1).reshape( (sector_alpha_dim, sector_beta_dim)) wfn.sector((3, 3)).coeff = coeffs ref_string = 'Sector N = 3 : S_z = -3\n' + \ "a'000'b'111' 1\n" + \ "Sector N = 3 : S_z = -1\n" + \ "a'001'b'011' 1\n" + \ "a'001'b'101' 2\n" + \ "a'001'b'110' 3\n" + \ "a'010'b'011' 4\n" + \ "a'010'b'101' 5\n" + \ "a'010'b'110' 6\n" + \ "a'100'b'011' 7\n" + \ "a'100'b'101' 8\n" + \ "a'100'b'110' 9\n" + \ "Sector N = 3 : S_z = 1\n" + \ "a'011'b'001' 1\n" + \ "a'011'b'010' 2\n" + \ "a'011'b'100' 3\n" + \ "a'101'b'001' 4\n" + \ "a'101'b'010' 5\n" + \ "a'101'b'100' 6\n" + \ "a'110'b'001' 7\n" + \ "a'110'b'010' 8\n" + \ "a'110'b'100' 9\n" + \ "Sector N = 3 : S_z = 3\n" + \ "a'111'b'000' 1\n" save_stdout = sys.stdout sys.stdout = chkprint = StringIO() wfn.print_wfn() sys.stdout = save_stdout outstring = chkprint.getvalue() self.assertEqual(outstring, ref_string) wfn.print_wfn(fmt='occ') ref_string = "Sector N = 3 : S_z = -3\n" + \ "bbb 1\n" + \ "Sector N = 3 : S_z = -1\n" + \ ".b2 1\n" + \ "b.2 2\n" + \ "bba 3\n" + \ ".2b 4\n" + \ "bab 5\n" + \ "b2. 6\n" + \ "abb 7\n" + \ "2.b 8\n" + \ "2b. 9\n" + \ "Sector N = 3 : S_z = 1\n" + \ ".a2 1\n" + \ ".2a 2\n" + \ "baa 3\n" + \ "a.2 4\n" + \ "aba 5\n" + \ "2.a 6\n" + \ "aab 7\n" + \ "a2. 8\n" + \ "2a. 9\n" + \ "Sector N = 3 : S_z = 3\n" + \ "aaa 1\n" save_stdout = sys.stdout sys.stdout = chkprint = StringIO() wfn.print_wfn(fmt='occ') sys.stdout = save_stdout outstring = chkprint.getvalue() self.assertEqual(outstring, ref_string)