Source code for codeviking.math.linalg

from array import array


[docs]def tridiag_solve(a, b, c, y): r""" Calculate the solution of a tridiagonal system of linear equations. Consider the linear system: .. math:: \mathbf{M} \cdot \mathbf{x} = \mathbf{y} Where the matrix :math:`\mathbf{M}` is a tridiagonal matrix with the following form: .. math:: \left( \begin{matrix} b_0 & c_0 & & & & 0 \\ a_1 & b_1 & c_1 & & & \\ & a_2 & b_2 & c_2 & & \\ & & \ddots & \ddots & \ddots & \\ & & & a_{n-2}& b_{n-2}& c_{n-2} \\ 0 & & & & a_{n-1}& b_{n-1} \end{matrix} \right) \cdot \left( \begin{matrix} x_0 \\ x_1 \\ x_2 \\ \vdots \\ x_{n-2}\\ x_{n-1} \end{matrix} \right) = \left( \begin{matrix} y_0 \\ y_1 \\ y_2 \\ \vdots \\ y_{n-2}\\ y_{n-1} \end{matrix} \right) Note that elements :math:`a_0` and :math:`c_{n-1}` are not used. This function returns the vector :math:`\mathbf{x}`. :param a: subdiagonal :type a: Seq[float] :param b: diagonal :type b: Seq[float] :param c: superdiagonal :type c: Seq[float] :param y: rhs :type y: Seq[float] :return: solution to the tridiagonal system :rtype: Seq[float] """ n = len(a) if len(b) != n or len(c) != n or len(y) != n: raise ValueError("All list arguments must have the same length: " "a.length=${a.length}, b.length=${b.length}, " "c.length=${c.length}, y.length=${y.length}.") x = array('d', [0.0 for i in range(n)]) beta = b[0] u = array('d', [0.0 for i in range(n)]) if beta == 0.0: raise ValueError("algorithm encountered a zero value for b[0].") x[0] = y[0] / beta # forward substitution for i in range(1, n): u[i] = c[i - 1] / beta beta = b[i] - a[i] * u[i] if beta == 0.0: raise ValueError("algorithm encountered a zero value for beta" "while doing forward substitution.") x[i] = (y[i] - a[i] * x[i - 1]) / beta # backsubstitution. for i in range(n - 2, -1, -1): x[i] -= u[i + 1] * x[i + 1] return x