def test_mt_vectorize(): from representability.tensor import index_tuple_basis from representability.tensor import Bijection a = np.arange(16).reshape((4, 4), order='C') print(a) basis = [(0, 0), (0, 1), (1, 0), (1, 1)] basis = index_tuple_basis(basis) ta = Tensor(a, basis=basis, name='a') assert np.allclose(ta.data, a) assert ta.size == 16 assert isinstance(ta.basis, Bijection) b = np.arange(16, 16 + 36).reshape((6, 6), order='C') print(b) basis = [(0, 0), (0, 1), (0, 2), (0, 3), (1, 2), (2, 3)] basis = index_tuple_basis(basis) tb = Tensor(b, basis=basis, name='b') mt = MultiTensor([ta, tb]) dbe = DualBasisElement() dbe.add_element('a', (0, 0, 0, 1), 1.0) # 1 dbe.add_element('b', (0, 1, 0, 2), 1.0) # 24 assert mt.off_set_map == {'a': 0, 'b': 16} mt_vec_idx, _ = mt.synthesize_element(dbe) assert mt_vec_idx[0] == 1 assert mt_vec_idx[1] == 24
def test_d2_q2_mapping_hubbard(): n_density, rdm_generator = system_hubbard() density = AntiSymmOrbitalDensity(n_density, 8) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm() opdm_a, opdm_b = density.construct_opdm() bas_aa, bas_ab = geminal_spin_basis(4) 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) rdms = MultiTensor( [opdm_a, opdm_b, tpdm_aa, tpdm_bb, tpdm_ab, tqdm_aa, tqdm_bb, tqdm_ab]) dual_basis = d2_q2_mapping(4) 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 test_d2_spin_rep(): n_density, rdm_generator, transform, molecule = system() assert np.isclose(molecule.fci_energy, -2.84383506834) density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() bas_aa, bas_ab = geminal_spin_basis(molecule.n_orbitals) tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bas_ab) rdms = MultiTensor([tpdm_ab]) dim = int(np.sqrt(tpdm_ab.data.shape[0])) s_rep_dual_constant = 0 for i, j in product(range(dim), repeat=2): s_rep_dual_constant += tpdm_ab.data[bas_ab.rev((i, j)), bas_ab.rev((j, i))] N = molecule.n_electrons M = 0 S = 0 db = DualBasis() db += s_representability_d2ab(dim, N, M, S) rdms.dual_basis = db xvec = rdms.vectorize_tensors() A, _, b = rdms.synthesize_dual_basis() assert np.allclose(A.dot(xvec) - b, 0.0) assert np.allclose(A.dot(xvec), s_rep_dual_constant)
def test_d2_spin_rep_hubbard(): n_density, rdm_generator = system_hubbard() density = AntiSymmOrbitalDensity(n_density, 8) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() bas_aa, bas_ab = geminal_spin_basis(4) tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bas_ab) rdms = MultiTensor([tpdm_ab]) dim = int(np.sqrt(tpdm_ab.data.shape[0])) s_rep_dual_constant = 0 for i, j in product(range(dim), repeat=2): s_rep_dual_constant += tpdm_ab.data[bas_ab.rev((i, j)), bas_ab.rev((j, i))] N = 4 M = 0 S = 0 db = DualBasis() db += s_representability_d2ab(dim, N, M, S) rdms.dual_basis = db xvec = rdms.vectorize_tensors() A, _, b = rdms.synthesize_dual_basis() assert np.allclose(A.dot(xvec) - b, 0.0) assert np.allclose(A.dot(xvec), s_rep_dual_constant)
def test_d2_spin_sz_rep(): n_density, rdm_generator, transform, molecule = system() assert np.isclose(molecule.fci_energy, -2.84383506834) density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() opdm_a, opdm_b = density.construct_opdm() bas_aa, bas_ab = geminal_spin_basis(molecule.n_orbitals) tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bas_ab) opdm_a = Tensor(opdm_a, name='ck_a') opdm_b = Tensor(opdm_b, name='ck_b') rdms = MultiTensor([opdm_a, opdm_b, tpdm_ab]) dim = int(np.sqrt(tpdm_ab.data.shape[0])) sz_rep_value = 0 for i in range(dim): sz_rep_value += 0.5 * (opdm_a.data[i, i] - opdm_b.data[i, i]) N = molecule.n_electrons M = 0 S = 0 db = DualBasis() db += s_representability_d2ab(dim, N, M, S) db += sz_representability(dim, M) rdms.dual_basis = db xvec = rdms.vectorize_tensors() A, _, b = rdms.synthesize_dual_basis() assert np.allclose(A.dot(xvec) - b, 0.0)
def test_d2_d1_mapping_hubbard(): n_density, rdm_generator = system_hubbard() density = AntiSymmOrbitalDensity(n_density, 8) tpdm_aa, tpdm_bb, tpdm_ab, [bas_aa, bas_ab] = density.construct_tpdm() opdm_a, opdm_b = density.construct_opdm() from itertools import product test_opdm = np.zeros_like(opdm_a) for i, j in product(range(opdm_a.shape[0]), repeat=2): if i <= j: for r in range(opdm_a.shape[0]): if i != r and j != r: top_gem = tuple(sorted([i, r])) bot_gem = tuple(sorted([j, r])) parity = (-1)**(r < i) * (-1)**(r < j) if i == j: test_opdm[i, j] += tpdm_aa[bas_aa[top_gem], bas_aa[bot_gem]] * parity else: test_opdm[j, i] += tpdm_aa[bas_aa[top_gem], bas_aa[bot_gem]] * parity * 0.5 test_opdm[j, i] += tpdm_aa[bas_aa[bot_gem], bas_aa[top_gem]] * parity * 0.5 test_opdm[i, j] += tpdm_aa[bas_aa[top_gem], bas_aa[bot_gem]] * parity * 0.5 test_opdm[i, j] += tpdm_aa[bas_aa[bot_gem], bas_aa[top_gem]] * parity * 0.5 assert np.allclose(test_opdm, opdm_a) bas_aa, bas_ab = geminal_spin_basis(4) 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) rdms = MultiTensor([opdm_a, opdm_b, tpdm_aa, tpdm_bb, tpdm_ab]) # d2ab_d1a test Na = Nb = 2 dual_basis = d2ab_d1a_mapping(4, Nb) dual_basis += d2ab_d1b_mapping(4, Na) dual_basis += d2aa_d1a_mapping(4, Na) dual_basis += d2bb_d1b_mapping(4, Nb) rdms.dual_basis = dual_basis A, _, c = rdms.synthesize_dual_basis() Amat = A.todense() w, v = np.linalg.eigh(np.dot(Amat, Amat.T)) cmat = c.todense() primal_vec = rdms.vectorize_tensors() residual = Amat.dot(primal_vec) - cmat assert np.allclose(residual, np.zeros_like(residual))
def test_multitensor_init(): """ Testing the generation of a multitensor object with random tensors """ a = np.random.random((5, 5)) b = np.random.random((4, 4)) c = np.random.random((3, 3)) at = Tensor(a, name='a') bt = Tensor(b, name='b') ct = Tensor(c, name='c') mt = MultiTensor([at, bt, ct]) assert len(mt.dual_basis) == 0 vec = np.vstack((at.vectorize(), bt.vectorize())) vec = np.vstack((vec, ct.vectorize())) assert np.allclose(vec, mt.vectorize_tensors())
def test_d2_g2_mapping(): n_density, rdm_generator, transform, molecule = system_h4() density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) 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() opdm_a, opdm_b = density.construct_opdm() bas_aa, bas_ab = geminal_spin_basis(molecule.n_orbitals) 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') phdm_ba = Tensor(phdm_ba, name='ckck_ba') 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(molecule.n_orbitals) 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 test_dual_basis_element(): """ Test the generation and composition of dual basis elements :return: """ # test the addition of two BasisElements should result in a basis de = DualBasisElement() de_2 = DualBasisElement() db_0 = de + de_2 assert isinstance(db_0, DualBasis) db_1 = db_0 + db_0 assert isinstance(db_1, DualBasis) dim = 2 opdm = np.random.random((dim, dim)) opdm = (opdm.T + opdm) / 2 opdm = Tensor(opdm, name='opdm') rdm = MultiTensor([opdm]) def generate_dual_basis_element(i, j): element = DualBasisElement(["opdm"], [(i, j)], [-1.0], 1 if i == j else 0, 0) return element opdm_to_oqdm_map = DualBasis() for val, idx in opdm.all_iterator(): i, j = idx opdm_to_oqdm_map += generate_dual_basis_element(i, j) rdm.dual_basis = opdm_to_oqdm_map A, b, c = rdm.synthesize_dual_basis() Adense = A.todense() opdm_flat = opdm.data.reshape((-1, 1)) oqdm = Adense.dot(opdm_flat) test_oqdm = oqdm + b.todense() assert np.allclose(test_oqdm.reshape((dim, dim)), np.eye(dim) - opdm.data)
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 dqg_run_bpsdp(): 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 print('Running System Setup') basis = 'sto-6g' # basis = '6-31g' multiplicity = 1 # charge = 0 # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, 0.75])] # charge = 1 # geometry = [('H', [0.0, 0.0, 0.0]), ('He', [0, 0, 0.75])] charge = 0 bd = 1.2 # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, bd]), # ('H', [0.0, 0.0, 2 * bd]), ('H', [0, 0, 3 * bd])] # geometry = [['H', [0, 0, 0]], ['H', [1.2, 0, 0]], # ['H', [0, 1.2, 0]], ['H', [1.2, 1.2, 0]]] # geometry = [['He', [0, 0, 0]], ['H', [0, 0, 1.2]]] # geometry = [['Be' [0, 0, 0]], [['B', [1.2, 0, 0]]]] geometry = [['N', [0, 0, 0]], ['N', [0, 0, 1.1]]] molecule = MolecularData(geometry, basis, multiplicity, charge) # Run Psi4. # molecule = run_psi4(molecule, # run_scf=True, # run_mp2=False, # run_cisd=False, # run_ccsd=False, # run_fci=True, # delete_input=True) molecule = run_pyscf(molecule, run_scf=True, run_mp2=False, run_cisd=False, run_ccsd=False, run_fci=True) print('nuclear_repulsion', molecule.nuclear_repulsion) print('gs energy ', molecule.fci_energy) print("hf energy ", molecule.hf_energy) nuclear_repulsion = molecule.nuclear_repulsion gs_energy = molecule.fci_energy import openfermion as of hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=[0], active_indices=[1, 2, 3, 4]) print(type(hamiltonian)) print(hamiltonian) nuclear_repulsion = hamiltonian.constant hamiltonian.constant = 0 ham = of.get_sparse_operator(hamiltonian).toarray() w, v = np.linalg.eigh(ham) idx = 0 gs_energy = w[idx] n_density = v[:, [idx]] @ v[:, [idx]].conj().T from representability.fermions.density.antisymm_sz_density import AntiSymmOrbitalDensity density = AntiSymmOrbitalDensity(n_density, 8) opdm_a, opdm_b = density.construct_opdm() tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() true_tpdm = density.get_tpdm(density.rho, density.dim) true_tpdm = true_tpdm.transpose(0, 1, 3, 2) test_tpdm = unspin_adapt(tpdm_aa, tpdm_bb, tpdm_ab) assert np.allclose(true_tpdm, test_tpdm) tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm() phdm_ab, phdm_ba, phdm_aabb = density.construct_phdm() Na = np.round(opdm_a.trace()).real Nb = np.round(opdm_b.trace()).real 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 = Na + Nb print('n_electrons', n_electrons) dim = one_body_ints.shape[0] spatial_basis_rank = dim // 2 bij_bas_aa, bij_bas_ab = geminal_spin_basis(spatial_basis_rank) opdm_a_interaction, opdm_b_interaction, v2aa, v2bb, v2ab = \ spin_adapted_interaction_tensor_rdm_consistent(two_body_ints, one_body_ints) dual_basis = sz_adapted_linear_constraints( spatial_basis_rank, Na, Nb, ['ck', 'kc', 'cckk', 'ckck', 'kkcc'], S=1, M=-1) print("constructed dual basis") opdm_a = Tensor(opdm_a, name='ck_a') opdm_b = Tensor(opdm_b, name='ck_b') oqdm_a = Tensor(np.eye(dim // 2) - opdm_a.data, name='kc_a') oqdm_b = Tensor(np.eye(dim // 2) - opdm_b.data, name='kc_b') tpdm_aa = Tensor(tpdm_aa, name='cckk_aa', basis=bij_bas_aa) tpdm_bb = Tensor(tpdm_bb, name='cckk_bb', basis=bij_bas_aa) tpdm_ab = Tensor(tpdm_ab, name='cckk_ab', basis=bij_bas_ab) tqdm_aa = Tensor(tqdm_aa, name='kkcc_aa', basis=bij_bas_aa) tqdm_bb = Tensor(tqdm_bb, name='kkcc_bb', basis=bij_bas_aa) tqdm_ab = Tensor(tqdm_ab, name='kkcc_ab', basis=bij_bas_ab) phdm_ab = Tensor(phdm_ab, name='ckck_ab', basis=bij_bas_ab) phdm_ba = Tensor(phdm_ba, name='ckck_ba', basis=bij_bas_ab) phdm_aabb = Tensor(phdm_aabb, name='ckck_aabb') dtensor = 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 ]) 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**2, spatial_basis_rank**2)), name='ckck_ab', basis=bij_bas_ab) cphdm_ba = Tensor(np.zeros((spatial_basis_rank**2, spatial_basis_rank**2)), 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 ]) print( (ctensor.vectorize_tensors().T @ dtensor.vectorize_tensors())[0, 0].real) print(gs_energy) ctensor.dual_basis = dual_basis A, _, b = ctensor.synthesize_dual_basis() print("size of dual basis", len(dual_basis.elements)) print(A @ dtensor.vectorize_tensors() - b) nc, nv = A.shape A.eliminate_zeros() nnz = A.nnz from sdpsolve.sdp import SDP from sdpsolve.solvers.bpsdp import solve_bpsdp from sdpsolve.solvers.bpsdp.bpsdp_old import solve_bpsdp from sdpsolve.utils.matreshape import vec2block 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 sdp.Initialize() epsilon = 1.0E-7 sdp.epsilon = float(epsilon) sdp.epsilon_inner = float(epsilon) / 100 sdp.disp = True sdp.iter_max = 70000 sdp.inner_solve = 'CG' sdp.inner_iter_max = 2 # # sdp_data = solve_bpsdp(sdp) solve_bpsdp(sdp) # # create all the psd-matrices for the # variable_dictionary = {} # for tensor in ctensor.tensors: # linear_dim = int(np.sqrt(tensor.size)) # variable_dictionary[tensor.name] = cvx.Variable(shape=(linear_dim, linear_dim), PSD=True, name=tensor.name) # print("constructing constraints") # constraints = [] # for dbe in dual_basis: # single_constraint = [] # for tname, v_elements, p_coeffs in dbe: # active_indices = get_var_indices(ctensor.tensors[tname], v_elements) # single_constraint.append(variable_dictionary[tname][active_indices] * p_coeffs) # constraints.append(cvx.sum(single_constraint) == dbe.dual_scalar) # print('constraints constructed') # print("constructing the problem") # objective = cvx.Minimize( # cvx.trace(copdm_a.data @ variable_dictionary['ck_a']) + # cvx.trace(copdm_b.data @ variable_dictionary['ck_b']) + # cvx.trace(ctpdm_aa.data @ variable_dictionary['cckk_aa']) + # cvx.trace(ctpdm_bb.data @ variable_dictionary['cckk_bb']) + # cvx.trace(ctpdm_ab.data @ variable_dictionary['cckk_ab'])) # cvx_problem = cvx.Problem(objective, constraints=constraints) # print('problem constructed') # cvx_problem.solve(solver=cvx.SCS, verbose=True, eps=0.5E-5, max_iters=100000) # rdms_solution = vec2block(sdp.blockstruct, sdp.primal) print(gs_energy) # print(cvx_problem.value + nuclear_repulsion) # print(sdp_data.primal_value() + nuclear_repulsion) print(sdp.primal.T @ sdp.cvec) print(nuclear_repulsion) rdms = vec2block(sdp.blockstruct, sdp.primal) tpdm = unspin_adapt(rdms[4], rdms[5], rdms[6]) print(np.einsum('ijij', tpdm)) tpdm = np.einsum('ijkl->ijlk', tpdm)
def run_with_openfermion_cvxpy(): # solve the spin problem import sys from openfermion.hamiltonians import MolecularData from openfermionpsi4 import run_psi4 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 from openfermion.transforms import jordan_wigner from representability.fermions.utils import get_molecule_openfermion from representability.fermions.constraints.test_antisymm_sz_constraints import system from representability.fermions.density.spin_density import SpinOrbitalDensity print('Running System Setup') basis = 'sto-3g' # basis = '6-31g' multiplicity = 0 # charge = 0 # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, 0.75])] # charge = 1 # geometry = [('H', [0.0, 0.0, 0.0]), ('He', [0, 0, 0.75])] charge = 0 bd = 1.2 # geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, bd]), # ('H', [0.0, 0.0, 2 * bd]), ('H', [0, 0, 3 * bd])] geometry = [['H', [0, 0, 0]], ['H', [1.2, 0, 0]], ['H', [0, 1.2, 0]], ['H', [1.2, 1.2, 0]]] # geometry = [['He', [0, 0, 0]], ['H', [0, 0, 1.2]]] molecule = MolecularData(geometry, basis, multiplicity, charge) # Run Psi4. molecule = run_psi4(molecule, run_scf=True, run_mp2=False, run_cisd=False, run_ccsd=False, run_fci=True, delete_input=True) print('nuclear_repulsion', molecule.nuclear_repulsion) print('gs energy ', molecule.fci_energy) nuclear_repulsion = molecule.nuclear_repulsion gs_energy = molecule.fci_energy tpdm = np.einsum('ijkl->ijlk', molecule.fci_two_rdm) opdm = molecule.fci_one_rdm oqdm = map_one_pdm_to_one_hole_dm(opdm) tqdm = map_two_pdm_to_two_hole_dm(tpdm, opdm) phdm = map_two_pdm_to_particle_hole_dm(tpdm, opdm) tpdm = Tensor(tpdm, name='cckk') tqdm = Tensor(tqdm, name='kkcc') opdm = Tensor(opdm, name='ck') phdm = Tensor(phdm, name='ckck') hamiltonian = molecule.get_molecular_hamiltonian() 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 = molecule.n_electrons print('n_electrons', n_electrons) Na = n_electrons // 2 Nb = n_electrons // 2 dim = one_body_ints.shape[0] mm = dim**2 h1, v2 = spin_orbital_interaction_tensor(two_body_ints, one_body_ints) dual_basis = spin_orbital_linear_constraints( dim, Na, Nb, ['ck', 'cckk', 'kkcc', 'ckck'], sz=0) print("constructed dual basis") copdm = h1 coqdm = Tensor(np.zeros((dim, dim)), name='kc') ctpdm = v2 ctqdm = Tensor(np.zeros((dim, dim, dim, dim)), name='kkcc') cphdm = Tensor(np.zeros((dim, dim, dim, dim)), name='ckck') ctensor = MultiTensor([copdm, coqdm, ctpdm, ctqdm, cphdm]) ctensor.dual_basis = dual_basis print("size of dual basis", len(dual_basis.elements)) # create all the psd-matrices for the variable_dictionary = {} for tensor in ctensor.tensors: linear_dim = int(np.sqrt(tensor.size)) variable_dictionary[tensor.name] = cvx.Variable(shape=(linear_dim, linear_dim), PSD=True, name=tensor.name) print("constructing constraints") constraints = [] for dbe in dual_basis: single_constraint = [] for tname, v_elements, p_coeffs in dbe: active_indices = get_var_indices(ctensor.tensors[tname], v_elements) single_constraint.append( variable_dictionary[tname][active_indices] * p_coeffs) constraints.append(cvx.sum(single_constraint) == dbe.dual_scalar) print('constraints constructed') print("constructing the problem") # construct the problem variable for cvx # interaction_integral_matrix = np.einsum('ijkl->ijlk', v2.data).reshape((dim**2, dim**2)) interaction_integral_matrix = v2.data.reshape((dim**2, dim**2)) objective = cvx.Minimize( cvx.trace(copdm.data @ variable_dictionary['ck']) + cvx.trace(interaction_integral_matrix @ variable_dictionary['cckk'])) cvx_problem = cvx.Problem(objective, constraints=constraints) print('problem constructed') one_energy = np.trace(copdm.data.dot(opdm.data)) two_energy = np.trace(interaction_integral_matrix @ tpdm.data.reshape( (dim**2, dim**2))) # np.einsum('ijkl,ijkl', tpdm.data, ctpdm.data) # cvx_problem.solve(solver=cvx.SCS, verbose=True, eps=0.5E-6, max_iters=60000) cvx_problem.solve(solver=cvx.SCS, verbose=True, eps=1.5E-5, max_iters=60000) # print(cvx_problem.value + nuclear_repulsion, gs_energy) # this should give something close to -2.147170020986181 # assert np.isclose(cvx_problem.value + nuclear_repulsion, gs_energy) # for 2-electron systems only print(variable_dictionary['cckk'].value) # np.save("HeHminus_631g_tpdm.npy", variable_dictionary['cckk'].value) print(cvx_problem.value + nuclear_repulsion) print(gs_energy) print(nuclear_repulsion)
def test_d2_trace_hubbard(): n_density, rdm_generator = system_hubbard() density = AntiSymmOrbitalDensity(n_density, 8) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() bas_aa, bas_ab = geminal_spin_basis(4) 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) rdms = MultiTensor([tpdm_aa, tpdm_bb, tpdm_ab]) dual_basis = trace_d2_aa(4, 2) rdms.dual_basis = DualBasis(elements=[dual_basis]) A, b, c = rdms.synthesize_dual_basis() Amat = A.todense() bmat = b.todense() cmat = c.todense() primal_vec = rdms.vectorize_tensors() residual = Amat.dot(primal_vec) - cmat assert np.allclose(residual, np.zeros_like(residual)) dual_basis = trace_d2_bb(4, 2) rdms.dual_basis = DualBasis(elements=[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)) dual_basis = trace_d2_ab(4, 2, 2) rdms.dual_basis = DualBasis(elements=[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)) db = DualBasis() db += trace_d2_aa(4, 2) db += trace_d2_ab(4, 2, 2) db += trace_d2_bb(4, 2) rdms.dual_basis = db 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)
def test_d2_trace_h4(): n_density, rdm_generator, transform, molecule = system_h4() density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) dim = molecule.n_orbitals tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() Na, Nb = 2, 2 trace_ab = 0 for i, j in product(range(molecule.n_orbitals), repeat=2): trace_ab += tpdm_ab[i * dim + j, i * dim + j] assert np.isclose(trace_ab, Na, Nb) assert np.isclose(np.trace(tpdm_aa), Na * (Na - 1) / 2) assert np.isclose(np.trace(tpdm_bb), Nb * (Nb - 1) / 2) bas_aa, bas_ab = geminal_spin_basis(molecule.n_orbitals) 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) rdms = MultiTensor([tpdm_aa, tpdm_bb, tpdm_ab]) dual_basis = trace_d2_aa(molecule.n_orbitals, molecule.n_electrons / 2) rdms.dual_basis = DualBasis(elements=[dual_basis]) A, b, c = rdms.synthesize_dual_basis() Amat = A.todense() bmat = b.todense() cmat = c.todense() primal_vec = rdms.vectorize_tensors() residual = Amat.dot(primal_vec) - cmat assert np.allclose(residual, np.zeros_like(residual)) dual_basis = trace_d2_bb(molecule.n_orbitals, molecule.n_electrons / 2) rdms.dual_basis = DualBasis(elements=[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)) dual_basis = trace_d2_ab(molecule.n_orbitals, molecule.n_electrons / 2, molecule.n_electrons / 2) rdms.dual_basis = DualBasis(elements=[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)) db = DualBasis() db += trace_d2_aa(molecule.n_orbitals, molecule.n_electrons / 2) db += trace_d2_ab(molecule.n_orbitals, molecule.n_electrons / 2, molecule.n_electrons / 2) db += trace_d2_bb(molecule.n_orbitals, molecule.n_electrons / 2) rdms.dual_basis = db 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_open_shell(): import openfermion as of e_fci = [] e_rdm = [] for U in [1]: # 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) hamiltonian = of.get_interaction_operator(hubbard) op_mat = of.get_number_preserving_sparse_operator( hubbard, 2 * sites, sites, spin_preserving=True).toarray() sz_mat = of.get_number_preserving_sparse_operator( of.sz_operator(sites), 2 * sites, sites, spin_preserving=True).toarray() s2_mat = of.get_number_preserving_sparse_operator( of.s_squared_operator(sites), 2 * sites, sites, spin_preserving=True).toarray() w, v = np.linalg.eigh(op_mat) sz_exp = [] s2_exp = [] for ii in range(len(w)): sz_exp.append((v[:, [ii]].conj().T @ sz_mat @ v[:, [ii]])[0, 0].real) s2_exp.append((v[:, [ii]].conj().T @ s2_mat @ v[:, [ii]])[0, 0].real) print(sz_exp[:10]) print(s2_exp[:10]) print(w[:10]) 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 print('n_electrons', n_electrons) Na = 1 + (n_electrons // 2) Nb = n_electrons // 2 spatial_basis_rank = sites bij_bas_aa, bij_bas_ab = geminal_spin_basis(spatial_basis_rank) 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'], S=0.5, M=0.5) 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)) nc, nv = A.shape 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 sdp.Initialize() epsilon = 0.5e-5 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' sdp_data = solve_bpsdp(sdp) print(sdp.primal.T @ sdp.cvec, gs_e)
def v2rdm_cvvxpy(one_body_ints, two_body_ints, Na, Nb): """ Generate a cvxpy Problem corresponding the variational 2-RDM method Note: if you are using with integrals generated from OpenFermion you need to reorder the 2-body ints before passing to this function. this can be accomplished by changing the integrals using einsum np.einsum('ijkl->ijlk', two_body_ints). the integrals can be found after grabbing the hamiltonian from molecule.get_molecular_hamiltonian() and calling the attribute `two_body_tensor`. This routine returns a cvx problem corresponding to the v2-RDM DQG sdp. This can be solved by calling cvx.Problem.solve(). We recommend using the SCS solver. :param one_body_ints: spinless Fermion one-body integrals :param two_body_ints: spinless Fermion basis two-body integrals :param Int Na: number of Fermions with alpha-spin :param Int Nb: number of Fermions with beta-spin :return: cvxpy Problem object, variable dictionary :rtype: cvx.Problem """ dim = one_body_ints.shape[0] // 2 mm = dim**2 mn = dim * (dim - 1) // 2 h1a, h1b, v2aa, v2bb, v2ab = spin_adapted_interaction_tensor_rdm_consistent( two_body_ints, one_body_ints) print("constructing dual basis") dual_basis = sz_adapted_linear_constraints(dim, Na, Nb, ['ck', 'cckk', 'kkcc', 'ckck']) print("dual basis constructed") bas_aa, bas_ab = geminal_spin_basis(dim) v2ab.data *= 2.0 copdm_a = h1a copdm_b = h1b coqdm_a = Tensor(np.zeros((dim, dim)), name='kc_a') coqdm_b = Tensor(np.zeros((dim, dim)), name='kc_b') ctpdm_aa = v2aa ctpdm_bb = v2bb ctpdm_ab = v2ab ctqdm_aa = Tensor(np.zeros((mn, mn)), name='kkcc_aa', basis=bas_aa) ctqdm_bb = Tensor(np.zeros((mn, mn)), name='kkcc_bb', basis=bas_aa) ctqdm_ab = Tensor(np.zeros((mm, mm)), name='kkcc_ab', basis=bas_ab) cphdm_ab = Tensor(np.zeros((dim, dim, dim, dim)), name='ckck_ab') cphdm_ba = Tensor(np.zeros((dim, dim, dim, dim)), name='ckck_ba') cphdm_aabb = Tensor(np.zeros((2 * mm, 2 * mm)), 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 print('synthesizing dual basis') # A, _, b = ctensor.synthesize_dual_basis() print("dual basis synthesized") # create all the psd-matrices for the variable_dictionary = {} for tensor in ctensor.tensors: linear_dim = int(np.sqrt(tensor.size)) variable_dictionary[tensor.name] = cvx.Variable(shape=(linear_dim, linear_dim), PSD=True, name=tensor.name) print("constructing constraints") constraints = [] for dbe in dual_basis: single_constraint = [] for tname, v_elements, p_coeffs in dbe: active_indices = get_var_indices(ctensor.tensors[tname], v_elements) # vec_idx = ctensor.tensors[tname].index_vectorized(*v_elements) # dim = int(np.sqrt(ctensor.tensors[tname].size)) single_constraint.append( variable_dictionary[tname][active_indices] * p_coeffs) constraints.append(cvx.sum(single_constraint) == dbe.dual_scalar) print('constraints constructed') print("constructing the problem") # construct the problem variable for cvx objective = cvx.Minimize( cvx.trace(copdm_a.data * variable_dictionary['ck_a']) + cvx.trace(copdm_b.data * variable_dictionary['ck_b']) + cvx.trace(v2aa.data * variable_dictionary['cckk_aa']) + cvx.trace(v2bb.data * variable_dictionary['cckk_bb']) + cvx.trace(v2ab.data * variable_dictionary['cckk_ab'])) cvx_problem = cvx.Problem(objective, constraints=constraints) print('problem constructed') return cvx_problem, variable_dictionary
def test_d1_q1_mapping(): n_density, rdm_generator, transform, molecule = system_h4() density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() opdm_a, opdm_b = density.construct_opdm() oqdm_a, oqdm_b = density.construct_ohdm() bas_aa, bas_ab = geminal_spin_basis(molecule.n_orbitals) opdm_a = Tensor(opdm_a, name='ck_a') opdm_b = Tensor(opdm_b, name='ck_b') oqdm_a = Tensor(oqdm_a, name='kc_a') oqdm_b = Tensor(oqdm_b, name='kc_b') rdms = MultiTensor([opdm_a, opdm_b, oqdm_a, oqdm_b]) dual_basis = d1a_q1a_mapping(molecule.n_orbitals) 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)) dual_basis = d1b_q1b_mapping(molecule.n_orbitals) 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)) dual_basis_a = d1b_q1b_mapping(molecule.n_orbitals) dual_basis_b = d1a_q1a_mapping(molecule.n_orbitals) rdms.dual_basis = dual_basis_a + dual_basis_b 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 test_d2_trace(): n_density, rdm_generator, transform, molecule = system() assert np.isclose(molecule.fci_energy, -2.84383506834) density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) tpdm_aa, tpdm_bb, tpdm_ab, _ = density.construct_tpdm() bas_aa, bas_ab = geminal_spin_basis(molecule.n_orbitals) 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) rdms = MultiTensor([tpdm_aa, tpdm_bb, tpdm_ab]) dual_basis = trace_d2_aa(molecule.n_orbitals, molecule.n_electrons / 2) rdms.dual_basis = DualBasis(elements=[dual_basis]) A, b, c = rdms.synthesize_dual_basis() Amat = A.todense() bmat = b.todense() cmat = c.todense() primal_vec = rdms.vectorize_tensors() residual = Amat.dot(primal_vec) - cmat assert np.allclose(residual, np.zeros_like(residual)) dual_basis = trace_d2_bb(molecule.n_orbitals, molecule.n_electrons / 2) rdms.dual_basis = DualBasis(elements=[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)) dual_basis = trace_d2_ab(molecule.n_orbitals, molecule.n_electrons / 2, molecule.n_electrons / 2) rdms.dual_basis = DualBasis(elements=[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)) db = DualBasis() db += trace_d2_aa(molecule.n_orbitals, molecule.n_electrons / 2) db += trace_d2_ab(molecule.n_orbitals, molecule.n_electrons / 2, molecule.n_electrons / 2) db += trace_d2_bb(molecule.n_orbitals, molecule.n_electrons / 2) rdms.dual_basis = db 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 sdp_nrep_sz_reconstruction(corrupted_tpdm_aa, corrupted_tpdm_bb, corrupted_tpdm_ab, num_alpha, num_beta, disp=False, inner_iter_type='EXACT', epsilon=1.0E-8, max_iter=5000): if np.ndim(corrupted_tpdm_aa) != 2: raise TypeError("corrupted_tpdm_aa must be a 2-tensor") if np.ndim(corrupted_tpdm_bb) != 2: raise TypeError("corrupted_tpdm_bb must be a 2-tensor") if np.ndim(corrupted_tpdm_ab) != 2: raise TypeError("corrupted_tpdm_ab must be a 2-tensor") if num_alpha != num_beta: raise ValueError( "right now we are not supporting differing spin numbers") spatial_basis_rank = int(np.sqrt(corrupted_tpdm_ab.shape[0])) # get basis bijection bij_bas_aa, bij_bas_ab = geminal_spin_basis(spatial_basis_rank) # build basis look up table bas_aa = {} bas_ab = {} cnt_aa = 0 cnt_ab = 0 # iterate over spatial orbital indices for p, q in product(range(spatial_basis_rank), repeat=2): if q > p: bas_aa[(p, q)] = cnt_aa cnt_aa += 1 bas_ab[(p, q)] = cnt_ab cnt_ab += 1 dual_basis = sz_adapted_linear_constraints(spatial_basis_rank, num_alpha, num_beta, ['ck', 'cckk', 'kkcc', 'ckck']) dual_basis += d2_e2_mapping(spatial_basis_rank, bas_aa, bas_ab, corrupted_tpdm_aa, corrupted_tpdm_bb, corrupted_tpdm_ab) c_cckk_me_aa = spin_orbital_marginal_norm_min(corrupted_tpdm_aa.shape[0], tensor_name='cckk_me_aa') c_cckk_me_bb = spin_orbital_marginal_norm_min(corrupted_tpdm_bb.shape[0], tensor_name='cckk_me_bb') c_cckk_me_ab = spin_orbital_marginal_norm_min(corrupted_tpdm_ab.shape[0], tensor_name='cckk_me_ab') copdm_a = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)), name='ck_a') copdm_b = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank)), name='ck_b') 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 = Tensor(np.zeros_like(corrupted_tpdm_aa), name='cckk_aa', basis=bij_bas_aa) ctpdm_bb = Tensor(np.zeros_like(corrupted_tpdm_bb), name='cckk_bb', basis=bij_bas_aa) ctpdm_ab = Tensor(np.zeros_like(corrupted_tpdm_ab), name='cckk_ab', basis=bij_bas_ab) ctqdm_aa = Tensor(np.zeros_like(corrupted_tpdm_aa), name='kkcc_aa', basis=bij_bas_aa) ctqdm_bb = Tensor(np.zeros_like(corrupted_tpdm_bb), name='kkcc_bb', basis=bij_bas_aa) ctqdm_ab = Tensor(np.zeros_like(corrupted_tpdm_ab), 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') cphdm_ba = Tensor(np.zeros((spatial_basis_rank, spatial_basis_rank, spatial_basis_rank, spatial_basis_rank)), name='ckck_ba') 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, c_cckk_me_aa, c_cckk_me_bb, c_cckk_me_ab ]) ctensor.dual_basis = dual_basis A, _, b = ctensor.synthesize_dual_basis() nc, nv = A.shape 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 sdp.Initialize() sdp.epsilon = float(epsilon) sdp.epsilon_inner = float(epsilon) sdp.inner_solve = inner_iter_type sdp.disp = disp sdp.iter_max = max_iter solve_bpsdp(sdp) rdms_solution = vec2block(sdp.blockstruct, sdp.primal) return rdms_solution[4], rdms_solution[5], rdms_solution[6]
Nb = n_electrons // 2 dim = one_body_ints.shape[0] mm = dim**2 h1, v2 = spin_orbital_interaction_tensor(two_body_ints, one_body_ints) dual_basis = spin_orbital_linear_constraints( dim, Na + Nb, ['ck', 'cckk', 'kkcc', 'ckck']) print("constructed dual basis") copdm = h1 coqdm = Tensor(np.zeros((dim, dim)), name='kc') ctpdm = v2 ctqdm = Tensor(np.zeros((dim, dim, dim, dim)), name='kkcc') cphdm = Tensor(np.zeros((dim, dim, dim, dim)), name='ckck') ctensor = MultiTensor([copdm, coqdm, ctpdm, ctqdm, cphdm]) ctensor.dual_basis = dual_basis print("size of dual basis", len(dual_basis.elements)) # create all the psd-matrices for the variable_dictionary = {} for tensor in ctensor.tensors: linear_dim = int(np.sqrt(tensor.size)) variable_dictionary[tensor.name] = cvx.Variable(shape=(linear_dim, linear_dim), PSD=True, name=tensor.name) print("constructing constraints") constraints = [] for dbe in dual_basis:
def test_d2_e2_constraint(): n_density, rdm_generator, transform, molecule = system() density = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) tpdm_aa, tpdm_bb, tpdm_ab, [bas_aa, bas_ab] = density.construct_tpdm() tqdm_aa, tqdm_bb, tqdm_ab, _ = density.construct_thdm() # generate error tensors corrupted_tpdm_aa = add_gaussian_noise(tpdm_aa, 1) corrupted_tpdm_aa = 0.5 * (corrupted_tpdm_aa + corrupted_tpdm_aa.T) corrupted_tpdm_bb = add_gaussian_noise(tpdm_bb, 1) corrupted_tpdm_bb = 0.5 * (corrupted_tpdm_bb + corrupted_tpdm_bb.T) corrupted_tpdm_ab = add_gaussian_noise(tpdm_ab, 1) corrupted_tpdm_ab = 0.5 * (corrupted_tpdm_ab + corrupted_tpdm_ab.T) error_aa = corrupted_tpdm_aa - tpdm_aa error_bb = corrupted_tpdm_bb - tpdm_bb error_ab = corrupted_tpdm_ab - tpdm_ab error_matrix_aa = density.construct_tpdm_error_matrix(error_aa) error_matrix_bb = density.construct_tpdm_error_matrix(error_bb) error_matrix_ab = density.construct_tpdm_error_matrix(error_ab) assert error_matrix_aa.shape[0] == 2 * tpdm_aa.shape[0] assert error_matrix_bb.shape[0] == 2 * tpdm_bb.shape[0] assert error_matrix_ab.shape[0] == 2 * tpdm_ab.shape[0] dim_aa = tpdm_aa.shape[0] dim_bb = tpdm_bb.shape[0] dim_ab = tpdm_ab.shape[0] assert np.allclose(error_matrix_aa[:dim_aa, :dim_aa], np.eye(dim_aa)) assert np.allclose(error_matrix_bb[:dim_bb, :dim_bb], np.eye(dim_bb)) assert np.allclose(error_matrix_ab[:dim_ab, :dim_ab], np.eye(dim_ab)) assert np.allclose(error_matrix_aa[:dim_aa, dim_aa:], error_aa) assert np.allclose(error_matrix_aa[dim_aa:, :dim_aa], error_aa.T) assert np.allclose(error_matrix_bb[:dim_bb, dim_bb:], error_bb) assert np.allclose(error_matrix_bb[dim_bb:, :dim_bb], error_bb.T) assert np.allclose(error_matrix_ab[:dim_ab, dim_ab:], error_ab) assert np.allclose(error_matrix_ab[dim_ab:, :dim_ab], error_ab.T) # get basis bijection bij_bas_aa, bij_bas_ab = geminal_spin_basis(molecule.n_orbitals) tpdm_aa = Tensor(tensor=tpdm_aa, name='cckk_aa', basis=bij_bas_aa) error_tensor_aa = Tensor(tensor=error_matrix_aa, name='cckk_me_aa') tpdm_bb = Tensor(tensor=tpdm_bb, name='cckk_bb', basis=bij_bas_aa) error_tensor_bb = Tensor(tensor=error_matrix_bb, name='cckk_me_bb') tpdm_ab = Tensor(tensor=tpdm_ab, name='cckk_ab', basis=bij_bas_ab) error_tensor_ab = Tensor(tensor=error_matrix_ab, name='cckk_me_ab') rdms = MultiTensor([ tpdm_aa, tpdm_bb, tpdm_ab, error_tensor_aa, error_tensor_bb, error_tensor_ab ]) xvec = rdms.vectorize_tensors() db = d2_e2_mapping(int(np.sqrt(dim_ab)), bas_aa, bas_ab, corrupted_tpdm_aa, corrupted_tpdm_bb, corrupted_tpdm_ab) rdms.dual_basis = db A, _, b = rdms.synthesize_dual_basis() A = A.todense() b = b.todense() w, v = np.linalg.eigh(A.dot(A.T)) assert np.all(w > 0) assert np.allclose(A.dot(xvec) - b, 0.0)
def sdp_nrep_reconstruction(corrupted_tpdm, num_alpha, num_beta): """ Reconstruct a 2-RDm that looks like the input corrupted tpdm This reconstruction scheme uses the spin-orbital reconstruction code which is not the optimal size SDP :param corrupted_tpdm: measured 2-RDM from the device :param num_alpha: number of alpha spin electrons :param num_beta: number of beta spin electrons :return: purified 2-RDM """ if np.ndim(corrupted_tpdm) != 4: raise TypeError("corrupted_tpdm must be a 4-tensor") if num_alpha != num_beta: raise ValueError( "right now we are not supporting differing spin numbers") sp_dim = corrupted_tpdm.shape[0] # single-particle rank opdm = np.zeros((sp_dim, sp_dim), dtype=int) oqdm = np.zeros((sp_dim, sp_dim), dtype=int) tpdm = np.zeros_like(corrupted_tpdm) tqdm = np.zeros_like(corrupted_tpdm) tgdm = np.zeros_like(corrupted_tpdm) opdm = Tensor(tensor=opdm, name='ck') oqdm = Tensor(tensor=oqdm, name='kc') tpdm = Tensor(tensor=tpdm, name='cckk') tqdm = Tensor(tensor=tqdm, name='kkcc') tgdm = Tensor(tensor=tgdm, name='ckck') error_matrix = spin_orbital_marginal_norm_min(sp_dim**2, tensor_name='cckk_me') rdms = MultiTensor([opdm, oqdm, tpdm, tqdm, tgdm, error_matrix]) db = spin_orbital_linear_constraints(sp_dim, num_alpha + num_beta, ['ck', 'cckk', 'kkcc', 'ckck']) db += d2_e2_mapping_spinorbital(sp_dim, corrupted_tpdm) rdms.dual_basis = db A, _, c = rdms.synthesize_dual_basis() nv = A.shape[1] nc = A.shape[0] nnz = A.nnz blocklist = [ sp_dim, sp_dim, sp_dim**2, sp_dim**2, sp_dim**2, 2 * sp_dim**2 ] nb = len(blocklist) sdp = SDP() sdp.nc = nc sdp.nv = nv sdp.nnz = nnz sdp.blockstruct = blocklist sdp.nb = nb sdp.Amat = A.real sdp.bvec = c.todense().real sdp.cvec = rdms.vectorize_tensors().real sdp.Initialize() sdp.epsilon = float(1.0E-8) sdp.inner_solve = "EXACT" sdp.disp = True solve_bpsdp(sdp) solution_rdms = vec2block(blocklist, sdp.primal) tpdm_reconstructed = np.zeros_like(corrupted_tpdm) for p, q, r, s in product(range(sp_dim), repeat=4): tpdm_reconstructed[p, q, r, s] = solution_rdms[2][p * sp_dim + q, r * sp_dim + s] return tpdm_reconstructed