예제 #1
0
def test_vbc_svd_decomps():
    molecule = build_h4square_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='random')
    fqe_wf.normalize()
    _, tpdm = fqe_wf.sector((nele, sz)).get_openfermion_rdms()
    d3 = fqe_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)
    new_residual = np.zeros_like(acse_residual)
    for p, q, r, s in product(range(nso), repeat=4):
        new_residual[p, q, r, s] = (acse_residual[p, q, r, s] -
                                    acse_residual[s, r, q, p]) / 2

    sos_op = adapt.get_svd_tensor_decomp(new_residual, None)

    # reconstruct tensor from sop
    test_tensor = np.zeros_like(new_residual)
    for v, cc in zip(sos_op.basis_rotation, sos_op.charge_charge):
        vc = v.conj()
        test_tensor += np.einsum('pi,si,ij,qj,rj->pqrs', v, vc, -1j * cc, v,
                                 vc)
    assert np.allclose(test_tensor, new_residual)
예제 #2
0
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])
예제 #3
0
def davidson_diagonalization(
        hamiltonian: fqe.restricted_hamiltonian.RestrictedHamiltonian,
        n_alpha: int,
        n_beta: int,
        nroots=1,
        guess_vecs=None):
    norb = hamiltonian.dim()  # this should be the num_orbitals
    nele = n_alpha + n_beta
    sz = n_alpha - n_beta
    wfn = fqe.Wavefunction([[nele, sz, norb]])
    graph = wfn.sector((nele, sz)).get_fcigraph()

    # Generate Guess Vecs for Davidson-Liu
    if guess_vecs is None:
        guess_vec1_coeffs = np.zeros((graph.lena(), graph.lenb()))
        guess_vec2_coeffs = np.zeros((graph.lena(), graph.lenb()))
        alpha_hf = fqe.util.init_bitstring_groundstate(n_alpha)
        beta_hf = fqe.util.init_bitstring_groundstate(n_beta)
        guess_vec1_coeffs[graph.index_alpha(alpha_hf),
                          graph.index_beta(beta_hf)] = 1.0
        guess_vec2_coeffs[graph.index_alpha(alpha_hf << 1),
                          graph.index_beta(beta_hf << 1)] = 1.0

        guess_wfn1 = copy.deepcopy(wfn)
        guess_wfn2 = copy.deepcopy(wfn)
        guess_wfn1.set_wfn(
            strategy="from_data",
            raw_data={(nele, sz): guess_vec1_coeffs},
        )
        guess_wfn2.set_wfn(
            strategy="from_data",
            raw_data={(nele, sz): guess_vec2_coeffs},
        )
        fqe_random = fqe.Wavefunction([[nele, sz, norb]])
        fqe_random.set_wfn(strategy='random')
        fqe_random.sector((nele, sz)).coeff.imag = 0
        fqe_random.normalize()
        guess_vecs = [guess_wfn1, guess_wfn2, fqe_random]

    # run FQE-DL
    dl_w, dl_v = davidsonliu_fqe(hamiltonian,
                                 nroots,
                                 guess_vecs,
                                 nele=nele,
                                 sz=sz,
                                 norb=norb)
    return dl_w, dl_v
예제 #4
0
def test_double_factorization_trotter():
    norbs = 4
    n_elec = norbs
    sz = 0
    time = 0.126
    fqe_wfn = fqe.Wavefunction([[n_elec, sz, norbs]])
    fqe_wfn.set_wfn(strategy="random")
    fqe_wfn.print_wfn()
    initial_wf = fqe.to_cirq_ncr(fqe_wfn).reshape((-1, 1))

    basis_change_unitaries = []
    for ii in range(2):
        basis_change_unitaries.append(
            random_unitary_matrix(4, real=False, seed=ii))
    vij_mats = []
    for ii in range(1):
        vij_mats.append(random_hermitian_matrix(norbs, real=True, seed=ii))

    with pytest.raises(ValueError):
        _ = double_factor_trotter_evolution(fqe_wfn,
                                            basis_change_unitaries + [0],
                                            vij_mats=vij_mats,
                                            deltat=0)

    final_wfn = double_factor_trotter_evolution(
        initial_wfn=fqe_wfn,
        basis_change_unitaries=basis_change_unitaries,
        vij_mats=vij_mats,
        deltat=time,
    )

    intermediate_wfn = evolve_wf_givens(initial_wf.copy(),
                                        basis_change_unitaries[0])
    for step in range(1, len(basis_change_unitaries)):
        intermediate_wfn = evolve_wf_diagonal_coulomb(intermediate_wfn,
                                                      vij_mats[step - 1], time)
        intermediate_wfn = evolve_wf_givens(intermediate_wfn,
                                            basis_change_unitaries[step])

    test_final_wfn = fqe.from_cirq(intermediate_wfn.flatten(), 1.0e-12)
    assert np.allclose(final_wfn.rdm("i^ j"), test_final_wfn.rdm("i^ j"))
    assert np.allclose(final_wfn.rdm("i^ j^ k l"),
                       test_final_wfn.rdm("i^ j^ k l"))

    test_final_wfn = double_factor_trotter_wf_evolution(
        initial_wf.copy(), basis_change_unitaries, vij_mats, time)
    test_final_wfn = fqe.from_cirq(test_final_wfn.flatten(), 1.0e-12)
    assert np.allclose(final_wfn.rdm("i^ j"), test_final_wfn.rdm("i^ j"))
    assert np.allclose(final_wfn.rdm("i^ j^ k l"),
                       test_final_wfn.rdm("i^ j^ k l"))
예제 #5
0
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)
예제 #6
0
def test_fqe_givens():
    """Test Givens Rotation evolution for correctness."""
    # set up
    norbs = 4
    n_elec = norbs
    sz = 0
    n_qubits = 2 * norbs
    time = 0.126
    fqe_wfn = fqe.Wavefunction([[n_elec, sz, norbs]])
    fqe_wfn.set_wfn(strategy="random")
    ikappa = random_quadratic_hamiltonian(
        norbs,
        conserves_particle_number=True,
        real=False,
        expand_spin=False,
        seed=2,
    )
    fqe_ham = RestrictedHamiltonian((ikappa.n_body_tensors[1, 0], ))
    u = expm(-1j * ikappa.n_body_tensors[1, 0] * time)

    # time-evolve
    final_fqe_wfn = fqe_wfn.time_evolve(time, fqe_ham)
    spin_ham = np.kron(ikappa.n_body_tensors[1, 0], np.eye(2))
    assert of.is_hermitian(spin_ham)
    ikappa_spin = of.InteractionOperator(
        constant=0,
        one_body_tensor=spin_ham,
        two_body_tensor=np.zeros((n_qubits, n_qubits, n_qubits, n_qubits)),
    )
    bigU = expm(-1j * of.get_sparse_operator(ikappa_spin).toarray() * time)
    initial_wf = fqe.to_cirq(fqe_wfn).reshape((-1, 1))
    final_wf = bigU @ initial_wf
    final_wfn_test = fqe.from_cirq(final_wf.flatten(), 1.0e-12)

    assert np.allclose(final_fqe_wfn.rdm("i^ j"), final_wfn_test.rdm("i^ j"))
    assert np.allclose(final_fqe_wfn.rdm("i^ j^ k l"),
                       final_wfn_test.rdm("i^ j^ k l"))

    final_wfn_test2 = fqe.from_cirq(
        evolve_wf_givens(initial_wf.copy(), u.copy()).flatten(), 1.0e-12)
    givens_fqe_wfn = evolve_fqe_givens(fqe_wfn, u.copy())
    assert np.allclose(givens_fqe_wfn.rdm("i^ j"), final_wfn_test2.rdm("i^ j"))
    assert np.allclose(givens_fqe_wfn.rdm("i^ j^ k l"),
                       final_wfn_test2.rdm("i^ j^ k l"))
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
def test_charge_charge_evolution():
    norbs = 4
    n_elec = norbs
    sz = 0
    time = 0.126
    fqe_wfn = fqe.Wavefunction([[n_elec, sz, norbs]])
    fqe_wfn.set_wfn(strategy="random")
    initial_fqe_wfn = copy.deepcopy(fqe_wfn)
    initial_wf = fqe.to_cirq(fqe_wfn).reshape((-1, 1))

    # time-evolve

    vij = np.random.random((norbs, norbs))
    vij = vij + vij.T
    final_fqe_wfn = evolve_fqe_diagaonal_coulomb(initial_fqe_wfn, vij, time)
    test_wfn = evolve_wf_diagonal_coulomb(wf=initial_wf,
                                          vij_mat=vij,
                                          time=time)
    test_wfn = fqe.from_cirq(test_wfn.flatten(), 1.0e-12)

    assert np.allclose(final_fqe_wfn.rdm("i^ j"), test_wfn.rdm("i^ j"))
    assert np.allclose(final_fqe_wfn.rdm("i^ j^ k l"),
                       test_wfn.rdm("i^ j^ k l"))
예제 #10
0
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)
예제 #11
0
    import numpy
    import fqe
    from fqe.unittest_data import build_lih_data, build_hamiltonian

    numpy.set_printoptions(floatmode='fixed',
                           precision=6,
                           linewidth=80,
                           suppress=True)
    numpy.random.seed(seed=409)

    h1e, h2e, wfn = build_lih_data.build_lih_data('energy')
    lih_hamiltonian = fqe.get_restricted_hamiltonian(([  # type: ignore
        h1e, h2e
    ]))
    print(lih_hamiltonian._tensor)
    lihwfn = fqe.Wavefunction([[4, 0, 6]])
    lihwfn.set_wfn(strategy='from_data', raw_data={(4, 0): wfn})

    time = 0.01
    ops = FermionOperator('2^ 0', 3.0 - 1.j)
    ops += FermionOperator('0^ 2', 3.0 + 1.j)
    print(ops)
    sham = fqe.get_sparse_hamiltonian(ops, conserve_spin=False)
    evolved = fqe.time_evolve(lihwfn, time, sham)
    evolved.print_wfn()
    nbody_evol = lihwfn.apply_generated_unitary(time,
                                                'taylor',
                                                sham,
                                                accuracy=1.0e-8)
    evolved.ax_plus_y(-1.0, nbody_evol)
    print(evolved.norm() < 1.e-8)
예제 #12
0
def evolve_cirq_givens(initial_wf: np.ndarray, u: np.ndarray):
    n_qubits = int(np.log2(initial_wf.shape[0]))
    qubits = cirq.LineQubit.range(n_qubits)
    circuit = cirq.Circuit(optimal_givens_decomposition(qubits, u.copy()))
    final_state = circuit.final_wavefunction(initial_state=initial_wf.flatten())
    return final_state


if __name__ == "__main__":

    norbs = 10
    sz = 0
    nelec = norbs
    start_time = time.time()
    initial_wfn = fqe.Wavefunction([[nelec, sz, norbs]])
    print("Wavefunction Initialization ", time.time() - start_time)
    graph = initial_wfn.sector((nelec, sz)).get_fcigraph()
    hf_wf = np.zeros((graph.lena(), graph.lenb()), dtype=np.complex128)
    hf_wf[0, 0] = 1
    start_time = time.time()
    cirq_wf = of.jw_hartree_fock_state(nelec, 2 * norbs)
    print("Cirq wf initialization time ", time.time() - start_time)
    initial_wfn.set_wfn(strategy='from_data',
                        raw_data={(nelec, sz): hf_wf})

    # set up Hamiltonian
    ikappa = random_quadratic_hamiltonian(norbs, conserves_particle_number=True,
                                          real=True, expand_spin=False, seed=5)
    ikappa_matrix = ikappa.n_body_tensors[1, 0]
    diagonal_coulomb = fqe.diagonal_coulomb.DiagonalCoulomb(ikappa_matrix)
예제 #13
0
def davidsonliu_fqe(
    hmat: Hamiltonian,
    nroots: int,
    guess_vecs,
    nele,
    sz,
    norb,
    epsilon: float = 1.0e-8,
    verbose=False,
):
    """TODO: Add docstring."""
    if nroots < 1 or nroots > 2**(hmat.dim() - 1):
        raise ValueError("Number of roots is incorrectly specified")

    gv_sector = list(guess_vecs[0].sectors())[0]
    for gv in guess_vecs:
        if list(gv.sectors())[0] != gv_sector:
            raise TypeError("Sectors don't match for guess vectors")

    # get diagonal Hamiltonian as the preconditioner.
    # TODO: This should be changed to Slater-Condon rules construction and not
    #  this hack!
    diagonal_ham = np.zeros_like(guess_vecs[0].sector(gv_sector).coeff)
    graph = guess_vecs[0].sector(gv_sector).get_fcigraph()
    empty_vec = np.zeros_like(diagonal_ham)
    comp_basis = fqe.Wavefunction([[nele, sz, norb]])
    old_ia, old_ib = None, None

    for ia in graph.string_alpha_all():
        for ib in graph.string_beta_all():
            # empty_vec = np.zeros_like(diagonal_ham)
            if old_ia is not None and old_ib is not None:
                empty_vec[old_ia, old_ib] = 0.0
            empty_vec[graph.index_alpha(ia), graph.index_beta(ib)] = 1.0
            assert np.isclose(np.sum(empty_vec), 1)
            old_ia, old_ib = graph.index_alpha(ia), graph.index_beta(ib)
            comp_basis.set_wfn(strategy="from_data",
                               raw_data={(nele, sz): empty_vec})
            diagonal_ham[graph.index_alpha(ia),
                         graph.index_beta(ib)] = comp_basis.expectationValue(
                             hmat).real

    old_thetas = np.array([np.infty] * nroots)
    while len(guess_vecs) <= graph.lena() * graph.lenb() / 2:
        if verbose:
            print()
        current_num_gv = len(guess_vecs)
        start_time = time.time()
        subspace_mat = np.zeros((len(guess_vecs), len(guess_vecs)),
                                dtype=np.complex128)
        for i, j in product(range(len(guess_vecs)), repeat=2):
            if i >= j:
                subspace_mat[i, j] = guess_vecs[j].expectationValue(
                    hmat, brawfn=guess_vecs[i])
            subspace_mat[j, i] = subspace_mat[i, j]
        if verbose:
            print("subspace mat problem formation ", time.time() - start_time)

        # for nroots residuals
        start_time = time.time()
        w, v = np.linalg.eigh(subspace_mat)
        if verbose:
            print("subsapce eig problem time: ", time.time() - start_time)

        # if converged return
        if verbose:
            print(
                "eig convergence  {}, ".format(
                    np.linalg.norm(w[:nroots] - old_thetas)),
                w[:nroots] - old_thetas,
            )
        if np.linalg.norm(w[:nroots] - old_thetas) < epsilon:
            # build eigenvectors
            eigenvectors = []
            for i in range(nroots):
                eigenvectors.append(
                    sum([
                        v[j, i] * guess_vecs[j].sector(gv_sector).coeff
                        for j in range(current_num_gv)
                    ]))
            eigfuncs = []
            for eg in eigenvectors:
                new_wfn = copy.deepcopy(guess_vecs[0])
                new_wfn.set_wfn(strategy='from_data', raw_data={gv_sector: eg})
                eigfuncs.append(new_wfn)

            return w[:nroots], eigfuncs

        # else set new roots to the old roots
        old_thetas = w[:nroots]
        if verbose:
            print("Old Thetas: ", old_thetas)
        # update the subspace vecs with the vecs of the subspace problem with
        # the nroots lowest eigenvalues
        for i in range(nroots):
            # expand in the space of all existing guess_vecs
            subspace_eigvec_expanded = sum([
                v[j, i] * guess_vecs[j].sector(gv_sector).coeff
                for j in range(current_num_gv)
            ])
            subspace_eigvec = copy.deepcopy(guess_vecs[0])
            subspace_eigvec.set_wfn(
                strategy="from_data",
                raw_data={gv_sector: subspace_eigvec_expanded},
            )
            # this should return a fresh wavefunction copy.deepcop
            residual = subspace_eigvec.apply(hmat)
            subspace_eigvec.scale(-w[i])
            residual = residual + subspace_eigvec

            preconditioner = copy.deepcopy(residual)
            preconditioner.set_wfn(
                strategy="from_data",
                raw_data={gv_sector: np.reciprocal(w[i] - diagonal_ham)},
            )
            f_k_coeffs = np.multiply(
                preconditioner.sector(gv_sector).coeff,
                residual.sector(gv_sector).coeff,
            )
            f_k = copy.deepcopy(residual)
            f_k.set_wfn(strategy="from_data", raw_data={gv_sector: f_k_coeffs})

            # orthogonalize preconditioned_residual
            overlaps = []
            # print(len(guess_vecs))
            for idx in range(len(guess_vecs)):
                overlaps.append(
                    np.sum(
                        np.multiply(
                            guess_vecs[idx].get_coeff(gv_sector),
                            f_k.get_coeff(gv_sector),
                        )))

    for idx in range(len(guess_vecs)):
        f_k.sector(gv_sector).coeff -= (
            overlaps[idx] * guess_vecs[idx].sector(gv_sector).coeff)

    f_k.normalize()
    guess_vecs.append(f_k)

    eigenvectors = []
    for i in range(nroots):
        eigenvectors.append(
            sum([
                v[j, i] * guess_vecs[j].sector(gv_sector).coeff
                for j in range(current_num_gv)
            ]))
    eigfuncs = []
    for eg in eigenvectors:
        new_wfn = copy.deepcopy(guess_vecs[0])
        new_wfn.set_wfn(strategy='from_data', raw_data={gv_sector: eg})
        eigfuncs.append(new_wfn)

    return w[:nroots], eigfuncs
예제 #14
0
                                 norb=norb)
    return dl_w, dl_v


# TODO: Make this a unit test?
if __name__ == "__main__":
    eref = -8.877719570384043
    norb = 6
    nalpha = 2
    nbeta = 2
    sz = nalpha - nbeta
    nele = nalpha + nbeta
    h1e, h2e, lih_ground = build_lih_data("energy")
    h2e_zeros = np.zeros_like(h2e)
    elec_hamil = fqe.restricted_hamiltonian.RestrictedHamiltonian((h1e, h2e))
    wfn = fqe.Wavefunction([[nele, nalpha - nbeta, norb]])
    wfn.set_wfn(strategy="from_data",
                raw_data={(nele, nalpha - nbeta): lih_ground})
    graph = wfn.sector((4, 0)).get_fcigraph()
    ecalc = wfn.expectationValue(elec_hamil)

    # Generate Guess Vecs for Davidson-Liu
    guess_vec1_coeffs = np.zeros((graph.lena(), graph.lenb()))
    guess_vec2_coeffs = np.zeros((graph.lena(), graph.lenb()))
    alpha_hf = fqe.util.init_bitstring_groundstate(2)
    beta_hf = fqe.util.init_bitstring_groundstate(2)
    alpha_hf_idx = fqe.util.init_bitstring_groundstate(2)
    beta_hf_idx = fqe.util.init_bitstring_groundstate(2)
    guess_vec1_coeffs[graph.index_alpha(alpha_hf),
                      graph.index_beta(beta_hf)] = 1.0
    guess_vec2_coeffs[graph.index_alpha(alpha_hf << 1),