scipy.linalg¶
scipy
’s linalg
module contains two functions,
solve_triangular
, and cho_solve
. The functions can be called by
prepending them by scipy.linalg.
.
cho_solve¶
scipy
:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.cho_solve.html
Solve the linear equations
:raw-latex:`\begin{equation} \mathbf{A}\cdot\mathbf{x} = \mathbf{b} \end{equation}`
given the Cholesky factorization of \(\mathbf{A}\). As opposed to
scipy
, the function simply takes the Cholesky-factorised matrix,
\(\mathbf{A}\), and \(\mathbf{b}\) as inputs.
# code to be run in micropython
from ulab import numpy as np
from ulab import scipy as spy
A = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 2, 1, 8]])
b = np.array([4, 2, 4, 2])
print(spy.linalg.cho_solve(A, b))
array([-0.01388888888888906, -0.6458333333333331, 2.677083333333333, -0.01041666666666667], dtype=float64)
solve_triangular¶
scipy
:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.solve_triangular.html
Solve the linear equation
:raw-latex:`\begin{equation} \mathbf{a}\cdot\mathbf{x} = \mathbf{b} \end{equation}`
with the assumption that \(\mathbf{a}\) is a triangular matrix. The
two position arguments are \(\mathbf{a}\), and \(\mathbf{b}\),
and the optional keyword argument is lower
with a default value of
False
. lower
determines, whether data are taken from the lower,
or upper triangle of \(\mathbf{a}\).
Note that \(\mathbf{a}\) itself does not have to be a triangular
matrix: if it is not, then the values are simply taken to be 0 in the
upper or lower triangle, as dictated by lower
. However,
\(\mathbf{a}\cdot\mathbf{x}\) will yield \(\mathbf{b}\) only,
when \(\mathbf{a}\) is triangular. You should keep this in mind,
when trying to establish the validity of the solution by back
substitution.
# code to be run in micropython
from ulab import numpy as np
from ulab import scipy as spy
a = np.array([[3, 0, 0, 0], [2, 1, 0, 0], [1, 0, 1, 0], [1, 2, 1, 8]])
b = np.array([4, 2, 4, 2])
print('a:\n')
print(a)
print('\nb: ', b)
x = spy.linalg.solve_triangular(a, b, lower=True)
print('='*20)
print('x: ', x)
print('\ndot(a, x): ', np.dot(a, x))
a:
array([[3.0, 0.0, 0.0, 0.0],
[2.0, 1.0, 0.0, 0.0],
[1.0, 0.0, 1.0, 0.0],
[1.0, 2.0, 1.0, 8.0]], dtype=float64)
b: array([4.0, 2.0, 4.0, 2.0], dtype=float64)
====================
x: array([1.333333333333333, -0.6666666666666665, 2.666666666666667, -0.08333333333333337], dtype=float64)
dot(a, x): array([4.0, 2.0, 4.0, 2.0], dtype=float64)
With get the same solution, \(\mathbf{x}\), with the following matrix, but the dot product of \(\mathbf{a}\), and \(\mathbf{x}\) is no longer \(\mathbf{b}\):
# code to be run in micropython
from ulab import numpy as np
from ulab import scipy as spy
a = np.array([[3, 2, 1, 0], [2, 1, 0, 1], [1, 0, 1, 4], [1, 2, 1, 8]])
b = np.array([4, 2, 4, 2])
print('a:\n')
print(a)
print('\nb: ', b)
x = spy.linalg.solve_triangular(a, b, lower=True)
print('='*20)
print('x: ', x)
print('\ndot(a, x): ', np.dot(a, x))
a:
array([[3.0, 2.0, 1.0, 0.0],
[2.0, 1.0, 0.0, 1.0],
[1.0, 0.0, 1.0, 4.0],
[1.0, 2.0, 1.0, 8.0]], dtype=float64)
b: array([4.0, 2.0, 4.0, 2.0], dtype=float64)
====================
x: array([1.333333333333333, -0.6666666666666665, 2.666666666666667, -0.08333333333333337], dtype=float64)
dot(a, x): array([5.333333333333334, 1.916666666666666, 3.666666666666667, 2.0], dtype=float64)