def _expand_array(self): res = [] for values in itertools.product( *[range(inf, sup + 1) for var, inf, sup in self._limits]): res.append(self._get_element(values)) return ImmutableDenseNDimArray(res, self.shape)
def _arrayfy(a): from sympy.matrices import MatrixBase if isinstance(a, NDimArray): return a if isinstance(a, (MatrixBase, list, tuple, Tuple)): return ImmutableDenseNDimArray(a) return a
def test_NDim_array_conv(): MD = MutableDenseNDimArray([x, y, z]) MS = MutableSparseNDimArray([x, y, z]) ID = ImmutableDenseNDimArray([x, y, z]) IS = ImmutableSparseNDimArray([x, y, z]) assert MD.as_immutable() == ID assert MD.as_mutable() == MD assert MS.as_immutable() == IS assert MS.as_mutable() == MS assert ID.as_immutable() == ID assert ID.as_mutable() == MD assert IS.as_immutable() == IS assert IS.as_mutable() == MS
def derive_by_array(expr, dx): r""" Derivative by arrays. Supports both arrays and scalars. Given the array `A_{i_1, \ldots, i_N}` and the array `X_{j_1, \ldots, j_M}` this function will return a new array `B` defined by `B_{j_1,\ldots,j_M,i_1,\ldots,i_N} := \frac{\partial A_{i_1,\ldots,i_N}}{\partial X_{j_1,\ldots,j_M}}` Examples ======== >>> from sympy import derive_by_array >>> from sympy.abc import x, y, z, t >>> from sympy import cos >>> derive_by_array(cos(x*t), x) -t*sin(t*x) >>> derive_by_array(cos(x*t), [x, y, z, t]) [-t*sin(t*x), 0, 0, -x*sin(t*x)] >>> derive_by_array([x, y**2*z], [[x, y], [z, t]]) [[[1, 0], [0, 2*y*z]], [[0, y**2], [0, 0]]] """ from sympy.matrices import MatrixBase from sympy.tensor.array import SparseNDimArray array_types = (Iterable, MatrixBase, NDimArray) if isinstance(dx, array_types): dx = ImmutableDenseNDimArray(dx) for i in dx: if not i._diff_wrt: raise ValueError("cannot derive by this array") if isinstance(expr, array_types): if isinstance(expr, NDimArray): expr = expr.as_immutable() else: expr = ImmutableDenseNDimArray(expr) if isinstance(dx, array_types): if isinstance(expr, SparseNDimArray): lp = len(expr) new_array = { k + i * lp: v for i, x in enumerate(Flatten(dx)) for k, v in expr.diff(x)._sparse_array.items() } else: new_array = [[y.diff(x) for y in Flatten(expr)] for x in Flatten(dx)] return type(expr)(new_array, dx.shape + expr.shape) else: return expr.diff(dx) else: if isinstance(dx, array_types): return ImmutableDenseNDimArray([expr.diff(i) for i in Flatten(dx)], dx.shape) else: return diff(expr, dx)
def derive_by_array(expr, dx): r""" Derivative by arrays. Supports both arrays and scalars. Given the array `A_{i_1, \ldots, i_N}` and the array `X_{j_1, \ldots, j_M}` this function will return a new array `B` defined by `B_{j_1,\ldots,j_M,i_1,\ldots,i_N} := \frac{\partial A_{i_1,\ldots,i_N}}{\partial X_{j_1,\ldots,j_M}}` Examples ======== >>> from sympy import derive_by_array >>> from sympy.abc import x, y, z, t >>> from sympy import cos >>> derive_by_array(cos(x*t), x) -t*sin(t*x) >>> derive_by_array(cos(x*t), [x, y, z, t]) [-t*sin(t*x), 0, 0, -x*sin(t*x)] >>> derive_by_array([x, y**2*z], [[x, y], [z, t]]) [[[1, 0], [0, 2*y*z]], [[0, y**2], [0, 0]]] """ from sympy.matrices import MatrixBase array_types = (collections.Iterable, MatrixBase, NDimArray) if isinstance(dx, array_types): dx = ImmutableDenseNDimArray(dx) for i in dx: if not i._diff_wrt: raise ValueError("cannot derive by this array") if isinstance(expr, array_types): expr = ImmutableDenseNDimArray(expr) if isinstance(dx, array_types): new_array = [[y.diff(x) for y in expr] for x in dx] return type(expr)(new_array, dx.shape + expr.shape) else: return expr.diff(dx) else: if isinstance(dx, array_types): return ImmutableDenseNDimArray([expr.diff(i) for i in dx], dx.shape) else: return diff(expr, dx)
def test_NDArray(): from sympy.tensor.array import ( MutableDenseNDimArray, ImmutableDenseNDimArray, MutableSparseNDimArray, ImmutableSparseNDimArray, ) example = MutableDenseNDimArray( [ [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], [[13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24]], ] ) assert ( mcode(example) == "{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, " "{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}}" ) example = ImmutableDenseNDimArray(example) assert ( mcode(example) == "{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, " "{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}}" ) example = MutableSparseNDimArray(example) assert ( mcode(example) == "SparseArray[{" "{1, 1, 1} -> 1, {1, 1, 2} -> 2, {1, 1, 3} -> 3, " "{1, 1, 4} -> 4, {1, 2, 1} -> 5, {1, 2, 2} -> 6, " "{1, 2, 3} -> 7, {1, 2, 4} -> 8, {1, 3, 1} -> 9, " "{1, 3, 2} -> 10, {1, 3, 3} -> 11, {1, 3, 4} -> 12, " "{2, 1, 1} -> 13, {2, 1, 2} -> 14, {2, 1, 3} -> 15, " "{2, 1, 4} -> 16, {2, 2, 1} -> 17, {2, 2, 2} -> 18, " "{2, 2, 3} -> 19, {2, 2, 4} -> 20, {2, 3, 1} -> 21, " "{2, 3, 2} -> 22, {2, 3, 3} -> 23, {2, 3, 4} -> 24" "}, {2, 3, 4}]" ) example = ImmutableSparseNDimArray(example) assert ( mcode(example) == "SparseArray[{" "{1, 1, 1} -> 1, {1, 1, 2} -> 2, {1, 1, 3} -> 3, " "{1, 1, 4} -> 4, {1, 2, 1} -> 5, {1, 2, 2} -> 6, " "{1, 2, 3} -> 7, {1, 2, 4} -> 8, {1, 3, 1} -> 9, " "{1, 3, 2} -> 10, {1, 3, 3} -> 11, {1, 3, 4} -> 12, " "{2, 1, 1} -> 13, {2, 1, 2} -> 14, {2, 1, 3} -> 15, " "{2, 1, 4} -> 16, {2, 2, 1} -> 17, {2, 2, 2} -> 18, " "{2, 2, 3} -> 19, {2, 2, 4} -> 20, {2, 3, 1} -> 21, " "{2, 3, 2} -> 22, {2, 3, 3} -> 23, {2, 3, 4} -> 24" "}, {2, 3, 4}]" )
def tensorproduct(*args): """ Tensor product among scalars or array-like objects. Examples ======== >>> from sympy.tensor.array import tensorproduct, Array >>> from sympy.abc import x, y, z, t >>> A = Array([[1, 2], [3, 4]]) >>> B = Array([x, y]) >>> tensorproduct(A, B) [[[x, y], [2*x, 2*y]], [[3*x, 3*y], [4*x, 4*y]]] >>> tensorproduct(A, x) [[x, 2*x], [3*x, 4*x]] >>> tensorproduct(A, B, B) [[[[x**2, x*y], [x*y, y**2]], [[2*x**2, 2*x*y], [2*x*y, 2*y**2]]], [[[3*x**2, 3*x*y], [3*x*y, 3*y**2]], [[4*x**2, 4*x*y], [4*x*y, 4*y**2]]]] Applying this function on two matrices will result in a rank 4 array. >>> from sympy import Matrix, eye >>> m = Matrix([[x, y], [z, t]]) >>> p = tensorproduct(eye(3), m) >>> p [[[[x, y], [z, t]], [[0, 0], [0, 0]], [[0, 0], [0, 0]]], [[[0, 0], [0, 0]], [[x, y], [z, t]], [[0, 0], [0, 0]]], [[[0, 0], [0, 0]], [[0, 0], [0, 0]], [[x, y], [z, t]]]] """ from sympy.tensor.array import SparseNDimArray, ImmutableSparseNDimArray if len(args) == 0: return S.One if len(args) == 1: return _arrayfy(args[0]) if len(args) > 2: return tensorproduct(tensorproduct(args[0], args[1]), *args[2:]) # length of args is 2: a, b = map(_arrayfy, args) if not isinstance(a, NDimArray) or not isinstance(b, NDimArray): return a * b if isinstance(a, SparseNDimArray) and isinstance(b, SparseNDimArray): lp = len(b) new_array = { k1 * lp + k2: v1 * v2 for k1, v1 in a._sparse_array.items() for k2, v2 in b._sparse_array.items() } return ImmutableSparseNDimArray(new_array, a.shape + b.shape) al = list(a) bl = list(b) product_list = [i * j for i in al for j in bl] return ImmutableDenseNDimArray(product_list, a.shape + b.shape)
def _expand_array(self): # To perform a subs at every element of the array. def _array_subs(arr, var, val): arr = MutableDenseNDimArray(arr) for i in range(len(arr)): index = arr._get_tuple_index(i) arr[index] = arr[index].subs(var, val) return arr.tolist() list_gen = self.function for var, inf, sup in reversed(self._limits): list_expr = list_gen list_gen = [] for val in range(inf, sup+1): if not isinstance(list_expr, Iterable): list_gen.append(list_expr.subs(var, val)) else: list_gen.append(_array_subs(list_expr, var, val)) return ImmutableDenseNDimArray(list_gen)
def test_arraycomprehensionmap(): a = ArrayComprehensionMap(lambda i: i + 1, (i, 1, 5)) assert a.doit().tolist() == [2, 3, 4, 5, 6] assert a.shape == (5, ) assert a.is_shape_numeric assert a.tolist() == [2, 3, 4, 5, 6] assert len(a) == 5 assert isinstance(a.doit(), ImmutableDenseNDimArray) expr = ArrayComprehensionMap(lambda i: i + 1, (i, 1, k)) assert expr.doit() == expr assert expr.subs(k, 4) == ArrayComprehensionMap(lambda i: i + 1, (i, 1, 4)) assert expr.subs(k, 4).doit() == ImmutableDenseNDimArray([2, 3, 4, 5]) b = ArrayComprehensionMap(lambda i: i + 1, (i, 1, 2), (i, 1, 3), (i, 1, 4), (i, 1, 5)) assert b.doit().tolist() == [[[[2, 3, 4, 5, 6], [3, 5, 7, 9, 11], [4, 7, 10, 13, 16], [5, 9, 13, 17, 21]], [[3, 5, 7, 9, 11], [5, 9, 13, 17, 21], [7, 13, 19, 25, 31], [9, 17, 25, 33, 41]], [[4, 7, 10, 13, 16], [7, 13, 19, 25, 31], [10, 19, 28, 37, 46], [13, 25, 37, 49, 61]]], [[[3, 5, 7, 9, 11], [5, 9, 13, 17, 21], [7, 13, 19, 25, 31], [9, 17, 25, 33, 41]], [[5, 9, 13, 17, 21], [9, 17, 25, 33, 41], [13, 25, 37, 49, 61], [17, 33, 49, 65, 81]], [[7, 13, 19, 25, 31], [13, 25, 37, 49, 61], [19, 37, 55, 73, 91], [25, 49, 73, 97, 121]]]] # tests about lambda expression assert ArrayComprehensionMap(lambda: 3, (i, 1, 5)).doit().tolist() == [3, 3, 3, 3, 3] assert ArrayComprehensionMap(lambda i: i + 1, (i, 1, 5)).doit().tolist() == [2, 3, 4, 5, 6] raises(ValueError, lambda: ArrayComprehensionMap(i * j, (i, 1, 3), (j, 2, 4))) # The use of a function here triggers a deprecation warning from sympify() with warns(SymPyDeprecationWarning, test_stacklevel=False): a = ArrayComprehensionMap(lambda i, j: i + j, (i, 1, 5)) raises(ValueError, lambda: a.doit())
def test_derivative_by_array(): from sympy.abc import i, j, t, x, y, z bexpr = x*y**2*exp(z)*log(t) sexpr = sin(bexpr) cexpr = cos(bexpr) a = Array([sexpr]) assert derive_by_array(sexpr, t) == x*y**2*exp(z)*cos(x*y**2*exp(z)*log(t))/t assert derive_by_array(sexpr, [x, y, z]) == Array([bexpr/x*cexpr, 2*y*bexpr/y**2*cexpr, bexpr*cexpr]) assert derive_by_array(a, [x, y, z]) == Array([[bexpr/x*cexpr], [2*y*bexpr/y**2*cexpr], [bexpr*cexpr]]) assert derive_by_array(sexpr, [[x, y], [z, t]]) == Array([[bexpr/x*cexpr, 2*y*bexpr/y**2*cexpr], [bexpr*cexpr, bexpr/log(t)/t*cexpr]]) assert derive_by_array(a, [[x, y], [z, t]]) == Array([[[bexpr/x*cexpr], [2*y*bexpr/y**2*cexpr]], [[bexpr*cexpr], [bexpr/log(t)/t*cexpr]]]) assert derive_by_array([[x, y], [z, t]], [x, y]) == Array([[[1, 0], [0, 0]], [[0, 1], [0, 0]]]) assert derive_by_array([[x, y], [z, t]], [[x, y], [z, t]]) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) assert diff(sexpr, t) == x*y**2*exp(z)*cos(x*y**2*exp(z)*log(t))/t assert diff(sexpr, Array([x, y, z])) == Array([bexpr/x*cexpr, 2*y*bexpr/y**2*cexpr, bexpr*cexpr]) assert diff(a, Array([x, y, z])) == Array([[bexpr/x*cexpr], [2*y*bexpr/y**2*cexpr], [bexpr*cexpr]]) assert diff(sexpr, Array([[x, y], [z, t]])) == Array([[bexpr/x*cexpr, 2*y*bexpr/y**2*cexpr], [bexpr*cexpr, bexpr/log(t)/t*cexpr]]) assert diff(a, Array([[x, y], [z, t]])) == Array([[[bexpr/x*cexpr], [2*y*bexpr/y**2*cexpr]], [[bexpr*cexpr], [bexpr/log(t)/t*cexpr]]]) assert diff(Array([[x, y], [z, t]]), Array([x, y])) == Array([[[1, 0], [0, 0]], [[0, 1], [0, 0]]]) assert diff(Array([[x, y], [z, t]]), Array([[x, y], [z, t]])) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) # test for large scale sparse array for SparseArrayType in [ImmutableSparseNDimArray, MutableSparseNDimArray]: b = MutableSparseNDimArray({0:i, 1:j}, (10000, 20000)) assert derive_by_array(b, i) == ImmutableSparseNDimArray({0: 1}, (10000, 20000)) assert derive_by_array(b, (i, j)) == ImmutableSparseNDimArray({0: 1, 200000001: 1}, (2, 10000, 20000)) #https://github.com/sympy/sympy/issues/20655 U = Array([x, y, z]) E = 2 assert derive_by_array(E, U) == ImmutableDenseNDimArray([0, 0, 0])
def derive_by_array(expr, dx): """ Derivative by arrays. Supports both arrays and scalars. Given the array `A_{i_1, \ldots, i_N}` and the array `X_{j_1, \ldots, j_M}` this function will return a new array `B` defined by `B_{j_1,\ldots,j_M,i_1,\ldots,i_N} := \frac{\partial A_{i_1,\ldots,i_N}}{\partial X_{j_1,\ldots,j_M}` Examples ======== >>> from sympy.tensor.array import derive_by_array >>> from sympy.abc import x, y, z, t >>> from sympy import cos >>> derive_by_array(cos(x*t), x) -t*sin(t*x) >>> derive_by_array(cos(x*t), [x, y, z, t]) [-t*sin(t*x), 0, 0, -x*sin(t*x)] >>> derive_by_array([x, y**2*z], [[x, y], [z, t]]) [[[1, 0], [0, 2*y*z]], [[0, y**2], [0, 0]]] """ array_types = (collections.Iterable, MatrixBase, NDimArray) if isinstance(dx, array_types): dx = ImmutableDenseNDimArray(dx) for i in dx: if not i._diff_wrt: raise ValueError("cannot derive by this array") if isinstance(expr, array_types): expr = ImmutableDenseNDimArray(expr) if isinstance(dx, array_types): new_array = [[y.diff(x) for y in expr] for x in dx] return type(expr)(new_array, dx.shape + expr.shape) else: return expr.diff(dx) else: if isinstance(dx, array_types): return ImmutableDenseNDimArray([expr.diff(i) for i in dx], dx.shape) else: return diff(expr, dx)
def _arrayfy(a): if isinstance(a, NDimArray): return a if isinstance(a, (MatrixBase, list, tuple, Tuple)): return ImmutableDenseNDimArray(a) return a
def __new__(cls, iterable, shape=None, **kwargs): from sympy.tensor.array import ImmutableDenseNDimArray return ImmutableDenseNDimArray(iterable, shape, **kwargs)
def __new__(cls, *args, **kwargs): from sympy.tensor.array import ImmutableDenseNDimArray return ImmutableDenseNDimArray(*args, **kwargs)
def test_H2(): TP = sympy.diffgeom.TensorProduct R2 = sympy.diffgeom.rn.R2 y = R2.y dy = R2.dy dx = R2.dx g = (TP(dx, dx) + TP(dy, dy))*y**(-2) automat = twoform_to_matrix(g) mat = diag(y**(-2), y**(-2)) assert mat == automat gamma1 = metric_to_Christoffel_1st(g) assert gamma1[0, 0, 0] == 0 assert gamma1[0, 0, 1] == -y**(-3) assert gamma1[0, 1, 0] == -y**(-3) assert gamma1[0, 1, 1] == 0 assert gamma1[1, 1, 1] == -y**(-3) assert gamma1[1, 1, 0] == 0 assert gamma1[1, 0, 1] == 0 assert gamma1[1, 0, 0] == y**(-3) gamma2 = metric_to_Christoffel_2nd(g) assert gamma2[0, 0, 0] == 0 assert gamma2[0, 0, 1] == -y**(-1) assert gamma2[0, 1, 0] == -y**(-1) assert gamma2[0, 1, 1] == 0 assert gamma2[1, 1, 1] == -y**(-1) assert gamma2[1, 1, 0] == 0 assert gamma2[1, 0, 1] == 0 assert gamma2[1, 0, 0] == y**(-1) Rm = metric_to_Riemann_components(g) assert Rm[0, 0, 0, 0] == 0 assert Rm[0, 0, 0, 1] == 0 assert Rm[0, 0, 1, 0] == 0 assert Rm[0, 0, 1, 1] == 0 assert Rm[0, 1, 0, 0] == 0 assert Rm[0, 1, 0, 1] == -y**(-2) assert Rm[0, 1, 1, 0] == y**(-2) assert Rm[0, 1, 1, 1] == 0 assert Rm[1, 0, 0, 0] == 0 assert Rm[1, 0, 0, 1] == y**(-2) assert Rm[1, 0, 1, 0] == -y**(-2) assert Rm[1, 0, 1, 1] == 0 assert Rm[1, 1, 0, 0] == 0 assert Rm[1, 1, 0, 1] == 0 assert Rm[1, 1, 1, 0] == 0 assert Rm[1, 1, 1, 1] == 0 Ric = metric_to_Ricci_components(g) assert Ric[0, 0] == -y**(-2) assert Ric[0, 1] == 0 assert Ric[1, 0] == 0 assert Ric[0, 0] == -y**(-2) assert Ric == ImmutableDenseNDimArray([-y**(-2), 0, 0, -y**(-2)], (2, 2)) ## scalar curvature is -2 #TODO - it would be nice to have index contraction built-in R = (Ric[0, 0] + Ric[1, 1])*y**2 assert R == -2 ## Gauss curvature is -1 assert R/2 == -1
def test_arraycomprehensionmap(): a = ArrayComprehensionMap(lambda i: i + 1, (i, 1, 5)) assert a.doit().tolist() == [2, 3, 4, 5, 6] assert a.shape == (5, ) assert a.is_shape_numeric assert a.tolist() == [2, 3, 4, 5, 6] assert len(a) == 5 assert isinstance(a.doit(), ImmutableDenseNDimArray) expr = ArrayComprehensionMap(lambda i: i + 1, (i, 1, k)) assert expr.doit() == expr assert expr.subs(k, 4) == ArrayComprehensionMap(lambda i: i + 1, (i, 1, 4)) assert expr.subs(k, 4).doit() == ImmutableDenseNDimArray([2, 3, 4, 5]) b = ArrayComprehensionMap(lambda i: i + 1, (i, 1, 2), (i, 1, 3), (i, 1, 4), (i, 1, 5)) assert b.doit().tolist() == [ [ [[2, 3, 4, 5, 6], [3, 5, 7, 9, 11], [4, 7, 10, 13, 16], [5, 9, 13, 17, 21]], [ [3, 5, 7, 9, 11], [5, 9, 13, 17, 21], [7, 13, 19, 25, 31], [9, 17, 25, 33, 41], ], [ [4, 7, 10, 13, 16], [7, 13, 19, 25, 31], [10, 19, 28, 37, 46], [13, 25, 37, 49, 61], ], ], [ [ [3, 5, 7, 9, 11], [5, 9, 13, 17, 21], [7, 13, 19, 25, 31], [9, 17, 25, 33, 41], ], [ [5, 9, 13, 17, 21], [9, 17, 25, 33, 41], [13, 25, 37, 49, 61], [17, 33, 49, 65, 81], ], [ [7, 13, 19, 25, 31], [13, 25, 37, 49, 61], [19, 37, 55, 73, 91], [25, 49, 73, 97, 121], ], ], ] # tests about lambda expression assert ArrayComprehensionMap(lambda: 3, (i, 1, 5)).doit().tolist() == [ 3, 3, 3, 3, 3, ] assert ArrayComprehensionMap(lambda i: i + 1, (i, 1, 5)).doit().tolist() == [ 2, 3, 4, 5, 6, ] raises(ValueError, lambda: ArrayComprehensionMap(lambda i, j: i + j, (i, 1, 5)).doit()) raises(ValueError, lambda: ArrayComprehensionMap(i * j, (i, 1, 3), (j, 2, 4)))
def doit(self): if not self.is_shape_numeric: return self return ImmutableDenseNDimArray(self._expand_array())