def t1_tpdm_component(p, q, r, i, j, k): """ Iterate through two-RDM mapping components of T1 map :param Int p: index for T1 term :param Int q: index for T1 term :param Int r: index for T1 term :param Int i: index for T1 term :param Int j: index for T1 term :param Int k: index for T1 term :return: Generator yielding DualbasisElements """ terms = [ DualElementStructGenerator(1.0, [(i, p)], 'cckk', (q, r, j, k)), DualElementStructGenerator(-1.0, [(i, q)], 'cckk', (p, r, j, k)), DualElementStructGenerator(1.0, [(i, r)], 'cckk', (p, q, j, k)), DualElementStructGenerator(-1.0, [(j, p)], 'cckk', (q, r, i, k)), DualElementStructGenerator(1.0, [(j, q)], 'cckk', (p, r, i, k)), DualElementStructGenerator(-1.0, [(j, r)], 'cckk', (p, q, i, k)), DualElementStructGenerator(1.0, [(k, p)], 'cckk', (q, r, i, j)), DualElementStructGenerator(-1.0, [(k, q)], 'cckk', (p, r, i, j)), DualElementStructGenerator(1.0, [(k, r)], 'cckk', (p, q, i, j)) ] # create the generator that yeilds the next non-zero 2-RDM component for desg_term in terms: dbe = DualBasisElement() delta_val = 1.0 for krond_pair in desg_term.deltas: delta_val *= kdelta(*krond_pair) if np.isclose(delta_val, 1.0): dbe.add_element(desg_term.tensor_name, desg_term.tensor_element, desg_term.coeff) yield dbe
def d2bb_d1b_mapping(dim, normalization): """ Construct dual basis for contracting d2 -> d1 :param dim: linear dimension of the 1-RDM :param normalization: normalization constant for coeff of D1 elememnts :return: the dual basis of the contraction :rtype: DualBasis """ db_basis = DualBasis() dbe_list = [] dim /= 2 dim = int(dim) for i in range(dim): for j in range(i, dim): dbe = DualBasisElement() for r in range(dim): # duplicate entries get summed in DualBasisElement dbe.add_element('cckk', (2 * i + 1, 2 * r + 1, 2 * j + 1, 2 * r + 1), 0.5) dbe.add_element('cckk', (2 * j + 1, 2 * r + 1, 2 * i + 1, 2 * r + 1), 0.5) # D1 terms dbe.add_element('ck', (2 * i + 1, 2 * j + 1), -0.5 * normalization) dbe.add_element('ck', (2 * j + 1, 2 * i + 1), -0.5 * normalization) dbe.simplify() db_basis += dbe # dbe_list.append(dbe) # return DualBasis(elements=dbe_list) # db_basis return db_basis
def d1_q1_mapping(dim): """ Map the ck to kc D1 + Q1 = I :param dim: linear dimension of the 1-RDM :return: the dual basis of the mapping :rtype: DualBasis """ db = DualBasis() dbe_list = [] for i in range(dim): for j in range(i, dim): dbe = DualBasisElement() if i != j: dbe.add_element('ck', (i, j), 0.5) dbe.add_element('ck', (j, i), 0.5) dbe.add_element('kc', (j, i), 0.5) dbe.add_element('kc', (i, j), 0.5) dbe.dual_scalar = 0.0 else: dbe.add_element('ck', (i, j), 1.0) dbe.add_element('kc', (i, j), 1.0) dbe.dual_scalar = 1.0 # db += dbe dbe_list.append(dbe) return DualBasis(elements=dbe_list) # db
def _trace_map(tname, dim, normalization): dbe = DualBasisElement() for i, j in product(range(dim), repeat=2): if i < j: dbe.add_element(tname, (i, j, i, j), 1.0) dbe.dual_scalar = normalization return dbe
def trace_d2_bb(dim, Nb): dbe = DualBasisElement() for i, j in product(range(dim), repeat=2): if i < j: dbe.add_element('cckk_bb', (i, j, i, j), 2.0) dbe.dual_scalar = Nb * (Nb - 1) return dbe
def antisymmetry_constraints(dim): """ The dual basis elements representing the antisymmetry constraints :param dim: spinless Fermion basis rank :return: the dual basis of antisymmetry_constraints :rtype: DualBasis """ # dual_basis = DualBasis() dbe_list = [] for p, q, r, s in product(range(dim), repeat=4): if p * dim + q <= r * dim + s: if p < q and r < s: tensor_elements = [ tuple(indices) for indices in _coord_generator(p, q, r, s) ] tensor_names = ['cckk'] * len(tensor_elements) tensor_coeffs = [0.5] * len(tensor_elements) dbe = DualBasisElement() for n, e, c in zip(tensor_names, tensor_elements, tensor_coeffs): dbe.add_element(n, e, c) # dual_basis += dbe dbe_list.append(dbe) return DualBasis(elements=dbe_list)
def nb_constraint(dim, nb): """ :param dim: :param sz: :return: """ dbe = DualBasisElement() for i in range(dim // 2): dbe.add_element('ck', (2 * i + 1, 2 * i + 1), 1.0) dbe.dual_scalar = nb return DualBasis(elements=[dbe])
def d2_to_t1_from_iterator(dim): """ Generate T1 from the iteratively generated dbe elements :param dim: :return: """ db = [] # NOTE: Figure out why join_elements is not working for p, q, r, i, j, k in product(range(dim), repeat=6): if p != q and q != r and p != r and i != j and j != k and i != k: print(p, q, r, i, j, k) dbe = DualBasisElement() dbe.dual_scalar -= t1_dual_scalar(p, q, r, i, j, k) for element in t1_opdm_component(p, q, r, i, j, k): # dbe.join_elements(element) # print(element.primal_tensors_names, element.primal_elements, element.primal_coeffs) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0]) for element in t1_tpdm_component(p, q, r, i, j, k): # dbe.join_elements(element) # print(element.primal_tensors_names, element.primal_elements, element.primal_coeffs) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0]) dbe.add_element('t1', (p, q, r, i, j, k), -1.0) db.append(dbe) return DualBasis(elements=db)
def d2q2element_ab(p, q, r, s, factor, tname_d1_1, tname_d1_2, tname_d2, tname_q2): if tname_d1_1 != 'ck_a': raise TypeError("For some reason I am expecting a ck_a. Ask Nick") dbe = DualBasisElement() dbe.add_element(tname_d1_1, (p, r), krond[q, s] * factor) dbe.add_element(tname_d1_2, (q, s), krond[p, r] * factor) dbe.add_element(tname_q2, (r, s, p, q), 1.0 * factor) dbe.add_element(tname_d2, (p, q, r, s), -1.0 * factor) dbe.dual_scalar = krond[q, s] * krond[p, r] * factor return dbe
def s_representability_d2ab(dim, N, M, S): """ Constraint for S-representability PHYSICAL REVIEW A 72, 052505 2005 :param dim: number of spatial basis functions :param N: Total number of electrons :param M: Sz expected value :param S: S(S + 1) is eigenvalue of S^{2} :return: """ dbe = DualBasisElement() for i, j in product(range(dim), repeat=2): dbe.add_element('cckk_ab', (i, j, j, i), 1.0) dbe.dual_scalar = N / 2.0 + M**2 - S * (S + 1) return dbe
def _d1_q1_mapping(tname_d1, tname_q1, dim): db = DualBasis() for i in range(dim): for j in range(i, dim): dbe = DualBasisElement() if i != j: dbe.add_element(tname_d1, (i, j), 0.5) dbe.add_element(tname_d1, (j, i), 0.5) dbe.add_element(tname_q1, (i, j), 0.5) dbe.add_element(tname_q1, (j, i), 0.5) dbe.dual_scalar = 0.0 else: dbe.add_element(tname_d1, (i, j), 1.0) dbe.add_element(tname_q1, (i, j), 1.0) dbe.dual_scalar = 1.0 db += dbe # .simplify() return db
def t1_opdm_component(p, q, r, i, j, k): """ Iterate through one-RDM mapping components of T1 map :param Int p: Index for T1 matrix :param Int q: Index for T1 matrix :param Int r: Index for T1 matrix :param Int i: Index for T1 matrix :param Int j: Index for T1 matrix :param Int k: Index for T1 matrix :return: yield non-zero elements """ terms = [ DualElementStructGenerator(1.0, [(i, p), (j, q)], 'ck', (r, k)), DualElementStructGenerator(-1.0, [(i, p), (j, r)], 'ck', (q, k)), DualElementStructGenerator(-1.0, [(i, p), (k, q)], 'ck', (r, j)), DualElementStructGenerator(1.0, [(i, p), (k, r)], 'ck', (q, j)), DualElementStructGenerator(-1.0, [(i, q), (j, p)], 'ck', (r, k)), DualElementStructGenerator(1.0, [(i, q), (j, r)], 'ck', (p, k)), DualElementStructGenerator(1.0, [(i, q), (k, p)], 'ck', (r, j)), DualElementStructGenerator(-1.0, [(i, q), (k, r)], 'ck', (p, j)), DualElementStructGenerator(1.0, [(i, r), (j, p)], 'ck', (q, k)), DualElementStructGenerator(-1.0, [(i, r), (j, q)], 'ck', (p, k)), DualElementStructGenerator(-1.0, [(i, r), (k, p)], 'ck', (q, j)), DualElementStructGenerator(1.0, [(i, r), (k, q)], 'ck', (p, j)), DualElementStructGenerator(1.0, [(j, p), (k, q)], 'ck', (r, i)), DualElementStructGenerator(-1.0, [(j, p), (k, r)], 'ck', (q, i)), DualElementStructGenerator(-1.0, [(j, q), (k, p)], 'ck', (r, i)), DualElementStructGenerator(1.0, [(j, q), (k, r)], 'ck', (p, i)), DualElementStructGenerator(1.0, [(j, r), (k, p)], 'ck', (q, i)), DualElementStructGenerator(-1.0, [(j, r), (k, q)], 'ck', (p, i)) ] # Create the generator that yeilds the next non-zero 1-RDM component for desg_term in terms: dbe = DualBasisElement() delta_val = 1.0 for krond_pair in desg_term.deltas: delta_val *= kdelta(*krond_pair) if np.isclose(delta_val, 1.0): dbe.add_element(desg_term.tensor_name, desg_term.tensor_element, desg_term.coeff) yield dbe
def _contraction_base(tname_d2, tname_d1, dim, normalization, offset): db = DualBasis() for i in range(dim): for j in range(i + offset, dim): dbe = DualBasisElement() for r in range(dim): dbe.add_element(tname_d2, (i, r, j, r), 0.5) dbe.add_element(tname_d2, (j, r, i, r), 0.5) dbe.add_element(tname_d1, (i, j), -0.5 * normalization) dbe.add_element(tname_d1, (j, i), -0.5 * normalization) dbe.dual_scalar = 0 dbe.simplify() db += dbe return db
def g2d2map_aabb(p, q, r, s, dim, key, factor=1.0): """ Accept pqrs of G2 and map to D2 """ dbe = DualBasisElement() # this is ugly. :( quad = {'aabb': [0, 1], 'bbaa': [1, 0]} dbe.add_element('ckck_aabb', (p * dim + q + quad[key][0] * dim**2, r * dim + s + quad[key][1] * dim**2), 1.0 * factor) dbe.add_element('ckck_aabb', (r * dim + s + quad[key[::-1]][0] * dim**2, p * dim + q + quad[key[::-1]][1] * dim**2), 1.0 * factor) dbe.add_element('cckk_ab', (p, s, q, r), -1.0 * factor) dbe.add_element('cckk_ab', (q, r, p, s), -1.0 * factor) dbe.dual_scalar = 0.0 return dbe
def g2d2map_aa_or_bb(p, q, r, s, dim, key, factor=1.0): """ Accept pqrs of G2 and map to D2 """ dbe = DualBasisElement() quad = {'aa': [0, 0], 'bb': [1, 1]} dbe.add_element('ckck_aabb', (p * dim + q + quad[key][0] * dim**2, r * dim + s + quad[key][1] * dim**2), -1.0 * factor) dbe.add_element('ck_' + key[0], (p, r), krond[q, s] * factor) if p != s and r != q: gem1 = tuple(sorted([p, s])) gem2 = tuple(sorted([r, q])) parity = (-1)**(p < s) * (-1)**(r < q) dbe.add_element('cckk_' + key, (gem1[0], gem1[1], gem2[0], gem2[1]), parity * -0.5 * factor) dbe.dual_scalar = 0 return dbe
def sz_constraint(dim, sz): """ Sz constraint is on the 1-RDM :param dim: :param sz: :return: """ dbe = DualBasisElement() for i in range(dim // 2): dbe.add_element('ck', (2 * i, 2 * i), 0.5) dbe.add_element('ck', (2 * i + 1, 2 * i + 1), -0.5) dbe.dual_scalar = sz return DualBasis(elements=[dbe])
def d2q2element(p, q, r, s, factor): """ Build the dual basis element for symmetric form of 2-marginal :param p: tensor index :param q: tensor index :param r: tensor index :param s: tensor index :param factor: scaling coeff for a symmetric constraint :return: the dual basis of the mapping """ dbe = DualBasisElement() dbe.add_element('cckk', (p, q, r, s), -1.0 * factor) dbe.add_element('kkcc', (r, s, p, q), +1.0 * factor) dbe.add_element('ck', (p, r), krond[q, s] * factor) dbe.add_element('ck', (q, s), krond[p, r] * factor) dbe.add_element('ck', (p, s), -1. * krond[q, r] * factor) dbe.add_element('ck', (q, r), -1. * krond[p, s] * factor) dbe.dual_scalar = (krond[q, s] * krond[p, r] - krond[q, r] * krond[p, s]) * factor return dbe
def trace_constraint(dim, normalization): """ Generate the trace constraint on the 2-RDM :param dim: spinless Fermion basis rank :return: the dual basis element :rtype: DualBasisElement """ tensor_elements = [(i, j, i, j) for i, j in product(range(dim), repeat=2)] tensor_names = ['cckk'] * (dim**2) tensor_coeffs = [1.0] * (dim**2) bias = 0 return DualBasisElement(tensor_names=tensor_names, tensor_elements=tensor_elements, tensor_coeffs=tensor_coeffs, bias=bias, scalar=normalization)
def sz_representability(dim, M): """ Constraint for S_z-representability Helgaker, Jorgensen, Olsen. Sz is one-body RDM constraint :param dim: number of spatial basis functions :param M: Sz expected value :return: """ dbe = DualBasisElement() for i in range(dim): dbe.add_element('ck_a', (i, i), 0.5) dbe.add_element('ck_b', (i, i), -0.5) dbe.dual_scalar = M return dbe
def d2ab_d1b_mapping(dim, Na): """ Map the d2_spin-adapted 2-RDM to the D1 rdm :param Nb: number of beta electrons :param dim: :return: """ db = DualBasis() for i in range(dim): for j in range(i, dim): dbe = DualBasisElement() for r in range(dim): dbe.add_element('cckk_ab', (r, i, r, j), 0.5) dbe.add_element('cckk_ab', (r, j, r, i), 0.5) dbe.add_element('ck_b', (i, j), -0.5 * Na) dbe.add_element('ck_b', (j, i), -0.5 * Na) dbe.dual_scalar = 0 dbe.simplify() db += dbe return db
def g2d2map(p, q, r, s, factor=1): """ Build the dual basis element for a symmetric 2-marginal :param p: tensor index :param q: tensor index :param r: tensor index :param s: tensor index :param factor: weighting of the element :return: the dual basis element """ dbe = DualBasisElement() dbe.add_element('ck', (p, r), -1. * krond[q, s] * factor) dbe.add_element('ckck', (p, s, r, q), 1.0 * factor) dbe.add_element('cckk', (p, q, r, s), 1.0 * factor) dbe.dual_scalar = 0 return dbe
def d2_e2_mapping(dim, bas_aa, bas_ab, measured_tpdm_aa, measured_tpdm_bb, measured_tpdm_ab): """ Generate constraints such that the error matrix and the d2 matrices look like the measured matrices :param dim: spatial basis dimension :param measured_tpdm_aa: two-marginal of alpha-alpha spins :param measured_tpdm_bb: two-marginal of beta-beta spins :param measured_tpdm_ab: two-marginal of alpha-beta spins :return: """ db = DualBasis() # first constrain the aa-matrix aa_dim = dim * (dim - 1) / 2 ab_dim = dim**2 # map the aa matrix to the measured_tpdm_aa for p, q, r, s in product(range(dim), repeat=4): if p < q and r < s and bas_aa[(p, q)] <= bas_aa[(r, s)]: dbe = DualBasisElement() # two elements of D2aa dbe.add_element('cckk_aa', (p, q, r, s), 0.5) dbe.add_element('cckk_aa', (r, s, p, q), 0.5) # four elements of the E2aa dbe.add_element('cckk_me_aa', (bas_aa[(p, q)] + aa_dim, bas_aa[(r, s)]), 0.25) dbe.add_element('cckk_me_aa', (bas_aa[(r, s)] + aa_dim, bas_aa[(p, q)]), 0.25) dbe.add_element('cckk_me_aa', (bas_aa[(p, q)], bas_aa[(r, s)] + aa_dim), 0.25) dbe.add_element('cckk_me_aa', (bas_aa[(r, s)], bas_aa[(p, q)] + aa_dim), 0.25) dbe.dual_scalar = measured_tpdm_aa[bas_aa[(p, q)], bas_aa[(r, s)]].real dbe.simplify() # construct the dbe for constraining the [0, 0] orthant to the idenity matrix dbe_identity_aa = DualBasisElement() if bas_aa[(p, q)] == bas_aa[(r, s)]: dbe_identity_aa.add_element('cckk_me_aa', (bas_aa[(p, q)], bas_aa[(r, s)]), 1.0) dbe_identity_aa.dual_scalar = 1.0 else: dbe_identity_aa.add_element('cckk_me_aa', (bas_aa[(p, q)], bas_aa[(r, s)]), 0.5) dbe_identity_aa.add_element('cckk_me_aa', (bas_aa[(r, s)], bas_aa[(p, q)]), 0.5) dbe_identity_aa.dual_scalar = 0.0 db += dbe db += dbe_identity_aa # map the bb matrix to the measured_tpdm_bb for p, q, r, s in product(range(dim), repeat=4): if p < q and r < s and bas_aa[(p, q)] <= bas_aa[(r, s)]: dbe = DualBasisElement() # two elements of D2bb dbe.add_element('cckk_bb', (p, q, r, s), 0.5) dbe.add_element('cckk_bb', (r, s, p, q), 0.5) # four elements of the E2bb dbe.add_element('cckk_me_bb', (bas_aa[(p, q)] + aa_dim, bas_aa[(r, s)]), 0.25) dbe.add_element('cckk_me_bb', (bas_aa[(r, s)] + aa_dim, bas_aa[(p, q)]), 0.25) dbe.add_element('cckk_me_bb', (bas_aa[(p, q)], bas_aa[(r, s)] + aa_dim), 0.25) dbe.add_element('cckk_me_bb', (bas_aa[(r, s)], bas_aa[(p, q)] + aa_dim), 0.25) dbe.dual_scalar = measured_tpdm_bb[bas_aa[(p, q)], bas_aa[(r, s)]].real dbe.simplify() # construct the dbe for constraining the [0, 0] orthant to the idenity matrix dbe_identity_bb = DualBasisElement() if bas_aa[(p, q)] == bas_aa[(r, s)]: dbe_identity_bb.add_element('cckk_me_bb', (bas_aa[(p, q)], bas_aa[(r, s)]), 1.0) dbe_identity_bb.dual_scalar = 1.0 else: dbe_identity_bb.add_element('cckk_me_bb', (bas_aa[(p, q)], bas_aa[(r, s)]), 0.5) dbe_identity_bb.add_element('cckk_me_bb', (bas_aa[(r, s)], bas_aa[(p, q)]), 0.5) dbe_identity_bb.dual_scalar = 0.0 db += dbe db += dbe_identity_bb # map the ab matrix to the measured_tpdm_ab for p, q, r, s in product(range(dim), repeat=4): if bas_ab[(p, q)] <= bas_ab[(r, s)]: dbe = DualBasisElement() # two elements of D2ab dbe.add_element('cckk_ab', (p, q, r, s), 0.5) dbe.add_element('cckk_ab', (r, s, p, q), 0.5) # four elements of the E2ab dbe.add_element('cckk_me_ab', (bas_ab[(p, q)] + ab_dim, bas_ab[(r, s)]), 0.25) dbe.add_element('cckk_me_ab', (bas_ab[(r, s)] + ab_dim, bas_ab[(p, q)]), 0.25) dbe.add_element('cckk_me_ab', (bas_ab[(p, q)], bas_ab[(r, s)] + ab_dim), 0.25) dbe.add_element('cckk_me_ab', (bas_ab[(r, s)], bas_ab[(p, q)] + ab_dim), 0.25) dbe.dual_scalar = measured_tpdm_ab[bas_ab[(p, q)], bas_ab[(r, s)]].real dbe.simplify() # construct the dbe for constraining the [0, 0] orthant to the idenity matrix dbe_identity_ab = DualBasisElement() if bas_ab[(p, q)] == bas_ab[(r, s)]: dbe_identity_ab.add_element('cckk_me_ab', (bas_ab[(p, q)], bas_ab[(r, s)]), 1.0) dbe_identity_ab.dual_scalar = 1.0 else: dbe_identity_ab.add_element('cckk_me_ab', (bas_ab[(p, q)], bas_ab[(r, s)]), 0.5) dbe_identity_ab.add_element('cckk_me_ab', (bas_ab[(r, s)], bas_ab[(p, q)]), 0.5) dbe_identity_ab.dual_scalar = 0.0 db += dbe db += dbe_identity_ab return db
def g2d2map_ab(p, q, r, s, key, factor=1.0): dbe = DualBasisElement() if key == 'ab': if q == s: dbe.add_element('ck_' + key[0], (p, r), krond[q, s] * factor) dbe.add_element('cckk_' + key, (p, s, r, q), -1.0 * factor) elif key == 'ba': if q == s: dbe.add_element('ck_' + key[0], (p, r), krond[q, s] * factor) dbe.add_element('cckk_ab', (s, p, q, r), -1.0 * factor) else: raise TypeError("I only accept ab or ba blocks") dbe.add_element('ckck_' + key, (p, q, r, s), -1.0 * factor) dbe.dual_scalar = 0.0 return dbe
def d2q2element_ab(p, q, r, s, factor): dbe = DualBasisElement() if q == s: dbe.add_element('ck_a', (p, r), factor) if p == r: dbe.add_element('kc_b', (s, q), -factor) dbe.add_element('kkcc_ab', (r, s, p, q), factor) dbe.add_element('cckk_ab', (p, q, r, s), -factor) # dbe.dual_scalar = -krond[q, s]*krond[p, r] * factor dbe.dual_scalar = 0 return dbe
def d2bb_d1b_mapping(dim, Nb): """ Map the d2_spin-adapted 2-RDM to the D1 rdm :param Nb: number of beta electrons :param dim: :return: """ db = DualBasis() for i in range(dim): for j in range(i, dim): dbe = DualBasisElement() for r in range(dim): # Not in the basis because always zero if i == r or j == r: continue else: sir = 1 if i < r else -1 sjr = 1 if j < r else -1 ir_pair = (i, r) if i < r else (r, i) jr_pair = (j, r) if j < r else (r, j) if i == j: dbe.add_element( 'cckk_bb', (ir_pair[0], ir_pair[1], jr_pair[0], jr_pair[1]), sir * sjr) else: dbe.add_element( 'cckk_bb', (ir_pair[0], ir_pair[1], jr_pair[0], jr_pair[1]), sir * sjr * 0.5) dbe.add_element( 'cckk_bb', (jr_pair[0], jr_pair[1], ir_pair[0], ir_pair[1]), sir * sjr * 0.5) dbe.add_element('ck_b', (i, j), -0.5 * (Nb - 1)) dbe.add_element('ck_b', (j, i), -0.5 * (Nb - 1)) dbe.dual_scalar = 0 # dbe.simplify() db += dbe return db
def s_representability_d2ab_to_d2aa(dim): """ Constraint the antisymmetric part of the alpha-beta matrix to be equal to the aa and bb components if a singlet :param dim: :return: """ sma = dim * (dim - 1) // 2 sms = dim * (dim + 1) // 2 uadapt, d2ab_abas, d2ab_abas_rev, d2ab_sbas, d2ab_sbas_rev = \ gen_trans_2rdm(dim**2, dim) d2ab_bas = {} d2aa_bas = {} cnt_ab = 0 cnt_aa = 0 for p, q in product(range(dim), repeat=2): d2ab_bas[(p, q)] = cnt_ab cnt_ab += 1 if p < q: d2aa_bas[(p, q)] = cnt_aa cnt_aa += 1 d2ab_rev = dict(zip(d2ab_bas.values(), d2ab_bas.keys())) d2aa_rev = dict(zip(d2aa_bas.values(), d2aa_bas.keys())) assert uadapt.shape == (int(dim)**2, int(dim)**2) dbe_list = [] for r, s in product(range(dim * (dim - 1) // 2), repeat=2): if r < s: dbe = DualBasisElement() # lower triangle i, j = d2aa_rev[r] k, l = d2aa_rev[s] # aa element should equal the triplet block aa dbe.add_element('cckk_aa', (i, j, k, l), -0.5) coeff_mat = uadapt[:, [r]] @ uadapt[:, [s]].T for p, q in product(range(coeff_mat.shape[0]), repeat=2): if not np.isclose(coeff_mat[p, q], 0): ii, jj = d2ab_rev[p] kk, ll = d2ab_rev[q] dbe.add_element('cckk_ab', (ii, jj, kk, ll), 0.5 * coeff_mat[p, q]) # upper triangle . Hermitian conjugate dbe.add_element('cckk_aa', (k, l, i, j), -0.5) coeff_mat = uadapt[:, [s]] @ uadapt[:, [r]].T for p, q in product(range(coeff_mat.shape[0]), repeat=2): if not np.isclose(coeff_mat[p, q], 0): ii, jj = d2ab_rev[p] kk, ll = d2ab_rev[q] dbe.add_element('cckk_ab', (ii, jj, kk, ll), 0.5 * coeff_mat[p, q]) dbe.simplify() dbe_list.append(dbe) elif r == s: i, j = d2aa_rev[r] k, l = d2aa_rev[s] dbe = DualBasisElement() # aa element should equal the triplet block aa dbe.add_element('cckk_aa', (i, j, k, l), -1.0) coeff_mat = uadapt[:, [r]] @ uadapt[:, [s]].T for p, q in product(range(coeff_mat.shape[0]), repeat=2): if not np.isclose(coeff_mat[p, q], 0): ii, jj = d2ab_rev[p] kk, ll = d2ab_rev[q] dbe.add_element('cckk_ab', (ii, jj, kk, ll), coeff_mat[p, q]) dbe.simplify() dbe_list.append(dbe) return DualBasis(elements=dbe_list)
def d2_to_t1(dim): """ Generate the dual basis elements for mapping d2 and d1 to the T1-matrix The T1 condition is the sum of three-marginals T1 = <p^ q^ r^ i j k> i j k p^ q^ r^> in such a fashion that any triples component cancels out. T1 will be represented over antisymmeterized basis functions to save a significant amount of space :param dim: spin-orbital basis dimension :return: """ db = [] # DualBasis() for p, q, r, i, j, k in product(range(dim), repeat=6): # if (p * dim**2 + q * dim + r <= i * dim**2 + j * dim + k): print(p, q, r, i, j, k) dbe = DualBasisElement() dbe.dual_scalar -= ( (-1.0) * kdelta(i, p) * kdelta(j, q) * kdelta(k, r) + (1.0) * kdelta(i, p) * kdelta(j, r) * kdelta(k, q) + (1.0) * kdelta(i, q) * kdelta(j, p) * kdelta(k, r) + (-1.0) * kdelta(i, q) * kdelta(j, r) * kdelta(k, p) + (-1.0) * kdelta(i, r) * kdelta(j, p) * kdelta(k, q) + (1.0) * kdelta(i, r) * kdelta(j, q) * kdelta(k, p)) dbe.add_element('ck', (r, k), (1.0) * kdelta(i, p) * kdelta(j, q)) dbe.add_element('ck', (q, k), (-1.0) * kdelta(i, p) * kdelta(j, r)) dbe.add_element('ck', (r, j), (-1.0) * kdelta(i, p) * kdelta(k, q)) dbe.add_element('ck', (q, j), (1.0) * kdelta(i, p) * kdelta(k, r)) dbe.add_element('ck', (r, k), (-1.0) * kdelta(i, q) * kdelta(j, p)) dbe.add_element('ck', (p, k), (1.0) * kdelta(i, q) * kdelta(j, r)) dbe.add_element('ck', (r, j), (1.0) * kdelta(i, q) * kdelta(k, p)) dbe.add_element('ck', (p, j), (-1.0) * kdelta(i, q) * kdelta(k, r)) dbe.add_element('ck', (q, k), (1.0) * kdelta(i, r) * kdelta(j, p)) dbe.add_element('ck', (p, k), (-1.0) * kdelta(i, r) * kdelta(j, q)) dbe.add_element('ck', (q, j), (-1.0) * kdelta(i, r) * kdelta(k, p)) dbe.add_element('ck', (p, j), (1.0) * kdelta(i, r) * kdelta(k, q)) dbe.add_element('ck', (r, i), (1.0) * kdelta(j, p) * kdelta(k, q)) dbe.add_element('ck', (q, i), (-1.0) * kdelta(j, p) * kdelta(k, r)) dbe.add_element('ck', (r, i), (-1.0) * kdelta(j, q) * kdelta(k, p)) dbe.add_element('ck', (p, i), (1.0) * kdelta(j, q) * kdelta(k, r)) dbe.add_element('ck', (q, i), (1.0) * kdelta(j, r) * kdelta(k, p)) dbe.add_element('ck', (p, i), (-1.0) * kdelta(j, r) * kdelta(k, q)) dbe.add_element('cckk', (q, r, j, k), (1.0) * kdelta(i, p)) dbe.add_element('cckk', (p, r, j, k), (-1.0) * kdelta(i, q)) dbe.add_element('cckk', (p, q, j, k), (1.0) * kdelta(i, r)) dbe.add_element('cckk', (q, r, i, k), (-1.0) * kdelta(j, p)) dbe.add_element('cckk', (p, r, i, k), (1.0) * kdelta(j, q)) dbe.add_element('cckk', (p, q, i, k), (-1.0) * kdelta(j, r)) dbe.add_element('cckk', (q, r, i, j), (1.0) * kdelta(k, p)) dbe.add_element('cckk', (p, r, i, j), (-1.0) * kdelta(k, q)) dbe.add_element('cckk', (p, q, i, j), (1.0) * kdelta(k, r)) dbe.add_element('t1', (p, q, r, i, j, k), -1.0) dbe.simplify() db.append(dbe) return DualBasis(elements=db)
def trace_d2_ab(dim, Na, Nb): dbe = DualBasisElement() for i, j in product(range(dim), repeat=2): dbe.add_element('cckk_ab', (i, j, i, j), 1.0) dbe.dual_scalar = Na * Nb return dbe
def d2q2element(p, q, r, s, factor, tname_d1_1, tname_d2, tname_q2): # , spin_string): """ # ( 1.00000) cre(r) cre(s) des(q) des(p) # ( 1.00000) kdelta(p,s) cre(r) des(q) # ( -1.00000) kdelta(p,r) cre(s) des(q) # ( -1.00000) kdelta(q,s) cre(r) des(p) # ( 1.00000) kdelta(q,r) cre(s) des(p) # ( -1.00000) kdelta(p,s) kdelta(q,r) # ( 1.00000) kdelta(p,r) kdelta(q,s) """ dbe = DualBasisElement() dbe.add_element(tname_q2, (p, q, r, s), -factor) dbe.add_element(tname_d2, (r, s, p, q), factor) if p == s: dbe.add_element(tname_d1_1, (r, q), factor) if p == r: dbe.add_element(tname_d1_1, (s, q), -factor) if q == s: dbe.add_element(tname_d1_1, (r, p), -factor) if q == r: dbe.add_element(tname_d1_1, (s, p), factor) # remember the negative sign because AX = b dbe.dual_scalar = -factor * (krond[p, r] * krond[q, s] - krond[p, s] * krond[q, r]) # dbe.add_element('kkcc_' + spin_string + spin_string, (r, s, p, q), factor) # if q == s: # dbe.add_element('ck_' + spin_string, (p, r), factor) # if p == s: # dbe.add_element('ck_' + spin_string, (q, r), -factor) # if q == r: # dbe.add_element('kc_' + spin_string, (s, p), factor) # if p == r: # dbe.add_element('kc_' + spin_string, (s, q), -factor) # dbe.add_element('cckk_' + spin_string + spin_string, (p, q, r, s), -factor) # dbe.dual_scalar = 0 return dbe
def d2_to_t1_matrix(dim): """ Generate the dual basis elements for mapping d2 and d1 to the T1-matrix The T1 condition is the sum of three-marginals T1 = <p^ q^ r^ i j k> i j k p^ q^ r^> in such a fashion that any triples component cancels out. T1 will be represented over antisymmeterized basis functions to save a significant amount of space :param dim: spin-orbital basis dimension :return: """ db = [] # DualBasis() for p, q, r, i, j, k in product(range(dim), repeat=6): if (p * dim**2 + q * dim + r <= i * dim**2 + j * dim + k and p != q and q != r and p != r and i != j and j != k and i != k): print(p, q, r, i, j, k) dbe = DualBasisElement() if np.isclose(p * dim**2 + q * dim + r, i * dim**2 + j * dim + k): # diagonal term should be treated once dbe.dual_scalar -= t1_dual_scalar(p, q, r, i, j, k) for element in t1_opdm_component(p, q, r, i, j, k): # dbe.join_elements(element) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0]) for element in t1_tpdm_component(p, q, r, i, j, k): # dbe.join_elements(element) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0]) dbe.add_element('t1', (p, q, r, i, j, k), -1.0) else: dbe.dual_scalar -= t1_dual_scalar(p, q, r, i, j, k) * 0.5 for element in t1_opdm_component(p, q, r, i, j, k): # dbe.join_elements(element) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0] * 0.5) for element in t1_tpdm_component(p, q, r, i, j, k): # dbe.join_elements(element) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0] * 0.5) dbe.dual_scalar -= t1_dual_scalar(i, j, k, p, q, r) * 0.5 for element in t1_opdm_component(i, j, k, p, q, r): # dbe.join_elements(element) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0] * 0.5) for element in t1_tpdm_component(i, j, k, p, q, r): # dbe.join_elements(element) dbe.add_element(element.primal_tensors_names[0], element.primal_elements[0], element.primal_coeffs[0] * 0.5) # This is the weirdest part right here! # we reference everything else in tensor ordering but then this is # put into a weird matrix order. The way it works is that it # just groups them dbe.add_element('t1', (p, q, r, i, j, k), -0.5) dbe.add_element('t1', (i, j, k, p, q, r), -0.5) dbe.simplify() db.append(dbe) return DualBasis(elements=db)