def test_shape_errors_false_grades_incorrect(): grader0 = MatrixGrader(answers='A*B', variables=['A', 'B'], sample_from={ 'A': RealMatrices(shape=[2, 3]), 'B': RealMatrices(shape=[3, 2]) }) grader1 = MatrixGrader(answers='A*B', variables=['A', 'B'], sample_from={ 'A': RealMatrices(shape=[2, 3]), 'B': RealMatrices(shape=[3, 2]) }, shape_errors=False) msg = ("Cannot add/subtract a matrix of shape (rows: 2, cols: 3) with " "a matrix of shape (rows: 3, cols: 2).") with raises(ShapeError, match=re.escape(msg)): grader0(None, 'A + B') assert grader1(None, 'A + B') == { 'ok': False, 'msg': msg, 'grade_decimal': 0 }
def test_matrix_inverses_raise_error_if_disabled(): grader = MatrixGrader(answers='A^2', variables=['A'], sample_from={'A': RealMatrices()}, negative_powers=False) match = 'Negative matrix powers have been disabled.' with raises(MathArrayError, match=match): grader(None, 'A^3*A^-1')['ok']
def test_works_with_matrixgrader(): grader = MatrixGrader(answers={ 'comparer_params': ['x*A*B^2'], 'comparer': LinearComparer(proportional=0.6, offset=0.4, linear=0.2) }, variables=['x', 'A', 'B'], sample_from={ 'A': RealMatrices(), 'B': RealMatrices() }, max_array_dim=2) assert grader(None, 'x*A*B^2')['grade_decimal'] == 1.0 assert grader(None, '2*x*A*B^2')['grade_decimal'] == 0.6 assert grader(None, 'x*A*B^2 + 5*[[1, 1], [1, 1]]')['grade_decimal'] == 0.4 assert grader(None, '3*x*A*B^2 + 5*[[1, 1], [1, 1]]')['grade_decimal'] == 0.2 assert grader(None, 'x*A*B^2 + x*[[1, 1], [1, 1]]')['grade_decimal'] == 0 assert grader(None, '0*A')['grade_decimal'] == 0
def test_fg_with_arrays(): grader = MatrixGrader(answers='x*A*B*u + z*C^3*v/(u*C*v)', variables=['A', 'B', 'C', 'u', 'v', 'z', 'x'], sample_from={ 'A': RealMatrices(shape=[2, 3]), 'B': RealMatrices(shape=[3, 2]), 'C': RealMatrices(shape=[2, 2]), 'u': RealVectors(shape=[2]), 'v': RealVectors(shape=[2]), 'z': ComplexRectangle() }, identity_dim=2) correct_0 = 'x*A*B*u + z*C^3*v/(u*C*v)' correct_1 = 'z*C^3*v/(u*C*v) + x*A*B*u' correct_2 = '(1/16)* z*(2*I)*(2*C)^3*v/(u*C*v) + x*A*B*u' correct_3 = '(1/16)* z*(2*I)*(2*C)^3*v/(v*trans(C)*u) + x*A*B*u/2 + 0.5*x*A*B*u' assert grader(None, correct_0)['ok'] assert grader(None, correct_1)['ok'] assert grader(None, correct_2)['ok'] assert grader(None, correct_3)['ok'] match = r"Cannot multiply a matrix of shape \(rows: 3, cols: 2\) with a matrix of shape \(rows: 3, cols: 2\)" with raises(ShapeError, match=match): grader(None, 'B*B') match = "Cannot raise a non-square matrix to powers." with raises(ShapeError, match=match): grader(None, 'B^2') match = "Cannot add/subtract scalars to a matrix." with raises(ShapeError, match=match): grader(None, 'B + 5') match = (r"There was an error evaluating function sin\(...\)<br/>" r"1st input has an error: received a matrix of shape " r"\(rows: 3, cols: 2\), expected a scalar") with raises(DomainError, match=match): grader(None, 'sin(B)')
def test_general_matrices(): # Test shape, real/complex, norm, triangular options, MathArray shapes = product(tuple(range(2, 5)), tuple(range(2, 5))) norms = ([2, 6], [3, 4], [4, 12], [1 - 1e-12, 1 + 1e-12]) triangles = (None, 'upper', 'lower') for shape in shapes: for norm in norms: for triangle in triangles: matrices = RealMatrices(shape=shape, norm=norm, triangular=triangle) m = matrices.gen_sample() assert m.shape == shape assert norm[0] <= np.linalg.norm(m) <= norm[1] assert np.array_equal(np.conj(m), m) assert isinstance(m, MathArray) if triangle is None: assert not within_tolerance(m, MathArray(np.triu(m)), 0) assert not within_tolerance(m, MathArray(np.tril(m)), 0) elif triangle == "upper": assert within_tolerance(m, MathArray(np.triu(m)), 0) elif triangle == "lower": assert within_tolerance(m, MathArray(np.tril(m)), 0) matrices = ComplexMatrices(shape=shape, norm=norm, triangular=triangle) m = matrices.gen_sample() assert m.shape == shape assert norm[0] <= np.linalg.norm(m) <= norm[1] assert not np.array_equal(np.conj(m), m) assert isinstance(m, MathArray) if triangle is None: assert not within_tolerance(m, MathArray(np.triu(m)), 0) assert not within_tolerance(m, MathArray(np.tril(m)), 0) elif triangle == "upper": assert within_tolerance(m, MathArray(np.triu(m)), 0) elif triangle == "lower": assert within_tolerance(m, MathArray(np.tril(m)), 0)
def test_matrix_inverses_work_if_not_disabled(): grader = MatrixGrader(answers='A^2', variables=['A'], sample_from={'A': RealMatrices()}) assert grader(None, 'A^3*A^-1')['ok']