예제 #1
0
def test_subtraction_with_zero():
    A = MathArray([[5,  2, 1], [-2, 4, -3]])
    assert equal_as_arrays(A - 0, A)
    assert equal_as_arrays(0 - A, -A) # pylint: disable=invalid-unary-operand-type

    u = MathArray([1, 2])
    assert equal_as_arrays(u - 0, u)
    assert equal_as_arrays(0 - u, -u) # pylint: disable=invalid-unary-operand-type
예제 #2
0
def test_subtraction_with_correct_shapes():

    u = MathArray([1, 2, 3])
    v = MathArray([10, 20, 30])
    w = MathArray([9, 18, 27])
    assert equal_as_arrays(v - u, w)

    A = MathArray([[5,  2, 1], [-2, 4, -3]])
    B = MathArray([[2, -1, 4], [3,  0,  1]])
    C = MathArray([[3,  3, -3], [-5,  4, -4]])
    assert equal_as_arrays(A - B, C)
예제 #3
0
def test_numpy_functions_preserve_class():
    A = MathArray([
        [1, 2, 3],
        [4, 5, 6]
    ])
    A_trans = MathArray([
        [1, 4],
        [2, 5],
        [3, 6]
    ])
    assert equal_as_arrays(np.transpose(A), A_trans)
    assert equal_as_arrays(A.T, A_trans)
예제 #4
0
def test_addition_with_correct_shapes():

    u = MathArray([1, 2, 3])
    v = MathArray([10, 20, 30])
    w = MathArray([11, 22, 33])
    assert equal_as_arrays(u + v, w)

    A = MathArray([[5,  2, 1], [-2, 4, -3]])
    B = MathArray([[2, -1, 4], [3,  0,  1]])
    C = MathArray([[7,  1, 5], [1,  4, -2]])
    assert equal_as_arrays(A + B, C)
    assert equal_as_arrays(A + B, B + A)
예제 #5
0
def test_cross():
    cross = ARRAY_ONLY_FUNCTIONS['cross']
    a = MathArray([2, -1, 3.5])
    b = MathArray([1.5, 2.25, -1])
    a_cross_b = MathArray([-6.875, 7.25, 6.])

    assert equal_as_arrays(cross(a, b), a_cross_b)

    vec_3 = random_math_array((3, ))
    vec_4 = random_math_array((4, ))
    match = (
        r"There was an error evaluating function cross\(...\)\n"
        r"1st input is ok: received a vector of length 3 as expected\n"
        r"2nd input has an error: received a vector of length 4, expected "
        r"a vector of length 3")
    with raises(DomainError, match=match):
        cross(vec_3, vec_4)

    match = (
        r"There was an error evaluating function cross\(...\)\n"
        r"1st input has an error: received a vector of length 4, expected "
        r"a vector of length 3\n"
        r"2nd input is ok: received a vector of length 3 as expected")
    with raises(DomainError, match=match):
        cross(vec_4, vec_3)
예제 #6
0
def test_in_place_powers():
    amounts = [2, -3.0, MathArray(5)]
    for amount in amounts:
        A = random_math_array([2, 2])
        A_copy = A.copy()
        A **= amount
        assert equal_as_arrays(A, A_copy ** amount)
예제 #7
0
def test_triple_vector_product_raises_error():
    # Since vector products are interpretted as dot products, they are
    # ambiguous, and we disallow them.

    variables = {
    'i': MathArray([1, 0]),
    'j': MathArray([0, 1]),
    }

    assert equal_as_arrays(
        evaluator("(i*i)*j", variables)[0],
        variables['j']
    )

    match = ("Multiplying three or more vectors is ambiguous. "
             "Please place parentheses around vector multiplications.")
    with raises(CalcError, match=match):
        evaluator("i*i*j", variables)[0]

    with raises(CalcError, match=match):
        evaluator("i*2*i*3*j", variables)[0]

    # Next example should raise an operator shape error, not a triple vec error
    match='Cannot divide by a vector'
    with raises(CalcError, match=match):
        evaluator("i*j/i*i*j", variables)[0]
예제 #8
0
def test_calc_functions_multiple_arguments():
    """Tests parse/eval handling functions with multiple arguments correctly"""
    def h1(x):
        return x

    def h2(x, y):
        return x * y

    def h3(x, y, z):
        return x * y * z

    assert evaluator("h(2)", {}, {"h": h1}, {})[0] == 2.0
    assert evaluator("h(2, 3)", {}, {"h": h2}, {})[0] == 6.0
    assert evaluator("h(2, 3, 4)", {}, {"h": h3}, {})[0] == 24.0
    assert equal_as_arrays(
        evaluator("h(2, [1, 2, 3])", {}, {"h": h2})[0], MathArray([2, 4, 6]))
    with raises(ArgumentError):
        evaluator("h(2, 1)", {}, {"h": h1}, {})
    with raises(UnableToParse):
        evaluator("h()", {}, {"h": h1}, {})
    with raises(ArgumentError):
        evaluator("h(1)", {}, {"h": h2}, {})
    with raises(ArgumentError):
        evaluator("h(1,2,3)", {}, {"h": h2}, {})
    with raises(UnableToParse):
        evaluator("h()", {}, {"h": h3}, {})
    with raises(ArgumentError):
        evaluator("h(1)", {}, {"h": h3}, {})
    with raises(ArgumentError):
        evaluator("h(1,2)", {}, {"h": h3}, {})
예제 #9
0
def test_matrix_times_matrix_multiplication():
    A = MathArray([
        [5, 2, 3],
        [-4, 3, -1]
    ])
    B = MathArray([
        [0, 4, 5, 2],
        [5, -2, 6, -3],
        [-7, 5, 8, 4]
    ])
    C = MathArray([
        [-11, 31, 61, 16],
        [22, -27, -10, -21]
    ])
    assert equal_as_arrays(A*B, C)

    X = random_math_array([3, 5])
    Y = random_math_array([4, 2])

    match = ("Cannot multiply a matrix of shape \(rows: 3, cols: 5\) with a matrix "
             "of shape \(rows: 4, cols: 2\)")
    with raises(ShapeError, match=match):
        X*Y

    row = MathArray([[1, 2, 3]])
    col = MathArray([[1], [2], [3]])
    assert row*col == 14 and isinstance(row*col, Number)
예제 #10
0
def test_in_place_division():

    amounts = [5, MathArray(5)]
    for amount in amounts:
        A = random_math_array([2, 2])
        A_copy = A.copy()
        A /= amount
        assert equal_as_arrays(A, A_copy / amount)
예제 #11
0
def test_in_place_multiplication():

    amounts = [5, random_math_array(tuple()), random_math_array([2, 2])]
    for amount in amounts:
        A = random_math_array([2, 2])
        A_copy = A.copy()
        A *= amount
        assert equal_as_arrays(A, A_copy * amount)
예제 #12
0
def test_in_place_subtraction():

    amounts = [0, random_math_array([2, 2])]
    for amount in amounts:
        A = random_math_array([2, 2])
        A_copy = A.copy()
        A -= amount
        assert equal_as_arrays(A, A_copy - amount)
예제 #13
0
def test_correct_arguments_get_passed_to_function():
    f = get_somefunc()

    w = np.random.uniform(-10, 10)
    x = random_math_array([2, 3])
    y = random_math_array([3])
    z = random_math_array([2])

    assert equal_as_arrays(f(w, x, y, z), w*x*y + z)
예제 #14
0
def test_math_arrays():
    A = MathArray([[1, 5], [4, -2]])
    v = MathArray([3, -2])
    n = 3
    x = 4.2
    z = 2 + 3j
    variables = {'A': A, 'v': v, 'n': n, 'x': x, 'z': z}

    expr = '(z*[[1, 5], [4, -2]]^n + 10*A/x)*v'
    result = evaluator(expr, variables, max_array_dim=2)[0]
    assert equal_as_arrays(result, (z * A**n + 10 * A / x) * v)
예제 #15
0
def test_vector_times_matrix_multiplication():
    u = MathArray([1, -2, 3])
    A = MathArray([[2, 4], [4, -3], [-1, 0]])
    b = MathArray([-9, 10])
    assert equal_as_arrays(u * A, b)
    assert b.ndim == 1  # result is a vector

    X = random_math_array(5)
    Y = random_math_array([4, 3])

    match = (r"Cannot multiply a vector of length 5 with a matrix of shape "
             r"\(rows: 4, cols: 3\)")
    with raises(ShapeError, match=match):
        X * Y
예제 #16
0
def test_nonpositive_matrix_powers():
    A = MathArray([[1, 5], [-4, 3]])
    I2 = MathArray([[1, 0], [0, 1]])

    # B is not invertible
    B = MathArray([[2, 1], [6, 3]])

    assert equal_as_arrays(A**0, I2)
    # Slight numerical errors in the inversion
    assert approx_equal_as_arrays(A**-2 * A**3, A, tol=1e-15)

    match = 'Cannot raise singular matrix to negative powers.'
    with raises(MathArrayError, match=match):
        B**-1
예제 #17
0
def test_addition_with_zero():
    A = MathArray([[5,  2, 1], [-2, 4, -3]])
    assert equal_as_arrays(A + 0, A)
    assert equal_as_arrays(0 + A, A)
    z0 = MathArray(0)
    assert equal_as_arrays(A + z0, A)
    assert equal_as_arrays(z0 + A, A)

    # This is ugly, but convenient for logic and implementation
    z3 = MathArray([[[0]]])
    assert equal_as_arrays(A + z3, A)
    assert equal_as_arrays(z3 + A, A)

    u = MathArray([1, 2])
    assert equal_as_arrays(u + 0, u)
    assert equal_as_arrays(0 + u, u)
예제 #18
0
def test_matrix_times_vector_multiplication():
    u = MathArray([1, -2, 3])
    A = MathArray([[2, 4, -1], [4, -3, 0]])
    b = MathArray([-9, 10])
    assert equal_as_arrays(A * u, b)
    assert b.ndim == 1  # result is a vector

    X = random_math_array([4, 3])
    Y = random_math_array(5)

    match = (
        r"Cannot multiply a matrix of shape \(rows: 4, cols: 3\) with a vector "
        r"of length 5.")
    with raises(ShapeError, match=match):
        X * Y
예제 #19
0
def test_array_input():
    """Test that vectors/matrices can be inputted into calc's evaluator"""
    result = evaluator("[1, 2, 3]", {}, {}, {}, max_array_dim=1)[0]
    assert equal_as_arrays(result, MathArray([1, 2, 3]))

    result = evaluator("[[1, 2], [3, 4]]", {}, {}, {}, max_array_dim=2)[0]
    assert equal_as_arrays(result, MathArray([[1, 2], [3, 4]]))

    expr = '[v, [4, 5, 6]]'
    result = evaluator(expr, {'v': MathArray([1, 2, 3])}, max_array_dim=2)[0]
    assert equal_as_arrays(result, MathArray([[1, 2, 3], [4, 5, 6]]))

    msg = "Vector and matrix expressions have been forbidden in this entry."
    with raises(UnableToParse, match=msg):
        evaluator("[[1, 2], [3, 4]]", {}, {}, {}, max_array_dim=0)
    msg = "Matrix expressions have been forbidden in this entry."
    with raises(UnableToParse, match=msg):
        evaluator("[[1, 2], [3, 4]]", {}, {}, {}, max_array_dim=1)
    msg = "Tensor expressions have been forbidden in this entry."
    with raises(UnableToParse, match=msg):
        evaluator("[[[1, 2], [3, 4]]]", {}, {}, {}, max_array_dim=2)

    # By default, this is fine
    evaluator("[[[1, 2], [3, 4]]]")
예제 #20
0
def test_scalar_product():
    X = MathArray([[1, 2, 3], [10, 20, 30]])
    two = MathArray(2)
    two3 = MathArray([[[2]]])
    Y = MathArray([[2, 4, 6], [20, 40, 60]])
    assert equal_as_arrays(2 * X, Y)
    assert equal_as_arrays(X * 2, Y)
    assert equal_as_arrays(two * X, Y)
    assert equal_as_arrays(X * two, Y)
    # This is ugly, but convenient for logic and implementation
    assert equal_as_arrays(two3 * X, Y)
    assert equal_as_arrays(X * two3, Y)
예제 #21
0
def test_matrix_power_works_with_floats_and_scalars_if_integral():
    A = random_math_array([3, 3])
    assert equal_as_arrays(A**2, A**2.0)
    assert equal_as_arrays(A**2, A**MathArray(2.0))
예제 #22
0
def test_identity_dim_provides_identity():
    no_identity = MatrixGrader()
    assert no_identity.constants.get('I', None) is None

    grader = MatrixGrader(identity_dim=4)
    assert equal_as_arrays(grader.constants['I'], identity(4))
예제 #23
0
def test_division_by_scalar():
    A = MathArray([4, 8])
    assert equal_as_arrays(A/2, MathArray([2, 4]))
    assert equal_as_arrays(A/MathArray(2), MathArray([2, 4]))

    assert 4/MathArray(2) == MathArray(2)
예제 #24
0
def test_copying():
    A = MathArray([1, 2, 3])
    assert equal_as_arrays(A, A.copy())