Exemple #1
0
    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)
Exemple #2
0
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
Exemple #3
0
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 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
Exemple #5
0
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)
Exemple #6
0
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)
Exemple #7
0
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}]"
    )
Exemple #8
0
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)
Exemple #9
0
    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())
Exemple #11
0
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])
Exemple #12
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)
Exemple #13
0
def _arrayfy(a):
    if isinstance(a, NDimArray):
        return a
    if isinstance(a, (MatrixBase, list, tuple, Tuple)):
        return ImmutableDenseNDimArray(a)
    return a
Exemple #14
0
 def __new__(cls, iterable, shape=None, **kwargs):
     from sympy.tensor.array import ImmutableDenseNDimArray
     return ImmutableDenseNDimArray(iterable, shape, **kwargs)
Exemple #15
0
 def __new__(cls, *args, **kwargs):
     from sympy.tensor.array import ImmutableDenseNDimArray
     return ImmutableDenseNDimArray(*args, **kwargs)
Exemple #16
0
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
Exemple #17
0
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())