コード例 #1
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_array_class_is_correct():
    """Tests two forms of MathArray creation actually create MathArray instances"""
    from_constructor = MathArray([[1, 2, 3], [4, 5, 6]])
    assert isinstance(from_constructor, MathArray)

    from_slice = MathArray([[1, 2, 3], [4, 5, 6]])[:, 2:3]
    assert isinstance(from_slice, MathArray)
コード例 #2
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_descriptions():
    scalar = MathArray(5)
    assert scalar.shape_name == 'scalar'
    assert scalar.description == 'scalar'
    assert scalar.shape == tuple()

    vector = MathArray([1, 2, 3, 4, 5])
    assert vector.shape_name == 'vector'
    assert vector.description == 'vector of length 5'
    assert vector.shape == (5,)

    matrix = MathArray([vector, vector, vector])
    assert matrix.shape_name == 'matrix'
    assert matrix.description == 'matrix of shape (rows: 3, cols: 5)'
    assert matrix.shape == (3, 5)


    tensor1 = MathArray([matrix, matrix, matrix, matrix])
    assert tensor1.shape_name == 'tensor'
    assert tensor1.description == 'tensor of shape (4, 3, 5)'
    assert tensor1.shape == (4, 3, 5)

    tensor2 = MathArray([tensor1, tensor1])
    assert tensor2.shape_name == 'tensor'
    assert tensor2.description == 'tensor of shape (2, 4, 3, 5)'
    assert tensor2.shape == (2, 4, 3, 5)
コード例 #3
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #4
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)
コード例 #5
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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
コード例 #6
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_vector_times_vector_is_dot_product():
    a = MathArray([1, 2, 3])
    b = MathArray([-2, 3, 4])
    c = MathArray([1, 2, 3, 4, 5])

    assert isinstance(a*b, Number)
    assert a*b == b*a == 16

    match = "Cannot calculate the dot product of a vector of length 3 with a vector of length 5"
    with raises(ShapeError, match=match):
        a*c
コード例 #7
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #8
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)
コード例 #9
0
ファイル: test_mathfuncs.py プロジェクト: bbadzioch/309_edX
def test_array_abs_input_types():
    array_abs = ARRAY_ONLY_FUNCTIONS['abs']

    x = random.uniform(0, 10)
    assert array_abs(x) == x
    assert array_abs(-x) == x

    assert array_abs(MathArray([2, -3, 6])) == 7

    match = ("The abs\(...\) function expects a scalar or vector. To take the "
             "norm of a matrix, try norm\(...\) instead.")
    with raises(FunctionEvalError, match=match):
        array_abs(MathArray([[1, 2], [3, 4]]))
コード例 #10
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
コード例 #11
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
コード例 #12
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
コード例 #13
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_subtraction_with_shape_mismath():
    # shape mismatch
    A = MathArray([[5,  2, 1], [-2, 4, -3]])
    B = MathArray([[2, -1], [3,  0]])
    match = ('Cannot add/subtract a matrix of shape \(rows: 2, cols: 3\) '
             'with a matrix of shape \(rows: 2, cols: 2\).')
    with raises(ShapeError, match=match):
        A - B

    # dimension mismatch
    u = MathArray([1, 2])
    match = ('Cannot add/subtract a vector of length 2 with a matrix of '
             'shape \(rows: 2, cols: 2\).')
    with raises(ShapeError, match=match):
        u - B
コード例 #14
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #15
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #16
0
ファイル: test_expressions.py プロジェクト: bbadzioch/309_edX
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}, {})
コード例 #17
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #18
0
ファイル: specify_domain.py プロジェクト: bbadzioch/309_edX
def get_shape_description(shape):
    """
    Get shape description from numpy shape tuple or string 'square'.
    """
    if shape == (1, ):
        return 'scalar'
    elif shape == 'square':
        return 'square matrix'

    return MathArray.get_description(shape)
コード例 #19
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_addition_with_other_types():
    A = MathArray([[5, 2], [-2, 4]])
    match = "Cannot add/subtract scalars to a matrix."
    with raises(ShapeError, match=match):
        A + 1
    with raises(ShapeError, match=match):
        A + 1.0
    with raises(ShapeError, match=match):
        A + (1 + 2j)
    with raises(TypeError, match="Cannot add/subtract a matrix with object of "
                "<type 'list'>"):
        A + [[1, 2], [4, 5]]
コード例 #20
0
def test_subtraction_with_other_types():
    A = MathArray([[5, 2], [-2, 4]])

    match = "Cannot add/subtract scalars to a matrix."
    with raises(ShapeError, match=match):
        A - 1
    with raises(ShapeError, match=match):
        A - 1.0
    with raises(ShapeError, match=match):
        A - (1 + 2j)
    with raises(TypeError,
                match="Cannot add/subtract a matrix with object of "
                "{list_type}".format(list_type=list)):
        A - [[1, 2], [4, 5]]
コード例 #21
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_division_by_array_raises_error():
    A = MathArray([4, 8])

    match = "Cannot divide by a vector"
    with raises(ShapeError, match=match):
        2/A

    match = "Cannot divide a vector by a vector"
    with raises(ShapeError, match=match):
        A/A

    match = "Cannot divide vector by object of <type 'list'>"
    with raises(TypeError, match=match):
        A/[1, 2, 3]
コード例 #22
0
def array_abs(obj):
    """
    Takes absolute value of numbers or vectors and suggests norm(...) instead
    for matrix/tensors.

    NOTE: The decision to limit abs(...) to scalars and vectors was motivated
    by pedagogy not software.
    """
    if isinstance(obj, MathArray) and obj.ndim > 1:
        msg = ("The abs(...) function expects a scalar or vector. To take the "
               "norm of a {}, try norm(...) instead.".format(
                   MathArray.get_shape_name(obj.ndim)))
        raise FunctionEvalError(msg)
    return np.linalg.norm(obj)
コード例 #23
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_scalar_special_cases():
    five = MathArray(5)
    three = MathArray(3)
    # Addition
    assert five + three == 8
    assert five + 3 == 8
    assert 5 + three == 8
    # Subtraction
    assert five - three == 2
    assert five - 3 == 2
    assert 5 - three == 2
    # Powers
    assert five**3 == 125
    assert 5**three == 125
    assert five**three == 125

    # With MathArrays on the right:
    match = "Cannot raise a scalar to a <type 'list'> power"
    with raises(TypeError, match=match):
        MathArray(2)**[1, 2, 3]

    match = 'Cannot raise a scalar to power of a vector.'
    with raises(ShapeError, match=match):
        MathArray(2)**MathArray([1, 2, 3])
コード例 #24
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #25
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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)
コード例 #26
0
    def eval_array(parse_result, metadata_dict):
        """
        Takes in a list of evaluated expressions and returns it as a MathArray.
        May mutate metadata_dict.

        If passed a list of numpy arrays, generates a matrix/tensor/etc.

        Arguments:
            parse_result: A list containing each element of the array
            metadata_dict: A dictionary with key 'max_array_dim_used', whose
                value should be an integer. If the result of eval_array has higher
                dimension than 'max_array_dim_used', this value will be updated.

        Usage
        =====
        Returns MathArray instances and updates metadata_dict['max_array_dim_used']
        if needed:
        >>> metadata_dict = { 'max_array_dim_used': 0 }
        >>> MathExpression.eval_array([1, 2, 3], metadata_dict)
        MathArray([1, 2, 3])
        >>> metadata_dict['max_array_dim_used']
        1

        If metadata_dict['max_array_dim_used'] is larger than returned array value,
        then metadata_dict is not updated:
        >>> metadata_dict = { 'max_array_dim_used': 2 }
        >>> MathExpression.eval_array([1, 2, 3], metadata_dict)
        MathArray([1, 2, 3])
        >>> metadata_dict['max_array_dim_used']
        2

        >>> metadata_dict = { 'max_array_dim_used': 0 }
        >>> MathExpression.eval_array([         # doctest: +NORMALIZE_WHITESPACE
        ...     [1 , 2],
        ...     [3, 4]
        ... ], metadata_dict)
        MathArray([[1,  2],
                [3,  4]])

        In practice, this is called recursively:
        >>> metadata_dict = { 'max_array_dim_used': 0 }
        >>> MathExpression.eval_array([         # doctest: +NORMALIZE_WHITESPACE
        ...     MathExpression.eval_array([1, 2, 3], metadata_dict),
        ...     MathExpression.eval_array([4, 5, 6], metadata_dict)
        ... ], metadata_dict)
        MathArray([[1, 2, 3],
               [4, 5, 6]])
        >>> metadata_dict['max_array_dim_used']
        2

        One complex entry will convert everything to complex:
        >>> metadata_dict = { 'max_array_dim_used': 0 }
        >>> MathExpression.eval_array([         # doctest: +NORMALIZE_WHITESPACE
        ...     MathExpression.eval_array([1, 2j, 3], metadata_dict),
        ...     MathExpression.eval_array([4, 5, 6], metadata_dict)
        ... ], metadata_dict)
        MathArray([[ 1.+0.j,  0.+2.j,  3.+0.j],
               [ 4.+0.j,  5.+0.j,  6.+0.j]])

        We try to detect shape errors:
        >>> metadata_dict = { 'max_array_dim_used': 0 }
        >>> try:                                            # doctest: +ELLIPSIS
        ...     MathExpression.eval_array([
        ...         MathExpression.eval_array([1, 2, 3], metadata_dict),
        ...         4
        ...     ], metadata_dict)
        ... except UnableToParse as error:
        ...     print(error)
        Unable to parse vector/matrix. If you're trying ...
        >>> metadata_dict = { 'max_array_dim_used': 0 }
        >>> try:                                            # doctest: +ELLIPSIS
        ...     MathExpression.eval_array([
        ...         2.0,
        ...         MathExpression.eval_array([1, 2, 3], metadata_dict),
        ...         4
        ...     ], metadata_dict)
        ... except UnableToParse as error:
        ...     print(error)
        Unable to parse vector/matrix. If you're trying ...
        """
        shape_message = ("Unable to parse vector/matrix. If you're trying to "
                         "enter a matrix, this is most likely caused by an "
                         "unequal number of elements in each row.")

        try:
            array = MathArray(parse_result)
        except ValueError:
            # This happens, for example, with np.array([1, 2, [3]])
            # when using numpy version 1.6
            raise UnableToParse(shape_message)

        if array.dtype == 'object':
            # This happens, for example, with np.array([[1], 2, 3]),
            # OR with with np.array([1, 2, [3]]) in recent versions of numpy
            raise UnableToParse(shape_message)

        if array.ndim > metadata_dict['max_array_dim_used']:
            metadata_dict['max_array_dim_used'] = array.ndim

        return array
コード例 #27
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
def test_copying():
    A = MathArray([1, 2, 3])
    assert equal_as_arrays(A, A.copy())
コード例 #28
0
def cross(a, b):
    return MathArray([
        a[1] * b[2] - b[1] * a[2], a[2] * b[0] - b[2] * a[0],
        a[0] * b[1] - b[0] * a[1]
    ])
コード例 #29
0
DEFAULT_SUFFIXES = {'%': 0.01}

METRIC_SUFFIXES = {
    'k': 1e3,
    'M': 1e6,
    'G': 1e9,
    'T': 1e12,
    'm': 1e-3,
    'u': 1e-6,
    'n': 1e-9,
    'p': 1e-12
}

pauli = {
    'sigma_x': MathArray([[0, 1], [1, 0]]),
    'sigma_y': MathArray([[0, -1j], [1j, 0]]),
    'sigma_z': MathArray([[1, 0], [0, -1]])
}

cartesian_xyz = {
    'hatx': MathArray([1, 0, 0]),
    'haty': MathArray([0, 1, 0]),
    'hatz': MathArray([0, 0, 1])
}

cartesian_ijk = {
    'hati': MathArray([1, 0, 0]),
    'hatj': MathArray([0, 1, 0]),
    'hatk': MathArray([0, 0, 1])
}
コード例 #30
0
ファイル: test_math_array.py プロジェクト: bbadzioch/309_edX
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))