123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862 |
- from sympy.core.function import expand_mul
- from sympy.core.symbol import Dummy, uniquely_named_symbol, symbols
- from sympy.utilities.iterables import numbered_symbols
- from .common import ShapeError, NonSquareMatrixError, NonInvertibleMatrixError
- from .eigen import _fuzzy_positive_definite
- from .utilities import _get_intermediate_simp, _iszero
- def _diagonal_solve(M, rhs):
- """Solves ``Ax = B`` efficiently, where A is a diagonal Matrix,
- with non-zero diagonal entries.
- Examples
- ========
- >>> from sympy import Matrix, eye
- >>> A = eye(2)*2
- >>> B = Matrix([[1, 2], [3, 4]])
- >>> A.diagonal_solve(B) == B/2
- True
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv_solve
- """
- if not M.is_diagonal():
- raise TypeError("Matrix should be diagonal")
- if rhs.rows != M.rows:
- raise TypeError("Size mis-match")
- return M._new(
- rhs.rows, rhs.cols, lambda i, j: rhs[i, j] / M[i, i])
- def _lower_triangular_solve(M, rhs):
- """Solves ``Ax = B``, where A is a lower triangular matrix.
- See Also
- ========
- upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv_solve
- """
- from .dense import MutableDenseMatrix
- if not M.is_square:
- raise NonSquareMatrixError("Matrix must be square.")
- if rhs.rows != M.rows:
- raise ShapeError("Matrices size mismatch.")
- if not M.is_lower:
- raise ValueError("Matrix must be lower triangular.")
- dps = _get_intermediate_simp()
- X = MutableDenseMatrix.zeros(M.rows, rhs.cols)
- for j in range(rhs.cols):
- for i in range(M.rows):
- if M[i, i] == 0:
- raise TypeError("Matrix must be non-singular.")
- X[i, j] = dps((rhs[i, j] - sum(M[i, k]*X[k, j]
- for k in range(i))) / M[i, i])
- return M._new(X)
- def _lower_triangular_solve_sparse(M, rhs):
- """Solves ``Ax = B``, where A is a lower triangular matrix.
- See Also
- ========
- upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv_solve
- """
- if not M.is_square:
- raise NonSquareMatrixError("Matrix must be square.")
- if rhs.rows != M.rows:
- raise ShapeError("Matrices size mismatch.")
- if not M.is_lower:
- raise ValueError("Matrix must be lower triangular.")
- dps = _get_intermediate_simp()
- rows = [[] for i in range(M.rows)]
- for i, j, v in M.row_list():
- if i > j:
- rows[i].append((j, v))
- X = rhs.as_mutable()
- for j in range(rhs.cols):
- for i in range(rhs.rows):
- for u, v in rows[i]:
- X[i, j] -= v*X[u, j]
- X[i, j] = dps(X[i, j] / M[i, i])
- return M._new(X)
- def _upper_triangular_solve(M, rhs):
- """Solves ``Ax = B``, where A is an upper triangular matrix.
- See Also
- ========
- lower_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv_solve
- """
- from .dense import MutableDenseMatrix
- if not M.is_square:
- raise NonSquareMatrixError("Matrix must be square.")
- if rhs.rows != M.rows:
- raise ShapeError("Matrix size mismatch.")
- if not M.is_upper:
- raise TypeError("Matrix is not upper triangular.")
- dps = _get_intermediate_simp()
- X = MutableDenseMatrix.zeros(M.rows, rhs.cols)
- for j in range(rhs.cols):
- for i in reversed(range(M.rows)):
- if M[i, i] == 0:
- raise ValueError("Matrix must be non-singular.")
- X[i, j] = dps((rhs[i, j] - sum(M[i, k]*X[k, j]
- for k in range(i + 1, M.rows))) / M[i, i])
- return M._new(X)
- def _upper_triangular_solve_sparse(M, rhs):
- """Solves ``Ax = B``, where A is an upper triangular matrix.
- See Also
- ========
- lower_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv_solve
- """
- if not M.is_square:
- raise NonSquareMatrixError("Matrix must be square.")
- if rhs.rows != M.rows:
- raise ShapeError("Matrix size mismatch.")
- if not M.is_upper:
- raise TypeError("Matrix is not upper triangular.")
- dps = _get_intermediate_simp()
- rows = [[] for i in range(M.rows)]
- for i, j, v in M.row_list():
- if i < j:
- rows[i].append((j, v))
- X = rhs.as_mutable()
- for j in range(rhs.cols):
- for i in reversed(range(rhs.rows)):
- for u, v in reversed(rows[i]):
- X[i, j] -= v*X[u, j]
- X[i, j] = dps(X[i, j] / M[i, i])
- return M._new(X)
- def _cholesky_solve(M, rhs):
- """Solves ``Ax = B`` using Cholesky decomposition,
- for a general square non-singular matrix.
- For a non-square matrix with rows > cols,
- the least squares solution is returned.
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- gauss_jordan_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv_solve
- """
- if M.rows < M.cols:
- raise NotImplementedError(
- 'Under-determined System. Try M.gauss_jordan_solve(rhs)')
- hermitian = True
- reform = False
- if M.is_symmetric():
- hermitian = False
- elif not M.is_hermitian:
- reform = True
- if reform or _fuzzy_positive_definite(M) is False:
- H = M.H
- M = H.multiply(M)
- rhs = H.multiply(rhs)
- hermitian = not M.is_symmetric()
- L = M.cholesky(hermitian=hermitian)
- Y = L.lower_triangular_solve(rhs)
- if hermitian:
- return (L.H).upper_triangular_solve(Y)
- else:
- return (L.T).upper_triangular_solve(Y)
- def _LDLsolve(M, rhs):
- """Solves ``Ax = B`` using LDL decomposition,
- for a general square and non-singular matrix.
- For a non-square matrix with rows > cols,
- the least squares solution is returned.
- Examples
- ========
- >>> from sympy import Matrix, eye
- >>> A = eye(2)*2
- >>> B = Matrix([[1, 2], [3, 4]])
- >>> A.LDLsolve(B) == B/2
- True
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.LDLdecomposition
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LUsolve
- QRsolve
- pinv_solve
- """
- if M.rows < M.cols:
- raise NotImplementedError(
- 'Under-determined System. Try M.gauss_jordan_solve(rhs)')
- hermitian = True
- reform = False
- if M.is_symmetric():
- hermitian = False
- elif not M.is_hermitian:
- reform = True
- if reform or _fuzzy_positive_definite(M) is False:
- H = M.H
- M = H.multiply(M)
- rhs = H.multiply(rhs)
- hermitian = not M.is_symmetric()
- L, D = M.LDLdecomposition(hermitian=hermitian)
- Y = L.lower_triangular_solve(rhs)
- Z = D.diagonal_solve(Y)
- if hermitian:
- return (L.H).upper_triangular_solve(Z)
- else:
- return (L.T).upper_triangular_solve(Z)
- def _LUsolve(M, rhs, iszerofunc=_iszero):
- """Solve the linear system ``Ax = rhs`` for ``x`` where ``A = M``.
- This is for symbolic matrices, for real or complex ones use
- mpmath.lu_solve or mpmath.qr_solve.
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- QRsolve
- pinv_solve
- LUdecomposition
- """
- if rhs.rows != M.rows:
- raise ShapeError(
- "``M`` and ``rhs`` must have the same number of rows.")
- m = M.rows
- n = M.cols
- if m < n:
- raise NotImplementedError("Underdetermined systems not supported.")
- try:
- A, perm = M.LUdecomposition_Simple(
- iszerofunc=_iszero, rankcheck=True)
- except ValueError:
- raise NonInvertibleMatrixError("Matrix det == 0; not invertible.")
- dps = _get_intermediate_simp()
- b = rhs.permute_rows(perm).as_mutable()
- # forward substitution, all diag entries are scaled to 1
- for i in range(m):
- for j in range(min(i, n)):
- scale = A[i, j]
- b.zip_row_op(i, j, lambda x, y: dps(x - y * scale))
- # consistency check for overdetermined systems
- if m > n:
- for i in range(n, m):
- for j in range(b.cols):
- if not iszerofunc(b[i, j]):
- raise ValueError("The system is inconsistent.")
- b = b[0:n, :] # truncate zero rows if consistent
- # backward substitution
- for i in range(n - 1, -1, -1):
- for j in range(i + 1, n):
- scale = A[i, j]
- b.zip_row_op(i, j, lambda x, y: dps(x - y * scale))
- scale = A[i, i]
- b.row_op(i, lambda x, _: dps(x / scale))
- return rhs.__class__(b)
- def _QRsolve(M, b):
- """Solve the linear system ``Ax = b``.
- ``M`` is the matrix ``A``, the method argument is the vector
- ``b``. The method returns the solution vector ``x``. If ``b`` is a
- matrix, the system is solved for each column of ``b`` and the
- return value is a matrix of the same shape as ``b``.
- This method is slower (approximately by a factor of 2) but
- more stable for floating-point arithmetic than the LUsolve method.
- However, LUsolve usually uses an exact arithmetic, so you do not need
- to use QRsolve.
- This is mainly for educational purposes and symbolic matrices, for real
- (or complex) matrices use mpmath.qr_solve.
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- pinv_solve
- QRdecomposition
- """
- dps = _get_intermediate_simp(expand_mul, expand_mul)
- Q, R = M.QRdecomposition()
- y = Q.T * b
- # back substitution to solve R*x = y:
- # We build up the result "backwards" in the vector 'x' and reverse it
- # only in the end.
- x = []
- n = R.rows
- for j in range(n - 1, -1, -1):
- tmp = y[j, :]
- for k in range(j + 1, n):
- tmp -= R[j, k] * x[n - 1 - k]
- tmp = dps(tmp)
- x.append(tmp / R[j, j])
- return M.vstack(*x[::-1])
- def _gauss_jordan_solve(M, B, freevar=False):
- """
- Solves ``Ax = B`` using Gauss Jordan elimination.
- There may be zero, one, or infinite solutions. If one solution
- exists, it will be returned. If infinite solutions exist, it will
- be returned parametrically. If no solutions exist, It will throw
- ValueError.
- Parameters
- ==========
- B : Matrix
- The right hand side of the equation to be solved for. Must have
- the same number of rows as matrix A.
- freevar : boolean, optional
- Flag, when set to `True` will return the indices of the free
- variables in the solutions (column Matrix), for a system that is
- undetermined (e.g. A has more columns than rows), for which
- infinite solutions are possible, in terms of arbitrary
- values of free variables. Default `False`.
- Returns
- =======
- x : Matrix
- The matrix that will satisfy ``Ax = B``. Will have as many rows as
- matrix A has columns, and as many columns as matrix B.
- params : Matrix
- If the system is underdetermined (e.g. A has more columns than
- rows), infinite solutions are possible, in terms of arbitrary
- parameters. These arbitrary parameters are returned as params
- Matrix.
- free_var_index : List, optional
- If the system is underdetermined (e.g. A has more columns than
- rows), infinite solutions are possible, in terms of arbitrary
- values of free variables. Then the indices of the free variables
- in the solutions (column Matrix) are returned by free_var_index,
- if the flag `freevar` is set to `True`.
- Examples
- ========
- >>> from sympy import Matrix
- >>> A = Matrix([[1, 2, 1, 1], [1, 2, 2, -1], [2, 4, 0, 6]])
- >>> B = Matrix([7, 12, 4])
- >>> sol, params = A.gauss_jordan_solve(B)
- >>> sol
- Matrix([
- [-2*tau0 - 3*tau1 + 2],
- [ tau0],
- [ 2*tau1 + 5],
- [ tau1]])
- >>> params
- Matrix([
- [tau0],
- [tau1]])
- >>> taus_zeroes = { tau:0 for tau in params }
- >>> sol_unique = sol.xreplace(taus_zeroes)
- >>> sol_unique
- Matrix([
- [2],
- [0],
- [5],
- [0]])
- >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
- >>> B = Matrix([3, 6, 9])
- >>> sol, params = A.gauss_jordan_solve(B)
- >>> sol
- Matrix([
- [-1],
- [ 2],
- [ 0]])
- >>> params
- Matrix(0, 1, [])
- >>> A = Matrix([[2, -7], [-1, 4]])
- >>> B = Matrix([[-21, 3], [12, -2]])
- >>> sol, params = A.gauss_jordan_solve(B)
- >>> sol
- Matrix([
- [0, -2],
- [3, -1]])
- >>> params
- Matrix(0, 2, [])
- >>> from sympy import Matrix
- >>> A = Matrix([[1, 2, 1, 1], [1, 2, 2, -1], [2, 4, 0, 6]])
- >>> B = Matrix([7, 12, 4])
- >>> sol, params, freevars = A.gauss_jordan_solve(B, freevar=True)
- >>> sol
- Matrix([
- [-2*tau0 - 3*tau1 + 2],
- [ tau0],
- [ 2*tau1 + 5],
- [ tau1]])
- >>> params
- Matrix([
- [tau0],
- [tau1]])
- >>> freevars
- [1, 3]
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Gaussian_elimination
- """
- from sympy.matrices import Matrix, zeros
- cls = M.__class__
- aug = M.hstack(M.copy(), B.copy())
- B_cols = B.cols
- row, col = aug[:, :-B_cols].shape
- # solve by reduced row echelon form
- A, pivots = aug.rref(simplify=True)
- A, v = A[:, :-B_cols], A[:, -B_cols:]
- pivots = list(filter(lambda p: p < col, pivots))
- rank = len(pivots)
- # Get index of free symbols (free parameters)
- # non-pivots columns are free variables
- free_var_index = [c for c in range(A.cols) if c not in pivots]
- # Bring to block form
- permutation = Matrix(pivots + free_var_index).T
- # check for existence of solutions
- # rank of aug Matrix should be equal to rank of coefficient matrix
- if not v[rank:, :].is_zero_matrix:
- raise ValueError("Linear system has no solution")
- # Free parameters
- # what are current unnumbered free symbol names?
- name = uniquely_named_symbol('tau', aug,
- compare=lambda i: str(i).rstrip('1234567890'),
- modify=lambda s: '_' + s).name
- gen = numbered_symbols(name)
- tau = Matrix([next(gen) for k in range((col - rank)*B_cols)]).reshape(
- col - rank, B_cols)
- # Full parametric solution
- V = A[:rank, free_var_index]
- vt = v[:rank, :]
- free_sol = tau.vstack(vt - V * tau, tau)
- # Undo permutation
- sol = zeros(col, B_cols)
- for k in range(col):
- sol[permutation[k], :] = free_sol[k,:]
- sol, tau = cls(sol), cls(tau)
- if freevar:
- return sol, tau, free_var_index
- else:
- return sol, tau
- def _pinv_solve(M, B, arbitrary_matrix=None):
- """Solve ``Ax = B`` using the Moore-Penrose pseudoinverse.
- There may be zero, one, or infinite solutions. If one solution
- exists, it will be returned. If infinite solutions exist, one will
- be returned based on the value of arbitrary_matrix. If no solutions
- exist, the least-squares solution is returned.
- Parameters
- ==========
- B : Matrix
- The right hand side of the equation to be solved for. Must have
- the same number of rows as matrix A.
- arbitrary_matrix : Matrix
- If the system is underdetermined (e.g. A has more columns than
- rows), infinite solutions are possible, in terms of an arbitrary
- matrix. This parameter may be set to a specific matrix to use
- for that purpose; if so, it must be the same shape as x, with as
- many rows as matrix A has columns, and as many columns as matrix
- B. If left as None, an appropriate matrix containing dummy
- symbols in the form of ``wn_m`` will be used, with n and m being
- row and column position of each symbol.
- Returns
- =======
- x : Matrix
- The matrix that will satisfy ``Ax = B``. Will have as many rows as
- matrix A has columns, and as many columns as matrix B.
- Examples
- ========
- >>> from sympy import Matrix
- >>> A = Matrix([[1, 2, 3], [4, 5, 6]])
- >>> B = Matrix([7, 8])
- >>> A.pinv_solve(B)
- Matrix([
- [ _w0_0/6 - _w1_0/3 + _w2_0/6 - 55/18],
- [-_w0_0/3 + 2*_w1_0/3 - _w2_0/3 + 1/9],
- [ _w0_0/6 - _w1_0/3 + _w2_0/6 + 59/18]])
- >>> A.pinv_solve(B, arbitrary_matrix=Matrix([0, 0, 0]))
- Matrix([
- [-55/18],
- [ 1/9],
- [ 59/18]])
- See Also
- ========
- sympy.matrices.dense.DenseMatrix.lower_triangular_solve
- sympy.matrices.dense.DenseMatrix.upper_triangular_solve
- gauss_jordan_solve
- cholesky_solve
- diagonal_solve
- LDLsolve
- LUsolve
- QRsolve
- pinv
- Notes
- =====
- This may return either exact solutions or least squares solutions.
- To determine which, check ``A * A.pinv() * B == B``. It will be
- True if exact solutions exist, and False if only a least-squares
- solution exists. Be aware that the left hand side of that equation
- may need to be simplified to correctly compare to the right hand
- side.
- References
- ==========
- .. [1] https://en.wikipedia.org/wiki/Moore-Penrose_pseudoinverse#Obtaining_all_solutions_of_a_linear_system
- """
- from sympy.matrices import eye
- A = M
- A_pinv = M.pinv()
- if arbitrary_matrix is None:
- rows, cols = A.cols, B.cols
- w = symbols('w:{}_:{}'.format(rows, cols), cls=Dummy)
- arbitrary_matrix = M.__class__(cols, rows, w).T
- return A_pinv.multiply(B) + (eye(A.cols) -
- A_pinv.multiply(A)).multiply(arbitrary_matrix)
- def _solve(M, rhs, method='GJ'):
- """Solves linear equation where the unique solution exists.
- Parameters
- ==========
- rhs : Matrix
- Vector representing the right hand side of the linear equation.
- method : string, optional
- If set to ``'GJ'`` or ``'GE'``, the Gauss-Jordan elimination will be
- used, which is implemented in the routine ``gauss_jordan_solve``.
- If set to ``'LU'``, ``LUsolve`` routine will be used.
- If set to ``'QR'``, ``QRsolve`` routine will be used.
- If set to ``'PINV'``, ``pinv_solve`` routine will be used.
- It also supports the methods available for special linear systems
- For positive definite systems:
- If set to ``'CH'``, ``cholesky_solve`` routine will be used.
- If set to ``'LDL'``, ``LDLsolve`` routine will be used.
- To use a different method and to compute the solution via the
- inverse, use a method defined in the .inv() docstring.
- Returns
- =======
- solutions : Matrix
- Vector representing the solution.
- Raises
- ======
- ValueError
- If there is not a unique solution then a ``ValueError`` will be
- raised.
- If ``M`` is not square, a ``ValueError`` and a different routine
- for solving the system will be suggested.
- """
- if method in ('GJ', 'GE'):
- try:
- soln, param = M.gauss_jordan_solve(rhs)
- if param:
- raise NonInvertibleMatrixError("Matrix det == 0; not invertible. "
- "Try ``M.gauss_jordan_solve(rhs)`` to obtain a parametric solution.")
- except ValueError:
- raise NonInvertibleMatrixError("Matrix det == 0; not invertible.")
- return soln
- elif method == 'LU':
- return M.LUsolve(rhs)
- elif method == 'CH':
- return M.cholesky_solve(rhs)
- elif method == 'QR':
- return M.QRsolve(rhs)
- elif method == 'LDL':
- return M.LDLsolve(rhs)
- elif method == 'PINV':
- return M.pinv_solve(rhs)
- else:
- return M.inv(method=method).multiply(rhs)
- def _solve_least_squares(M, rhs, method='CH'):
- """Return the least-square fit to the data.
- Parameters
- ==========
- rhs : Matrix
- Vector representing the right hand side of the linear equation.
- method : string or boolean, optional
- If set to ``'CH'``, ``cholesky_solve`` routine will be used.
- If set to ``'LDL'``, ``LDLsolve`` routine will be used.
- If set to ``'QR'``, ``QRsolve`` routine will be used.
- If set to ``'PINV'``, ``pinv_solve`` routine will be used.
- Otherwise, the conjugate of ``M`` will be used to create a system
- of equations that is passed to ``solve`` along with the hint
- defined by ``method``.
- Returns
- =======
- solutions : Matrix
- Vector representing the solution.
- Examples
- ========
- >>> from sympy import Matrix, ones
- >>> A = Matrix([1, 2, 3])
- >>> B = Matrix([2, 3, 4])
- >>> S = Matrix(A.row_join(B))
- >>> S
- Matrix([
- [1, 2],
- [2, 3],
- [3, 4]])
- If each line of S represent coefficients of Ax + By
- and x and y are [2, 3] then S*xy is:
- >>> r = S*Matrix([2, 3]); r
- Matrix([
- [ 8],
- [13],
- [18]])
- But let's add 1 to the middle value and then solve for the
- least-squares value of xy:
- >>> xy = S.solve_least_squares(Matrix([8, 14, 18])); xy
- Matrix([
- [ 5/3],
- [10/3]])
- The error is given by S*xy - r:
- >>> S*xy - r
- Matrix([
- [1/3],
- [1/3],
- [1/3]])
- >>> _.norm().n(2)
- 0.58
- If a different xy is used, the norm will be higher:
- >>> xy += ones(2, 1)/10
- >>> (S*xy - r).norm().n(2)
- 1.5
- """
- if method == 'CH':
- return M.cholesky_solve(rhs)
- elif method == 'QR':
- return M.QRsolve(rhs)
- elif method == 'LDL':
- return M.LDLsolve(rhs)
- elif method == 'PINV':
- return M.pinv_solve(rhs)
- else:
- t = M.H
- return (t * M).solve(t * rhs, method=method)
|