74 lines
3 KiB
Python
74 lines
3 KiB
Python
from mcp_calculator.config import Limits
|
|
from mcp_calculator.ops.context import MathError, set_limits
|
|
from mcp_calculator.ops.linalg import matrix
|
|
from tests.support import MathTestCase
|
|
|
|
A = [[1, 2], [3, 4]]
|
|
|
|
|
|
class ExactMatrixTest(MathTestCase):
|
|
def test_determinant(self):
|
|
self.assertEqual(matrix("determinant", A)["result"], "-2")
|
|
|
|
def test_symbolic_determinant(self):
|
|
self.assertEqual(matrix("determinant", [["a", "b"], ["c", "d"]])["result"], "a*d - b*c")
|
|
|
|
def test_inverse_is_exact(self):
|
|
self.assertEqual(matrix("inverse", A)["result"], [["-2", "1"], ["3/2", "-1/2"]])
|
|
|
|
def test_singular_inverse(self):
|
|
with self.assertRaisesRegex(MathError, "singular"):
|
|
matrix("inverse", [[1, 2], [2, 4]])
|
|
|
|
def test_eigenvalues(self):
|
|
values = {e["value"] for e in matrix("eigenvalues", [[2, 1], [1, 2]])["result"]}
|
|
self.assertEqual(values, {"1", "3"})
|
|
|
|
def test_eigenvectors(self):
|
|
r = matrix("eigenvectors", [[2, 0], [0, 3]])["result"]
|
|
self.assertEqual({e["value"]: e["vectors"] for e in r}, {"2": [["1", "0"]], "3": [["0", "1"]]})
|
|
|
|
def test_solve_linear_system(self):
|
|
self.assertEqual(matrix("solve", [[1, 1], [1, -1]], [10, 2])["result"], [["6"], ["4"]])
|
|
|
|
def test_solve_inconsistent(self):
|
|
self.assertIsNone(matrix("solve", [[1, 1], [1, 1]], [1, 2])["result"])
|
|
|
|
def test_multiply_and_shapes(self):
|
|
self.assertEqual(matrix("multiply", A, [[1], [1]])["result"], [["3"], ["7"]])
|
|
with self.assertRaisesRegex(MathError, "not compatible"):
|
|
matrix("multiply", A, [[1, 2, 3]])
|
|
|
|
def test_power_rank_trace_transpose(self):
|
|
self.assertEqual(matrix("power", A, exponent=2)["result"], [["7", "10"], ["15", "22"]])
|
|
self.assertEqual(matrix("rank", [[1, 2], [2, 4]])["result"], 1)
|
|
self.assertEqual(matrix("trace", A)["result"], "5")
|
|
self.assertEqual(matrix("transpose", A)["result"], [["1", "3"], ["2", "4"]])
|
|
|
|
def test_vectors(self):
|
|
self.assertEqual(matrix("dot", [1, 2, 3], [4, 5, 6])["result"], "32")
|
|
self.assertEqual(matrix("cross", [1, 0, 0], [0, 1, 0])["result"], [["0"], ["0"], ["1"]])
|
|
|
|
def test_characteristic_polynomial(self):
|
|
self.assertEqual(matrix("characteristic_polynomial", A)["result"], "lambda**2 - 5*lambda - 2")
|
|
|
|
|
|
class NumericMatrixTest(MathTestCase):
|
|
def test_numeric_mode(self):
|
|
r = matrix("determinant", A, numeric_mode=True)
|
|
self.assertTrue(r["mode"].startswith("numeric"))
|
|
self.assertApprox(r["result"], -2)
|
|
|
|
def test_svd_is_numeric(self):
|
|
self.assertEqual(len(matrix("svd", A)["singular_values"]), 2)
|
|
|
|
|
|
class MatrixValidationTest(MathTestCase):
|
|
def test_size_limit(self):
|
|
set_limits(Limits(max_matrix_size=2))
|
|
with self.assertRaisesRegex(MathError, "larger than"):
|
|
matrix("determinant", [[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
|
|
def test_ragged_rows(self):
|
|
with self.assertRaisesRegex(MathError, "same length"):
|
|
matrix("determinant", [[1, 2], [3]])
|