From 4d094d627acbd93a2c234dcf66e7ea5742bc6d9f Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Tue, 26 May 2020 23:29:24 -0400 Subject: [PATCH] Trac #33159: add special case to solve_right() for symbolic systems. Elements of SR remember whether or not they are exact, and if we are given a system consisting entirely of exact elements, then the checks for correctness in solve_left() and solve_right() need not be skipped as they are for other inexact rings. This commit adds a special case to the solve_right() method for matrices to handle SR with care, and includes an additional test case from Trac 29729. Since solve_left() is implemented in terms of solve_right(), both are addressed. --- src/sage/matrix/matrix2.pyx | 63 +++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 7d319bd54b9..a637f25c051 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -224,8 +224,8 @@ cdef class Matrix(Matrix1): - ``check`` -- boolean (default: ``True``); verify the answer if the system is non-square or rank-deficient, and if its - entries lie in an exact ring. Meaningless over inexact rings, - or when the system is square and of full rank. + entries lie in an exact ring. Meaningless over most inexact + rings, or when the system is square and of full rank. OUTPUT: @@ -239,12 +239,13 @@ cdef class Matrix(Matrix1): If the system is not square or does not have full rank, then a solution is attempted via other means. For example, over ``RDF`` or ``CDF`` a least-squares solution is returned, as - with MATLAB's "backslash" operator. For inexact rings, the + with MATLAB's "backslash" operator. For most inexact rings, the ``check`` parameter is ignored because an approximate solution will be returned in any case. Over exact rings, on the other hand, setting the ``check`` parameter results in an additional test to determine whether or not the answer actually solves the - system exactly. + system exactly. If a symbolic system involves only exact elements, + its solution can still be checked. If `B` is a vector, the result is returned as a vector, as well, and as a matrix, otherwise. @@ -395,6 +396,21 @@ cdef class Matrix(Matrix1): (0.5 - 1.5*I, 0.5 + 0.5*I) sage: b = vector(QQ[I], [1+I, 2]) sage: x = A.solve_left(b) + + Over the inexact ring ``SR``, we can still verify the solution + if all of the elements involved were exact to begin with; if + any are inexact, however, the ``check`` is still skipped + (:trac:`29729` and :trac:`33159`):: + + sage: A = matrix(SR, [[1, 1]]) + sage: b = vector(SR, [2, 3]) + sage: A.solve_left(b) + Traceback (most recent call last): + ... + ValueError: matrix equation has no solutions + sage: A.solve_left(b, check=False) + (2) + """ if is_Vector(B): try: @@ -433,8 +449,8 @@ cdef class Matrix(Matrix1): - ``check`` -- boolean (default: ``True``); verify the answer if the system is non-square or rank-deficient, and if its - entries lie in an exact ring. Meaningless over inexact rings, - or when the system is square and of full rank. + entries lie in an exact ring. Meaningless over most inexact + rings, or when the system is square and of full rank. OUTPUT: @@ -448,12 +464,13 @@ cdef class Matrix(Matrix1): If the system is not square or does not have full rank, then a solution is attempted via other means. For example, over ``RDF`` or ``CDF`` a least-squares solution is returned, as - with MATLAB's "backslash" operator. For inexact rings, the + with MATLAB's "backslash" operator. For most inexact rings, the ``check`` parameter is ignored because an approximate solution will be returned in any case. Over exact rings, on the other hand, setting the ``check`` parameter results in an additional test to determine whether or not the answer actually solves the - system exactly. + system exactly. If a symbolic system involves only exact elements, + its solution can still be checked. If `B` is a vector, the result is returned as a vector, as well, and as a matrix, otherwise. @@ -780,6 +797,23 @@ cdef class Matrix(Matrix1): sage: A = matrix(RF, [[0.24, 1, 0], [1, 0, 0]]) sage: 0 < (A * A.solve_right(B) - B).norm() < 1e-14 True + + Over the inexact ring ``SR``, we can still verify the solution + if all of the elements involved were exact to begin with; if + any are inexact, however, the ``check`` is still skipped + (:trac:`29729` and :trac:`33159`):: + + sage: m = matrix(SR, [0]) + sage: b = vector(SR, [1]) + sage: m.solve_right(b, check=True) + Traceback (most recent call last): + ... + ValueError: matrix equation has no solutions + sage: m.solve_right(b, check=False) + (0) + sage: m = matrix(SR, [0.0]) + sage: m.solve_right(b, check=True) + (0) """ try: L = B.base_ring() @@ -812,8 +846,17 @@ cdef class Matrix(Matrix1): K = P self = self.change_ring(P) - # If our field is inexact, checking the answer is doomed anyway. - check = (check and K.is_exact()) + # If our field is inexact, checking the answer is doomed in + # most cases. But here we handle the special ones. + from sage.symbolic.ring import SR + if K is SR: + # Elements of SR "remember" whether or not they are exact. + # If every element in the system is exact, we can probably + # still check the solution over the inexact ring SR. + check = (check and all( e.is_exact() + for e in self.list() + B.list() )) + else: + check = (check and K.is_exact()) if not K.is_integral_domain(): # The non-integral-domain case is handled almost entirely