Exemple #1
0
def test_random_interaction_operator_term(order, real, seed):
    op = random_interaction_operator_term(order, real, seed)

    assert openfermion.is_hermitian(op)

    assert op.constant == 0
    assert op.one_body_tensor.shape == (order, ) * 2
    assert op.two_body_tensor.shape == (order, ) * 4

    for tensor in (op.one_body_tensor, op.two_body_tensor):
        for indices in np.argwhere(tensor):
            assert len(set(indices)) == order

    op_2 = random_interaction_operator_term(order, real, seed)
    assert op == op_2

    if order == 1:
        assert op.one_body_tensor != 0
        assert op.two_body_tensor != 0
    elif order == 2:
        assert np.all((op.one_body_tensor == 0) == np.eye(2))
    elif order == 3:
        assert np.all(op.one_body_tensor == 0)
    elif order == 4:
        assert np.all(op.one_body_tensor == 0)
    else:
        assert np.all(op.one_body_tensor == 0)
        assert np.all(op.two_body_tensor == 0)
Exemple #2
0
    def get_svd_tensor_decomp(self, residual,
                              update_rank) -> SumOfSquaresOperator:
        """
        Residual must be real
        """
        ul, vl, one_body_residual, _, _, one_body_op = \
            doubles_factorization_svd(residual,
                                      eig_cutoff=update_rank)
        # add back in tbe 1-body term after all sum-of-squares terms
        assert of.is_hermitian(1j * one_body_op)
        if not np.isclose((1j * one_body_op).induced_norm(), 0):
            # enforce symmetry in one-body sector
            one_body_residual[::2, ::2] = 0.5 * \
                                          (one_body_residual[::2,
                                           ::2] + one_body_residual[1::2, 1::2])
            one_body_residual[1::2, 1::2] = one_body_residual[::2, ::2]

        basis_list = []
        cc_list = []
        for ll in range(len(ul)):
            Smat = ul[ll] + vl[ll]
            Dmat = ul[ll] - vl[ll]
            op1mat = Smat + 1j * Smat.T
            op2mat = Smat - 1j * Smat.T
            op3mat = Dmat + 1j * Dmat.T
            op4mat = Dmat - 1j * Dmat.T

            w1, v1 = sp.linalg.schur(op1mat)
            w1 = np.diagonal(w1)
            oww1 = np.outer(w1, w1)
            basis_list.append(v1)
            cc_list.append((-1 / 16) * oww1.imag)

            w2, v2 = sp.linalg.schur(op2mat)
            w2 = np.diagonal(w2)
            oww2 = np.outer(w2, w2)
            basis_list.append(v2)
            cc_list.append((-1 / 16) * oww2.imag)

            w3, v3 = sp.linalg.schur(op3mat)
            w3 = np.diagonal(w3)
            oww3 = np.outer(w3, w3)
            basis_list.append(v3)
            cc_list.append((1 / 16) * oww3.imag)

            w4, v4 = sp.linalg.schur(op4mat)
            w4 = np.diagonal(w4)
            oww4 = np.outer(w4, w4)
            basis_list.append(v4)
            cc_list.append((1 / 16) * oww4.imag)

        sos_op = SumOfSquaresOperator(basis_rotation=basis_list,
                                      charge_charge_matrix=cc_list,
                                      sdim=self.sdim,
                                      one_body_rotation=expm(one_body_residual))
        return sos_op
Exemple #3
0
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)
Exemple #4
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"))
Exemple #5
0
def test_normal_op_tensor_reconstruction():
    sdim = 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, _, _, _, _ = \
        doubles_factorization_svd(generator)

    sigma_idx = np.where(sigma > 1.0E-13)[0]
    test_generator_mat = np.zeros_like(generator_mat)
    for p, q, r, s in product(range(nso), repeat=4):
        for ll in sigma_idx:
            Smat = ul[ll] + vl[ll]
            Dmat = ul[ll] - vl[ll]

            op1mat = Smat + 1j * Smat.T
            op2mat = Smat - 1j * Smat.T
            op3mat = Dmat + 1j * Dmat.T
            op4mat = Dmat - 1j * Dmat.T
            test_generator_mat[p * nso + s, q * nso + r] += (1 / 16) * \
                                                            (op1mat[p, s] *
                                                             op1mat[q, r] +
                                                             op2mat[p, s] *
                                                             op2mat[q, r] -
                                                             op3mat[p, s] *
                                                             op3mat[q, r] -
                                                             op4mat[p, s] *
                                                             op4mat[q, r]).real

    assert np.allclose(test_generator_mat, generator_mat)

    test_generator = np.zeros_like(generator).astype(np.complex128)
    for ll in sigma_idx:
        Smat = ul[ll] + vl[ll]
        Dmat = ul[ll] - vl[ll]

        op1mat = Smat + 1j * Smat.T
        op2mat = Smat - 1j * Smat.T
        op3mat = Dmat + 1j * Dmat.T
        op4mat = Dmat - 1j * Dmat.T

        w1, v1 = np.linalg.eig(op1mat)
        assert np.allclose(v1 @ np.diag(w1) @ v1.conj().T, op1mat)
        v1c = v1.conj()
        for m, n in product(range(op1mat.shape[0]), repeat=2):
            assert np.isclose(op1mat[m, n],
                              v1[m, :].dot(np.diag(w1)).dot(v1c[n, :]))
        w2, v2 = np.linalg.eig(op2mat)
        assert np.allclose(v2 @ np.diag(w2) @ v2.conj().T, op2mat)
        v2c = v2.conj()
        for m, n in product(range(op2mat.shape[0]), repeat=2):
            assert np.isclose(op2mat[m, n],
                              np.einsum('j,j,j', v2[m, :], w2, v2c[n, :]))

        w3, v3 = np.linalg.eig(op3mat)
        v3c = v3.conj()
        assert np.allclose(v3 @ np.diag(w3) @ v3.conj().T, op3mat)
        w4, v4 = np.linalg.eig(op4mat)
        v4c = v4.conj()
        assert np.allclose(v4 @ np.diag(w4) @ v4.conj().T, op4mat)

        test_op1 = np.zeros((nso, nso, nso, nso), dtype=np.complex128)
        test_op2 = np.zeros((nso, nso, nso, nso), dtype=np.complex128)
        test_op3 = np.zeros((nso, nso, nso, nso), dtype=np.complex128)
        test_op4 = np.zeros((nso, nso, nso, nso), dtype=np.complex128)
        oww1 = np.outer(w1, w1)
        oww2 = np.outer(w2, w2)
        oww3 = np.outer(w3, w3)
        oww4 = np.outer(w4, w4)
        assert np.allclose(v1, v2.conj())
        assert np.allclose(v1, v3.conj())
        assert np.allclose(v1, v4)
        assert np.allclose(oww1, -oww2)
        assert np.allclose(oww3, -oww4)
        for p, q, r, s in product(range(nso), repeat=4):
            test_op1[p, q, r, s] += op1mat[p, s] * op1mat[q, r]
            assert np.isclose(
                op1mat[p, s] * op1mat[q, r],
                np.einsum('i,i,ij,j,j', v1[p, :], v1c[s, :], oww1, v1[q, :],
                          v1c[r, :]))
            test_op2[p, q, r, s] += op2mat[p, s] * op2mat[q, r]
            test_op3[p, q, r, s] -= op3mat[p, s] * op3mat[q, r]
            test_op4[p, q, r, s] -= op4mat[p, s] * op4mat[q, r]

        assert np.allclose(
            np.einsum('pi,si,ij,qj,rj->pqrs', v1, v1c, oww1, v1, v1c), test_op1)
        assert np.allclose(
            np.einsum('pi,si,ij,qj,rj->pqrs', v2, v2c, oww2, v2, v2c), test_op2)
        assert np.allclose(
            np.einsum('pi,si,ij,qj,rj->pqrs', v3, v3c, -oww3, v3, v3c),
            test_op3)
        assert np.allclose(
            np.einsum('pi,si,ij,qj,rj->pqrs', v4, v4c, -oww4, v4, v4c),
            test_op4)

        test_op1 *= (1 / 16)
        test_op2 *= (1 / 16)
        test_op3 *= (1 / 16)
        test_op4 *= (1 / 16)
        assert of.is_hermitian(1j * test_op1)
        assert of.is_hermitian(1j * test_op2)
        assert of.is_hermitian(1j * test_op3)
        assert of.is_hermitian(1j * test_op4)
        test_generator += test_op1 + test_op2 + test_op3 + test_op4

    assert np.allclose(test_generator, generator)
Exemple #6
0
def test_d2_g2_mapping():
    n_density, rdm_generator, transform, molecule = system_h4()
    # n_density, rdm_generator = system_hubbard()
    # n_density, rdm_generator, transform, molecule = system()
    dim = 4
    density = AntiSymmOrbitalDensity(n_density, 2 * dim)
    tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm()
    tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm()
    phdm_ab, phdm_ba, phdm_aabb = density.construct_phdm()
    # for i, j, k, l in product(range(dim), repeat=4):
    #     fop = ((2 * i, 1), (2 * j + 1, 0), (2 * l + 1, 1), (2 * k, 0))
    #     fop = of.FermionOperator(fop)
    #     opmat = of.get_sparse_operator(fop, n_qubits=2 * dim)
    #     rdm_val = (np.trace(n_density @ opmat))
    #     # print(rdm_val, phdm_ab[i * dim + j, k * dim + l])
    #     assert np.isclose(rdm_val, phdm_ab[i * dim + j, k * dim + l])

    # for i, j, k, l in product(range(dim), repeat=4):
    #     fop = ((2 * i + 1, 1), (2 * j, 0), (2 * l, 1), (2 * k + 1, 0))
    #     fop = of.FermionOperator(fop)
    #     opmat = of.get_sparse_operator(fop, n_qubits=2 * dim)
    #     rdm_val = (np.trace(n_density @ opmat))
    #     assert np.isclose(rdm_val, phdm_ba[i * dim + j, k * dim + l])

    # for i, j, k, l in product(range(dim), repeat=4):
    #     fop = ((2 * i, 1), (2 * j, 0), (2 * k, 1), (2 * l, 0))
    #     fop = of.FermionOperator(fop)
    #     opmat = of.get_sparse_operator(of.jordan_wigner(fop), n_qubits=2 * dim)
    #     rdm_val = (np.trace(n_density @ opmat))
    #     assert np.isclose(rdm_val, phdm_aabb[i * dim + j, l * dim + k])

    # for i, j, k, l in product(range(dim), repeat=4):
    #     fop = ((2 * i + 1, 1), (2 * j + 1, 0), (2 * k + 1, 1), (2 * l + 1, 0))
    #     fop = of.FermionOperator(fop)
    #     opmat = of.get_sparse_operator(of.jordan_wigner(fop), n_qubits=2 * dim)
    #     rdm_val = (np.trace(n_density @ opmat))
    #     # print((i, j, k, l), rdm_val, phdm_aabb[i * dim + j + dim**2, l * dim + k + dim**2])
    #     assert np.isclose(rdm_val, phdm_aabb[i * dim + j + dim**2, l * dim + k + dim**2])

    # for i, j, k, l in product(range(dim), repeat=4):
    #     fop = ((2 * i, 1), (2 * j, 0), (2 * k + 1, 1), (2 * l + 1, 0))
    #     fop = of.FermionOperator(fop)
    #     opmat = of.get_sparse_operator(of.jordan_wigner(fop), n_qubits=2 * dim)
    #     rdm_val = (np.trace(n_density @ opmat))
    #     assert np.isclose(rdm_val, phdm_aabb[i * dim + j, l * dim + k + dim**2])

    # for i, j, k, l in product(range(dim), repeat=4):
    #     fop = ((2 * i + 1, 1), (2 * j + 1, 0), (2 * l, 1), (2 * k, 0))
    #     fop = of.FermionOperator(fop)
    #     opmat = of.get_sparse_operator(of.jordan_wigner(fop), n_qubits=2 * dim)
    #     rdm_val = (np.trace(n_density @ opmat))
    #     # print((i, j, k, l), rdm_val, phdm_aabb[i * dim + j + dim**2, k * dim + l])
    #     assert np.isclose(rdm_val, phdm_aabb[i * dim + j + dim**2, k * dim + l])

    # for i, j, k, l in product(range(dim), repeat=4):
    #     assert np.isclose(phdm_aabb[i * dim + j + dim**2, k * dim + l],
    #                       phdm_aabb[k * dim + l, i * dim + j + dim**2]
    #                       )

    assert of.is_hermitian(phdm_ab)
    assert of.is_hermitian(phdm_ba)
    assert of.is_hermitian(phdm_aabb)
    w, v = np.linalg.eigh(phdm_ab)
    assert np.all(w > -1.0E-14)
    w, v = np.linalg.eigh(phdm_ba)
    assert np.all(w > -1.0E-14)
    w, v = np.linalg.eigh(phdm_aabb)
    assert np.all(w > -1.0E-14)

    opdm_a, opdm_b = density.construct_opdm()
    bas_aa, bas_ab = geminal_spin_basis(dim)

    opdm_a = Tensor(opdm_a, name='ck_a')
    opdm_b = Tensor(opdm_b, name='ck_b')
    tpdm_aa = Tensor(tpdm_aa, name='cckk_aa', basis=bas_aa)
    tpdm_bb = Tensor(tpdm_bb, name='cckk_bb', basis=bas_aa)
    tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bas_ab)
    tqdm_aa = Tensor(tqdm_aa, name='kkcc_aa', basis=bas_aa)
    tqdm_bb = Tensor(tqdm_bb, name='kkcc_bb', basis=bas_aa)
    tqdm_ab = Tensor(tqdm_ab, name='kkcc_ab', basis=bas_ab)
    phdm_ab = Tensor(phdm_ab, name='ckck_ab', basis=bas_ab)
    phdm_ba = Tensor(phdm_ba, name='ckck_ba', basis=bas_ab)
    phdm_aabb = Tensor(
        phdm_aabb, name='ckck_aabb'
    )  # What basis do we want to use for super blocks like this?

    rdms = MultiTensor([
        opdm_a, opdm_b, tpdm_aa, tpdm_bb, tpdm_ab, tqdm_aa, tqdm_bb, tqdm_ab,
        phdm_ab, phdm_ba, phdm_aabb
    ])
    dual_basis = d2_g2_mapping(dim)
    rdms.dual_basis = dual_basis

    A, _, c = rdms.synthesize_dual_basis()
    Amat = A.todense()
    cmat = c.todense()

    primal_vec = rdms.vectorize_tensors()
    residual = Amat.dot(primal_vec) - cmat
    assert np.allclose(residual, np.zeros_like(residual))
def v2rdm_hubbard():
    import sys
    from openfermion.hamiltonians import MolecularData
    from openfermionpsi4 import run_psi4
    from openfermionpyscf import run_pyscf
    from openfermion.utils import map_one_pdm_to_one_hole_dm, \
        map_two_pdm_to_two_hole_dm, map_two_pdm_to_particle_hole_dm
    import openfermion as of

    e_fci = []
    e_rdm = []
    for U in [4]:  # range(1, 11):
        sites = 5
        hubbard = of.hamiltonians.fermi_hubbard(1,
                                                sites,
                                                tunneling=1,
                                                coulomb=U,
                                                chemical_potential=0,
                                                magnetic_field=0,
                                                periodic=True,
                                                spinless=False)
        # op_mat = of.get_sparse_operator(hubbard).toarray()
        # # op_mat = of.get_number_preserving_sparse_operator(hubbard, sites * 2, sites-1).toarray()
        # w, v = np.linalg.eigh(op_mat)
        # # w_idx = 5 # N4U4
        # # w_idx = 25  # N6 U4
        # w_idx = 4
        # n_density = v[:, [w_idx]] @ v[:, [w_idx]].conj().T
        # from representability.fermions.density.antisymm_sz_density import AntiSymmOrbitalDensity

        # density = AntiSymmOrbitalDensity(n_density, sites * 2)
        # tpdm_aa, tpdm_bb, tpdm_ab, [bas_aa, bas_ab] = density.construct_tpdm()
        # rev_bas_aa = dict(zip(bas_aa.values(), bas_aa.keys()))
        # rev_bas_ab = dict(zip(bas_ab.values(), bas_ab.keys()))
        # for r, s in product(range(sites), repeat=2):
        #     i, j = rev_bas_ab[r]
        #     k, l = rev_bas_ab[s]
        # tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm()
        # phdm_ab, phdm_ba, phdm_aabb = density.construct_phdm()
        # opdm_a, opdm_b = density.construct_opdm()
        # bas_aa, bas_ab = geminal_spin_basis(sites)

        # opdm_a = Tensor(opdm_a, name='ck_a')
        # opdm_b = Tensor(opdm_b, name='ck_b')
        # oqdm_a = Tensor(np.eye(4) - opdm_a.data, name='kc_a')
        # oqdm_b = Tensor(np.eye(4) - opdm_b.data, name='kc_b')
        # tpdm_aa = Tensor(tpdm_aa, name='cckk_aa', basis=bas_aa)
        # tpdm_bb = Tensor(tpdm_bb, name='cckk_bb', basis=bas_aa)
        # tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bas_ab)
        # tqdm_aa = Tensor(tqdm_aa, name='kkcc_aa', basis=bas_aa)
        # tqdm_bb = Tensor(tqdm_bb, name='kkcc_bb', basis=bas_aa)
        # tqdm_ab = Tensor(tqdm_ab, name='kkcc_ab', basis=bas_ab)
        # phdm_ab = Tensor(phdm_ab, name='ckck_ab', basis=bas_ab)
        # phdm_ba = Tensor(phdm_ba, name='ckck_ba', basis=bas_ab)
        # phdm_aabb = Tensor(phdm_aabb, name='ckck_aabb')
        # rdms = MultiTensor(
        #     [opdm_a, opdm_b, oqdm_a, oqdm_b,
        #      tpdm_aa, tpdm_bb, tpdm_ab,
        #      tqdm_aa, tqdm_bb, tqdm_ab,
        #      phdm_ab, phdm_ba, phdm_aabb])
        # rdmvec = rdms.vectorize_tensors()

        hamiltonian = of.get_interaction_operator(hubbard)
        op_mat = of.get_number_preserving_sparse_operator(
            hubbard, 2 * sites, sites - 1, spin_preserving=False).toarray()
        w, _ = np.linalg.eigh(op_mat)

        gs_e = w[0]
        print(gs_e)

        one_body_ints, two_body_ints = hamiltonian.one_body_tensor, hamiltonian.two_body_tensor
        two_body_ints = np.einsum('ijkl->ijlk', two_body_ints)

        n_electrons = sites - 1
        print('n_electrons', n_electrons)
        Na = n_electrons // 2
        Nb = n_electrons // 2
        dim = one_body_ints.shape[0]
        spatial_basis_rank = sites
        sdim = spatial_basis_rank
        mm = dim**2
        bij_bas_aa, bij_bas_ab = geminal_spin_basis(spatial_basis_rank)

        # h1, v2 = spin_orbital_interaction_tensor(two_body_ints, one_body_ints)

        opdm_a_interaction, opdm_b_interaction, v2aa, v2bb, v2ab = \
            spin_adapted_interaction_tensor_rdm_consistent(two_body_ints.real,
                                                           one_body_ints.real)

        v2ab_mat = np.zeros_like(v2ab.data)
        for i in range(spatial_basis_rank):
            # ia^ j^b j^b ia
            idx = bij_bas_ab.rev((i, i))
            v2ab_mat[idx, idx] = U

        v2ab = Tensor(v2ab_mat, basis=v2ab.basis, name=v2ab.name)

        dual_basis = sz_adapted_linear_constraints(
            spatial_basis_rank, Na, Nb, ['ck', 'cckk', 'kkcc', 'ckck'])

        print("constructed dual basis")

        copdm_a = opdm_a_interaction
        copdm_b = opdm_b_interaction
        coqdm_a = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)),
                         name='kc_a')
        coqdm_b = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)),
                         name='kc_b')
        ctpdm_aa = v2aa
        ctpdm_bb = v2bb
        ctpdm_ab = v2ab
        ctqdm_aa = Tensor(np.zeros_like(v2aa.data),
                          name='kkcc_aa',
                          basis=bij_bas_aa)
        ctqdm_bb = Tensor(np.zeros_like(v2bb.data),
                          name='kkcc_bb',
                          basis=bij_bas_aa)
        ctqdm_ab = Tensor(np.zeros_like(v2ab.data),
                          name='kkcc_ab',
                          basis=bij_bas_ab)
        cphdm_ab = Tensor(np.zeros((spatial_basis_rank * spatial_basis_rank,
                                    spatial_basis_rank * spatial_basis_rank)),
                          name='ckck_ab',
                          basis=bij_bas_ab)
        cphdm_ba = Tensor(np.zeros((spatial_basis_rank * spatial_basis_rank,
                                    spatial_basis_rank * spatial_basis_rank)),
                          name='ckck_ba',
                          basis=bij_bas_ab)
        cphdm_aabb = Tensor(np.zeros(
            (2 * spatial_basis_rank**2, 2 * spatial_basis_rank**2)),
                            name='ckck_aabb')

        ctensor = MultiTensor([
            copdm_a, copdm_b, coqdm_a, coqdm_b, ctpdm_aa, ctpdm_bb, ctpdm_ab,
            ctqdm_aa, ctqdm_bb, ctqdm_ab, cphdm_ab, cphdm_ba, cphdm_aabb
        ])

        ctensor.dual_basis = dual_basis
        A, _, b = ctensor.synthesize_dual_basis()
        print("size of dual basis", len(dual_basis.elements))

        # print(tpdm_ab.data.trace())
        # print(ctensor.vectorize_tensors().T @ rdmvec)
        # print(b.shape)
        # print("FCI Residual ", np.linalg.norm(A @ rdmvec - b))
        # exit()

        nc, nv = A.shape
        # A.eliminate_zeros()
        nnz = A.nnz

        sdp = SDP()
        sdp.nc = nc
        sdp.nv = nv
        sdp.nnz = nnz
        sdp.blockstruct = list(
            map(lambda x: int(np.sqrt(x.size)), ctensor.tensors))
        sdp.nb = len(sdp.blockstruct)
        sdp.Amat = A.real
        sdp.bvec = b.todense().real
        sdp.cvec = ctensor.vectorize_tensors().real

        Amat = A.toarray()
        # print(A.shape)
        # # DQ num vars: 4, 4, 4, 4, 6, 6, 16, 6, 6 16
        # print("D2 size ", sum([x**2 for x in [6, 6, 16]]))
        # print("D1Q1 size ", sum([x**2 for x in [4, 4, 4, 4]]))
        # print("Spin constraint ", 16**2)
        # print(sum([x**2 for x in [4, 4, 4, 4, 6, 6, 16, 16]]))

        sm = sdim * (sdim - 1) // 2

        uadapt = gen_trans_2rdm(sdim**2, sdim)

        # spin_adapted_d2ab = uadapt.T @ tpdm_ab.data @ uadapt
        # d2ab_sa_a = spin_adapted_d2ab[:sm, :sm]
        # d2ab_sa_s = spin_adapted_d2ab[sm:, sm:]

        # for r, s in product(range(sdim * (sdim - 1) // 2), repeat=2):
        #     i, j = bas_aa.fwd(r)
        #     k, l = bas_aa.fwd(s)
        #     # print((i, j, k, l), d2ab_sa_a[bas_aa.rev((i, j)), bas_aa.rev((k, l))],
        #     #       uadapt[:, r].T @ tpdm_ab.data @ uadapt[:, s]
        #     #       )
        #     assert np.isclose(d2ab_sa_a[bas_aa.rev((i, j)), bas_aa.rev((k, l))], uadapt[:, [r]].T @ tpdm_ab.data @ uadapt[:, [s]])
        #     assert np.isclose(d2ab_sa_a[bas_aa.rev((i, j)), bas_aa.rev((k, l))], np.trace(tpdm_ab.data @ (uadapt[:, [s]] @ uadapt[:, [r]].T)))
        #     assert np.isclose(d2ab_sa_a[bas_aa.rev((i, j)), bas_aa.rev((k, l))], np.einsum('ij,ij', tpdm_ab.data, (uadapt[:, [s]] @ uadapt[:, [r]].T)))
        #     assert np.isclose(tpdm_aa.data[r, s] + tpdm_aa.data[s, r], uadapt[:, [r]].T @ tpdm_ab.data @ uadapt[:, [s]] + uadapt[:, [s]].T @ tpdm_ab.data @ uadapt[:, [r]])
        #     assert np.isclose(tpdm_bb.data[r, s] + tpdm_bb.data[s, r], uadapt[:, [r]].T @ tpdm_ab.data @ uadapt[:, [s]] + uadapt[:, [s]].T @ tpdm_ab.data @ uadapt[:, [r]])

        print("AA Dim: ", sdim * (sdim - 1) / 2, sm * (sm + 1) / 2)
        for ii in range(Amat.shape[0]):
            amats = vec2block(sdp.blockstruct, Amat[ii, :])
            for aa in amats:
                assert of.is_hermitian(aa)

        sdp.Initialize()
        epsilon = 1.0E-6
        sdp.epsilon = float(epsilon)
        sdp.epsilon_inner = float(epsilon)
        sdp.disp = True
        sdp.iter_max = 50000
        sdp.inner_iter_max = 1
        sdp.inner_solve = 'CG'

        write_sdpfile("new_hubbardN{}U{}_DQG.sdp".format(sites, U), sdp.nc,
                      sdp.nv, sdp.nnz, sdp.nb, sdp.Amat, sdp.bvec, sdp.cvec,
                      sdp.blockstruct)
        # sdp_data = solve_bpsdp(sdp)
        # sdp_data.primal_vector = rdmvec
        # sdp.iter_max = 5000
        #  sdp_data = solve_bpsdp(sdp)
        solve_rrsdp(sdp)
        print(sdp.primal.T @ sdp.cvec, gs_e)