def test_varsh_872_4(nuclear: NuclearBogoliubovDrudge): """Test simplification based on Varshalovich 8.7.2 Eq (4).""" dr = nuclear c, gamma, c_prm, gamma_prm = symbols('c gamma cprm gammaprm', integer=True) a, alpha, b, beta = symbols('a alpha b beta', integer=True) m_range = Range('m') sums = [ (alpha, m_range[-a, a + 1]), (beta, m_range[-b, b + 1]) ] amp = CG(a, alpha, b, beta, c, gamma) * CG( a, alpha, b, beta, c_prm, gamma_prm ) # Make sure that the pattern matching works in any way the summations are # written. for sums_i in [sums, reversed(sums)]: tensor = dr.sum(*sums_i, amp) res = tensor.simplify_am() assert res.n_terms == 1 term = res.local_terms[0] assert len(term.sums) == 0 assert term.amp == KroneckerDelta( c, c_prm ) * KroneckerDelta(gamma, gamma_prm)
def test_varsh_911_8(nuclear: NuclearBogoliubovDrudge): """Test simplification based on the rule in Varshalovich 9.1.1 Eq (8). """ dr = nuclear j, m, j12, m12, j2, m2, j1, m1, j_prm, m_prm, j23, m23, j3, m3 = symbols( 'j m j12 m12 j2 m2 j1 m1 jprm mprm j23 m23 j3 m3', integer=True ) m_range = Range('m') sums = [(m_i, m_range[-j_i, j_i + 1]) for m_i, j_i in [ (m1, j1), (m2, j2), (m3, j3), (m12, j12), (m23, j23) ]] amp = CG(j12, m12, j3, m3, j, m) * CG(j1, m1, j2, m2, j12, m12) * CG( j1, m1, j23, m23, j_prm, m_prm ) * CG(j2, m2, j3, m3, j23, m23) expected = ( KroneckerDelta(j, j_prm) * KroneckerDelta(m, m_prm) * (-1) ** (j1 + j2 + j3 + j) * sqrt(2 * j12 + 1) * sqrt(2 * j23 + 1) * Wigner6j(j1, j2, j12, j3, j, j23) ) # For performance reason, just test a random arrangement of the summations. random.shuffle(sums) tensor = dr.sum(*sums, amp) res = tensor.deep_simplify().merge() assert res.n_terms == 1 term = res.local_terms[0] assert len(term.sums) == 0 assert len(term.vecs) == 0 assert (term.amp - expected).simplify() == 0
def __init__(self, c, hyperparameter): """Initialize the Hopfield network. Args: n: number of cities d: distances between cities """ self.n = c.shape[0] self.c = c # hyperparameter represents how much you weigh the distance term relative to constraint term self.hyperparameter = hyperparameter # weights between neurons self.w = np.zeros((self.n, self.n, self.n, self.n)) for x in range(self.n): for i in range(self.n): for y in range(self.n): for j in range(self.n): self.w[x][i][y][j] = -2 * (KroneckerDelta(x, y) + KroneckerDelta(i, j) + self.d[x][y] * KroneckerDelta((i + 1) % self.n, j) * self.hyperparameter) # biases to neurons self.b = np.zeros((self.n, self.n)) for x in range(self.n): for i in range(self.n): self.b[x][i] = 4 # states of neurons self.s = np.random.choice([0, 1], (self.n, self.n))
def test_varsh_872_5(nuclear: NuclearBogoliubovDrudge): """Test simplification based on the rule in Varshalovich 8.7.2 Eq (5). """ dr = nuclear a, alpha, b, beta, b_prm, beta_prm = symbols( 'a alpha b beta bprm betaprm', integer=True ) c, gamma = symbols('c gamma', integer=True) sums = [ (alpha, Range('m', -a, a + 1)), (gamma, Range('M', -c, c + 1)) ] amp = CG(a, alpha, b, beta, c, gamma) * CG( a, alpha, b_prm, beta_prm, c, gamma ) expected = ( KroneckerDelta(b, b_prm) * KroneckerDelta(beta, beta_prm) * (2 * c + 1) / (2 * b + 1) ) for sums_i in [sums, reversed(sums)]: tensor = dr.sum(*sums_i, amp) res = tensor.deep_simplify().merge() assert res.n_terms == 1 term = res.local_terms[0] assert len(term.sums) == 0 assert len(term.vecs) == 0 assert (term.amp - expected).simplify() == 0
def generators(self, indexed=False) -> list[Union[Matrix, Tuple[Matrix, tuple]]]: """Generators for SO(N). Args: indexed (bool, Optional): For N > 3, there exists a naming scheme for generators. If True returns a tuple of the matrix and its (m,n) index. Returns: list[Union[Matrix, Tuple[Matrix, tuple]]]: list of (mathematical) generators Sources: - http://www.astro.sunysb.edu/steinkirch/books/group.pdf """ results = [] for m in range(self.dimension): for n in range(m): mat = zeros(self.dimension) for i in range(self.dimension): for j in range(self.dimension): mat[i, j] = -I * ( KroneckerDelta(m, i) * KroneckerDelta(n, j) - KroneckerDelta(m, j) * KroneckerDelta(n, i)) results.append((mat, (m, n)) if indexed else mat) if indexed: return sorted(results, key=lambda y: y[1]) return results
def _swap_ug(vec1: Vec, vec2: Vec, depth=None, *,spec: _UGSpec): """Swap two vectors based on the commutation rules for Unitary Group generators. Here, we introduce an additional input parameter 'depth' which is never specified by the user. Rather, it is put to make use os the anti-symmetric nature of the commutation relations and make the function def compact. """ if depth is None: depth = 1 char1, indice1, key1 = _parse_vec_uga(vec1,spec) char2, indice2, key2 = _parse_vec_uga(vec2,spec) p = indice1[0] q = indice1[1] r = indice2[0] s = indice2[1] if p != r: if p is min(p,r,key=default_sort_key): return None elif r is min(p,r,key=default_sort_key): expr = KroneckerDelta(q,r)*spec.uga[p,s] - KroneckerDelta(p,s)*spec.uga[r,q] return _UNITY, expr else: return None elif p == r: if q is min(q,s,key=default_sort_key): return None elif s is min(q,s,key=default_sort_key): expr = KroneckerDelta(q,r)*spec.uga[p,s] - KroneckerDelta(p,s)*spec.uga[r,q] return _UNITY, expr else: return None else: assert False
def test_Sum_doit(): assert Sum(n * Integral(a**2), (n, 0, 2)).doit() == a**3 assert Sum(n*Integral(a**2), (n, 0, 2)).doit(deep=False) == \ 3*Integral(a**2) assert summation(n * Integral(a**2), (n, 0, 2)) == 3 * Integral(a**2) # test nested sum evaluation s = Sum(Sum(Sum(2, (z, 1, n + 1)), (y, x + 1, n)), (x, 1, n)) assert 0 == (s.doit() - n * (n + 1) * (n - 1)).factor() assert Sum(Sum(KroneckerDelta(m, n), (m, 1, 3)), (n, 1, 3)).doit() == 3 assert Sum(Sum(KroneckerDelta(k, m), (m, 1, 3)), (n, 1, 3)).doit() == \ 3*Piecewise((1, And(S(1) <= k, k <= 3)), (0, True)) assert Sum(f(n)*Sum(KroneckerDelta(m, n), (m, 0, oo)), (n, 1, 3)).doit() == \ f(1) + f(2) + f(3) assert Sum(f(n)*Sum(KroneckerDelta(m, n), (m, 0, oo)), (n, 1, oo)).doit() == \ Sum(Piecewise((f(n), And(Le(0, n), n < oo)), (0, True)), (n, 1, oo)) l = Symbol('l', integer=True, positive=True) assert Sum(f(l)*Sum(KroneckerDelta(m, l), (m, 0, oo)), (l, 1, oo)).doit() == \ Sum(f(l), (l, 1, oo)) # issue 2597 nmax = symbols('N', integer=True, positive=True) pw = Piecewise((1, And(S(1) <= n, n <= nmax)), (0, True)) assert Sum(pw, (n, 1, nmax)).doit() == Sum(pw, (n, 1, nmax))
def test_matrixelement_diff(): dexpr = diff((D*w)[k,0], w[p,0]) assert w[k, p].diff(w[k, p]) == 1 assert w[k, p].diff(w[0, 0]) == KroneckerDelta(0, k)*KroneckerDelta(0, p) assert str(dexpr) == "Sum(KroneckerDelta(_i_1, p)*D[k, _i_1], (_i_1, 0, n - 1))" assert str(dexpr.doit()) == 'Piecewise((D[k, p], (p >= 0) & (p <= n - 1)), (0, True))'
def test_complicated_derivative_with_Indexed(): x, y = symbols("x,y", cls=IndexedBase) sigma = symbols("sigma") i, j, k = symbols("i,j,k") m0, m1, m2, m3, m4, m5 = symbols("m0:6") f = Function("f") expr = f((x[i] - y[i])**2 / sigma) _xi_1 = symbols("xi_1", cls=Dummy) assert expr.diff(x[m0]).dummy_eq( (x[i] - y[i])*KroneckerDelta(i, m0)*\ 2*Subs( Derivative(f(_xi_1), _xi_1), (_xi_1,), ((x[i] - y[i])**2/sigma,) )/sigma ) assert expr.diff(x[m0]).diff(x[m1]).dummy_eq( 2*KroneckerDelta(i, m0)*\ KroneckerDelta(i, m1)*Subs( Derivative(f(_xi_1), _xi_1), (_xi_1,), ((x[i] - y[i])**2/sigma,) )/sigma + \ 4*(x[i] - y[i])**2*KroneckerDelta(i, m0)*KroneckerDelta(i, m1)*\ Subs( Derivative(f(_xi_1), _xi_1, _xi_1), (_xi_1,), ((x[i] - y[i])**2/sigma,) )/sigma**2 )
def test_matrixelement_diff(): dexpr = diff((D*w)[k,0], w[p,0]) assert w[k, p].diff(w[k, p]) == 1 assert w[k, p].diff(w[0, 0]) == KroneckerDelta(0, k, (0, n-1))*KroneckerDelta(0, p, (0, 0)) _i_1 = Dummy("_i_1") assert dexpr.dummy_eq(Sum(KroneckerDelta(_i_1, p, (0, n-1))*D[k, _i_1], (_i_1, 0, n - 1))) assert dexpr.doit() == D[k, p]
def _eval_derivative(self, v): if not isinstance(v, MatrixElement): return S.Zero if self.args[0] != v.args[0]: return S.Zero from sympy import KroneckerDelta return KroneckerDelta(self.args[1], v.args[1])*KroneckerDelta(self.args[2], v.args[2])
def D_Ddag_comm_expr(a, b, c, d): del_ac = KroneckerDelta(a, c) del_bd = KroneckerDelta(b, d) b_ac = beta[a, c] b_db = beta[d, b] exprn = del_ac*del_bd*(spec.cartan[a]-spec.cartan[b]) + \ del_bd*b_ac*( eta[a]*spec.lower[a,c] - eta[c]*spec.raise_[a,c]) +\ del_ac*b_db*( eta[d]*spec.lower[b,d] - eta[b]*spec.raise_[b,d]) exprn = eta[a] * eta[c] * exprn return exprn
def test_matrixelement_diff(): dexpr = diff((D*w)[k,0], w[p,0]) assert w[k, p].diff(w[k, p]) == 1 assert w[k, p].diff(w[0, 0]) == KroneckerDelta(0, k)*KroneckerDelta(0, p) assert str(dexpr) == "Sum(KroneckerDelta(_i_1, p)*D[k, _i_1], (_i_1, 0, n - 1))" assert str(dexpr.doit()) == 'Piecewise((D[k, p], (p >= 0) & (p <= n - 1)), (0, True))' # TODO: bug with .dummy_eq( ), the previous 2 lines should be replaced by: return # stop eval _i_1 = Dummy("_i_1") assert dexpr.dummy_eq(Sum(KroneckerDelta(_i_1, p)*D[k, _i_1], (_i_1, 0, n - 1))) assert dexpr.doit().dummy_eq(Piecewise((D[k, p], (p >= 0) & (p <= n - 1)), (0, True)))
def test_DiagonalMatrix(): x = MatrixSymbol('x', n, m) D = DiagonalMatrix(x) assert D.diagonal_length is None assert D.shape == (n, m) x = MatrixSymbol('x', n, n) D = DiagonalMatrix(x) assert D.diagonal_length == n assert D.shape == (n, n) assert D[1, 2] == 0 assert D[1, 1] == x[1, 1] i = Symbol('i') j = Symbol('j') x = MatrixSymbol('x', 3, 3) ij = DiagonalMatrix(x)[i, j] assert ij != 0 assert ij.subs({i:0, j:0}) == x[0, 0] assert ij.subs({i:0, j:1}) == 0 assert ij.subs({i:1, j:1}) == x[1, 1] assert ask(Q.diagonal(D)) # affirm that D is diagonal x = MatrixSymbol('x', n, 3) D = DiagonalMatrix(x) assert D.diagonal_length == 3 assert D.shape == (n, 3) assert D[2, m] == KroneckerDelta(2, m)*x[2, m] assert D[3, m] == 0 raises(IndexError, lambda: D[m, 3]) x = MatrixSymbol('x', 3, n) D = DiagonalMatrix(x) assert D.diagonal_length == 3 assert D.shape == (3, n) assert D[m, 2] == KroneckerDelta(m, 2)*x[m, 2] assert D[m, 3] == 0 raises(IndexError, lambda: D[3, m]) x = MatrixSymbol('x', n, m) D = DiagonalMatrix(x) assert D.diagonal_length is None assert D.shape == (n, m) assert D[m, 4] != 0 x = MatrixSymbol('x', 3, 4) assert [DiagonalMatrix(x)[i] for i in range(12)] == [ x[0, 0], 0, 0, 0, 0, x[1, 1], 0, 0, 0, 0, x[2, 2], 0] # shape is retained, issue 12427 assert ( DiagonalMatrix(MatrixSymbol('x', 3, 4))* DiagonalMatrix(MatrixSymbol('x', 4, 2))).shape == (3, 2)
def test_DiagonalizeVector(): x = MatrixSymbol('x', n, 1) d = DiagonalizeVector(x) assert d.shape == (n, n) assert d[0, 1] == 0 assert d[0, 0] == x[0, 0] a = MatrixSymbol('a', 1, 1) d = diagonalize_vector(a) assert isinstance(d, MatrixSymbol) assert a == d assert diagonalize_vector(Identity(3)) == Identity(3) assert DiagonalizeVector(Identity(3)).doit() == Identity(3) assert isinstance(DiagonalizeVector(Identity(3)), DiagonalizeVector) # A diagonal matrix is equal to its transpose: assert DiagonalizeVector(x).T == DiagonalizeVector(x) assert diagonalize_vector(x.T) == DiagonalizeVector(x) dx = DiagonalizeVector(x) assert dx[0, 0] == x[0, 0] assert dx[1, 1] == x[1, 0] assert dx[0, 1] == 0 assert dx[0, m] == x[0, 0] * KroneckerDelta(0, m) z = MatrixSymbol('z', 1, n) dz = DiagonalizeVector(z) assert dz[0, 0] == z[0, 0] assert dz[1, 1] == z[0, 1] assert dz[0, 1] == 0 assert dz[0, m] == z[0, m] * KroneckerDelta(0, m) v = MatrixSymbol('v', 3, 1) dv = DiagonalizeVector(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[1, 0], 0], [0, 0, v[2, 0]], ]) v = MatrixSymbol('v', 1, 3) dv = DiagonalizeVector(v) assert dv.as_explicit() == Matrix([ [v[0, 0], 0, 0], [0, v[0, 1], 0], [0, 0, v[0, 2]], ]) dv = DiagonalizeVector(3 * v) assert dv.args == (3 * v, ) assert dv.doit() == 3 * DiagonalizeVector(v) assert isinstance(dv.doit(), MatMul)
def _eval_derivative(self, v): if not isinstance(v, MatrixElement): from sympy import MatrixBase if isinstance(self.parent, MatrixBase): return self.parent.diff(v)[self.i, self.j] return S.Zero if self.args[0] != v.args[0]: return S.Zero from sympy import KroneckerDelta return KroneckerDelta(self.args[1], v.args[1]) * KroneckerDelta( self.args[2], v.args[2])
def test_up_down_enum_symbs(): """Test the desired mathematical properties of enumeration symbols.""" for i in [UP, DOWN]: assert KroneckerDelta(i, i) == 1 assert KroneckerDelta(UP, DOWN) == 0 assert KroneckerDelta(DOWN, UP) == 0 sigma = symbols('sigma') for i in [UP, DOWN]: assert KroneckerDelta(i, sigma) != 0 assert KroneckerDelta(sigma, i) != 0
def test_arrayexpr_convert_index_to_array_support_function(): expr = M[i, j] assert _convert_indexed_to_array(expr) == (M, (i, j)) expr = M[i, j] * N[k, l] assert _convert_indexed_to_array(expr) == (ArrayTensorProduct(M, N), (i, j, k, l)) expr = M[i, j] * N[j, k] assert _convert_indexed_to_array(expr) == (ArrayDiagonal( ArrayTensorProduct(M, N), (1, 2)), (i, k, j)) expr = Sum(M[i, j] * N[j, k], (j, 0, k - 1)) assert _convert_indexed_to_array(expr) == (ArrayContraction( ArrayTensorProduct(M, N), (1, 2)), (i, k)) expr = M[i, j] + N[i, j] assert _convert_indexed_to_array(expr) == (ArrayAdd(M, N), (i, j)) expr = M[i, j] + N[j, i] assert _convert_indexed_to_array(expr) == (ArrayAdd( M, PermuteDims(N, Permutation([1, 0]))), (i, j)) expr = M[i, j] + M[j, i] assert _convert_indexed_to_array(expr) == (ArrayAdd( M, PermuteDims(M, Permutation([1, 0]))), (i, j)) expr = (M * N * P)[i, j] assert _convert_indexed_to_array(expr) == (ArrayContraction( ArrayTensorProduct(M, N, P), (1, 2), (3, 4)), (i, j)) expr = expr.function # Disregard summation in previous expression ret1, ret2 = _convert_indexed_to_array(expr) assert ret1 == ArrayDiagonal(ArrayTensorProduct(M, N, P), (1, 2), (3, 4)) assert str(ret2) == "(i, j, _i_1, _i_2)" expr = KroneckerDelta(i, j) * M[i, k] assert _convert_indexed_to_array(expr) == (M, ({i, j}, k)) expr = KroneckerDelta(i, j) * KroneckerDelta(j, k) * M[i, l] assert _convert_indexed_to_array(expr) == (M, ({i, j, k}, l)) expr = KroneckerDelta(j, k) * (M[i, j] * N[k, l] + N[i, j] * M[k, l]) assert _convert_indexed_to_array(expr) == (ArrayDiagonal( ArrayAdd( ArrayTensorProduct(M, N), PermuteDims(ArrayTensorProduct(M, N), Permutation(0, 2)(1, 3))), (1, 2)), (i, l, frozenset({j, k}))) expr = KroneckerDelta(j, m) * KroneckerDelta( m, k) * (M[i, j] * N[k, l] + N[i, j] * M[k, l]) assert _convert_indexed_to_array(expr) == (ArrayDiagonal( ArrayAdd( ArrayTensorProduct(M, N), PermuteDims(ArrayTensorProduct(M, N), Permutation(0, 2)(1, 3))), (1, 2)), (i, l, frozenset({j, m, k}))) expr = KroneckerDelta(i, j) * KroneckerDelta(j, k) * KroneckerDelta( k, m) * M[i, 0] * KroneckerDelta(m, n) assert _convert_indexed_to_array(expr) == (M, ({i, j, k, m, n}, 0)) expr = M[i, i] assert _convert_indexed_to_array(expr) == (ArrayDiagonal(M, (0, 1)), (i, ))
def func(x, y, z1, z2, mr, m, z3, z4, mr1, m1): return KroneckerDelta(x, 1) * ( (complex(z1, z2)) / (y + (complex(mr, m))**2) + (complex(z1, -z2)) / (y + (complex(mr, -m))**2) + (complex(z3, z4)) / (y + (complex(mr1, m1))**2) + (complex(z3, -z4)) / (y + (complex(mr1, -m1))**2)) + KroneckerDelta(x, 2) * ( ((complex(z1, z2)) * (complex(mr, m))) / (y + (complex(mr, m))**2) + ((complex(z1, -z2)) * (complex(mr, -m))) / (y + (complex(mr, -m))**2) + ((complex(z3, z4)) * (complex(mr1, m1))) / (y + (complex(mr1, m1))**2) + ((complex(z3, -z4)) * (complex(mr1, -m1))) / (y + (complex(mr1, -m1))**2))
def _contr_ancr_by_delta(label1, indices1, label2, indices2): """Contract an annihilation and a creation operator by delta.""" # For the delta contraction, some additional checking is needed for it to # make sense. err_header = 'Invalid field operators to contract by delta' # When the operators are on different base, it is likely that delta is not # what is intended. if label1 != label2: raise ValueError(err_header, (label1, label2), 'expecting the same base') if len(indices1) != len(indices2): raise ValueError(err_header, (indices1, indices2), 'expecting same number of indices') res = 1 for i, j in zip(indices1, indices2): # TODO: Maybe support continuous indices here. res *= KroneckerDelta(i, j) continue return res
def Rot_AngAx(n, theta): """ Rotation matrix Rodrigues formula angle-axis parametrization INPUT: n - vector [nx,ny,nz] 0 <= theta <= pi OUTPUT: Rot - matrix(3x3) nx,ny,nz = symbols('nx,ny,nz') n = [nx,ny,nz] """ dimens = 3 """ R = sp.MatrixSymbol('R', dimens, dimens) """ i, j = sp.symbols('i,j') R = sp.FunctionMatrix(dimens, dimens, sp.Lambda((i, j), cos(theta) * KroneckerDelta(i, j))) for k in range(dimens): R -= sp.FunctionMatrix( dimens, dimens, sp.Lambda((i, j), sin(theta) * Eijk(i, j, k) * n[k])) Rot = sp.Matrix(R) R2 = sp.zeros(dimens) for i in range(dimens): R2.row_op(i, lambda v, j: (1 - cos(theta)) * n[i] * n[j]) Rot += R2 Rot = sp.N(Rot, 4) #Rot = sp.matrix2numpy(Rot) return Rot
def _swap_lattice_gens(vec1: Vec, vec2: Vec, bcast_swap_info): """Swap the generators with lattice indices.""" swap_info: _SwapInfo = bcast_swap_info.value base_ranks = swap_info.base_ranks comms = swap_info.comms assume_comm = swap_info.assume_comm vecs = (vec1, vec2) indices1, indices2 = [i.indices for i in vecs] if len(indices1) != len(indices2): raise ValueError('Unmatching lattice indices for', vec1, vec2) base1, base2 = [vec.base for vec in vecs] try: rank1 = base_ranks[base1] rank2 = base_ranks[base2] except KeyError as exc: raise ValueError('Vector with unspecified normal order', exc.args) if rank1 < rank2: return None elif rank1 == rank2: # Same generator at possibly different sites always commute. key1, key2 = [ tuple(sympy_key(j) for j in i) for i in (indices1, indices2) ] if key1 <= key2: return None else: return _UNITY, _NOUGHT else: given = (base1, base2) rev = (base2, base1) if given in comms: comm, phase = _get_comm_phase(comms, given, indices1) comm_factor = _UNITY elif rev in comms: # a b = phi b a + kappa => phi b a = a b - kappa # => b a = (a b - kappa) / phi comm, phase = _get_comm_phase(comms, rev, indices1) comm_factor = -1 / phase phase = 1 / phase elif assume_comm: comm = _NOUGHT phase = _UNITY comm_factor = _UNITY else: raise ValueError('Commutation rules unspecified', vec1, vec2) delta = functools.reduce(operator.mul, (KroneckerDelta(i, j) for i, j in zip(indices1, indices2)), _UNITY) terms = Terms( Term( term.sums, delta * comm_factor * term.amp, tuple(i[indices1] if len(i.indices) == 0 else i for i in term.vecs)) for term in comm) return phase, terms
def _get_fermi_partitions(term: Term, spec: _AGPFSpec): """Given a term with a list of fermionic vectors, extract the various partitions of N, Pdag and P kind of terms. Assumes: All possible simplification and Pairing / SU2 extraction has been performed, i.e. all the indices are distinct. """ vecs = term.vecs amp = term.amp fermi_indcs = [] cr = spec.c_dag.base an = spec.c_.base # First extract all the indices of fermion operators for v in vecs: if v.base in (cr, an): fermi_indcs.append(v.indices[1]) if len(fermi_indcs) == 0: # if there are no fermion operators, return the term as it is return [Term(sums=term.sums, amp=amp, vecs=vecs)] else: # if there are fermion operators, then get all the possible # partitions of indices deltas_partns = list(_generate_partitions(fermi_indcs)) # get a list of even partitions, i.e. throw away partitions involving # odd number of indices evens = [ all( len(deltas_partns[i][j]) % 2 == 0 for j in range(len(deltas_partns[i]))) for i in range(len(deltas_partns)) ] # Now iterate through the list of partitions and form the deltas expression # for the amplitude delta_amp = Integer(0) for i in range(len(deltas_partns)): # if statement for even partitions if evens[i]: pt = deltas_partns[i] else: continue # Form the delta expressions delta_intmd = Integer(1) for i in range(len(pt)): delta_intmd *= _construct_deltas(pt[i]) if i > 0: delta_intmd *= (1 - KroneckerDelta(pt[i][0], pt[i - 1][0])) delta_amp += delta_intmd new_amp = amp * delta_amp return [Term(sums=term.sums, amp=new_amp, vecs=vecs)]
def _construct_deltas(indices): """Given a list of indices, form all possible KroneckerDelta pairs """ del_pairs = Integer(1) for i in range(len(indices) - 1): del_pairs *= KroneckerDelta(indices[i], indices[i + 1]) return del_pairs
def compute_density(self, expr, **kwargs): z = Dummy('z', real=True, finite=True) rvs = random_symbols(expr) if any(pspace(rv).is_Continuous for rv in rvs): expr = self.integrate(DiracDelta(expr - z), **kwargs) else: expr = self.integrate(KroneckerDelta(expr, z), **kwargs) return Lambda(z, expr)
def test_wigner3j_sum_to_wigner6j(nuclear: NuclearBogoliubovDrudge): """Test simplification of sum of product of four 3j's to a 6j. This test tries to simplify the original LHS of the equation from the Wolfram website. """ dr = nuclear j1, j2, j3, jprm3, j4, j5, j6 = symbols( 'j1 j2 j3 jprm3 j4 j5 j6', integer=True ) m1, m2, m3, mprm3, m4, m5, m6 = symbols( 'm1 m2 m3 mprm3 m4 m5 m6', integer=True ) m_range = Range('m') sums = [(m_i, m_range[-j_i, j_i + 1]) for m_i, j_i in [ (m1, j1), (m2, j2), (m4, j4), (m5, j5), (m6, j6) ]] phase = (-1) ** ( j1 + j2 + j4 + j5 + j6 - m1 - m2 - m4 - m5 - m6 ) amp = ( Wigner3j(j2, m2, j3, -m3, j1, m1) * Wigner3j(j1, -m1, j5, m5, j6, m6) * Wigner3j(j5, -m5, jprm3, mprm3, j4, m4) * Wigner3j(j4, -m4, j2, -m2, j6, -m6) ) expected = ( ((-1) ** (j3 - m3) / (2 * j3 + 1)) * KroneckerDelta(j3, jprm3) * KroneckerDelta(m3, mprm3) * Wigner6j(j1, j2, j3, j4, j5, j6) ).expand().simplify() # For performance reason, just test a random arrangement of the summations. random.shuffle(sums) tensor = dr.sum(*sums, phase * amp) res = tensor.deep_simplify().merge() assert res.n_terms == 1 term = res.local_terms[0] assert len(term.sums) == 0 assert len(term.vecs) == 0 assert (term.amp - expected).simplify() == 0
def test_simplify_delta_of_two_ranges(free_alg): """Test simplification of delta of two disjoint ranges.""" dr = free_alg p = dr.names tensor = dr.sum(KroneckerDelta(p.i, p.alpha) * p.v) assert tensor.n_terms == 1 assert tensor.simplify_deltas() == 0 assert tensor.simplify() == 0
def compute_density(self, expr, **kwargs): rvs = random_symbols(expr) if any(pspace(rv).is_Continuous for rv in rvs): z = Dummy('z', real=True) expr = self.compute_expectation(DiracDelta(expr - z), **kwargs) else: z = Dummy('z', integer=True) expr = self.compute_expectation(KroneckerDelta(expr, z), **kwargs) return Lambda(z, expr)
def test_simplify_delta_of_unsolvable_functions(free_alg): """Test simplification of delta of with functions unable to solve.""" dr = free_alg p = dr.names f = Function('f') tensor = dr.sum((p.i, p.R), KroneckerDelta(f(p.i), p.alpha) * p.v) assert tensor.n_terms == 1 assert tensor.simplify_deltas() == tensor assert tensor.simplify() == tensor
def test_tensor_can_be_simplified_amp(free_alg): """Test the amplitude simplification for tensors. More than trivial tensor amplitude simplification is tested here. Currently it mostly concentrates on the dispatching to SymPy and delta simplification. The master simplification is also tested. """ dr = free_alg p = dr.names r = p.R s = p.S v = p.v i, j = p.R_dumms[:2] alpha = p.alpha x = IndexedBase('x') y = IndexedBase('y') theta = sympify('theta') tensor = (dr.sum( (i, r), sin(theta)**2 * x[i] * v[i]) + dr.sum( (i, r), (j, r), cos(theta)**2 * x[j] * KroneckerDelta(i, j) * v[i]) + dr.sum( (i, r), (alpha, s), KroneckerDelta(i, alpha) * y[i] * v[i])) assert tensor.n_terms == 3 first = tensor.simplify_deltas().simplify_amps() # Now we should have one term killed. assert first.n_terms == 2 # Merge again should really simplify. merged = first.reset_dumms().merge().simplify_amps() assert merged.n_terms == 1 expected = dr.sum((i, r), x[i] * v[i]) assert merged == expected # The master simplification should do it in one turn. simpl = tensor.simplify() assert simpl == expected