Source code for tryalgo.gauss_jordan

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""\
Linear equation system Ax=b by Gauss-Jordan

jill-jenn vie et christoph durr - 2014-2018
"""

__all__ = ["gauss_jordan", "GJ_ZERO_SOLUTIONS", "GJ_SINGLE_SOLUTION",
           "GJ_SEVERAL_SOLUTIONS"]


# snip{
# pylint: disable=chained-comparison
def is_zero(x):                    # tolerance
    """error tolerant zero test
    """
    return -1e-6 < x and x < 1e-6
    # replace with x == 0 si we are handling Fraction elements


GJ_ZERO_SOLUTIONS = 0
GJ_SINGLE_SOLUTION = 1
GJ_SEVERAL_SOLUTIONS = 2


[docs] def gauss_jordan(A, x, b): """Linear equation system Ax=b by Gauss-Jordan :param A: m by n matrix :param x: table of size n :param b: table of size m :modifies: x will contain solution if any :returns int: 0 if no solution, 1 if solution unique, 2 otherwise :complexity: :math:`O(n^2m)` """ n = len(x) m = len(b) assert len(A) == m and len(A[0]) == n S = [] # put linear system in a single matrix S for i in range(m): S.append(A[i][:] + [b[i]]) S.append(list(range(n))) # indices in x k = diagonalize(S, n, m) if k < m: for i in range(k, m): if not is_zero(S[i][n]): return GJ_ZERO_SOLUTIONS for j in range(k): x[S[m][j]] = S[j][n] if k < n: for j in range(k, n): x[S[m][j]] = 0 return GJ_SEVERAL_SOLUTIONS return GJ_SINGLE_SOLUTION
def diagonalize(S, n, m): """diagonalize """ for k in range(min(n, m)): val, i, j = max((abs(S[i][j]), i, j) for i in range(k, m) for j in range(k, n)) if is_zero(val): return k S[i], S[k] = S[k], S[i] # swap lines k, i for r in range(m + 1): # swap columns k, j S[r][j], S[r][k] = S[r][k], S[r][j] pivot = float(S[k][k]) # without float if Fraction elements for j in range(k, n + 1): S[k][j] /= pivot # divide line k by pivot for i in range(m): # remove line k scaled by line i if i != k: fact = S[i][k] for j in range(k, n + 1): S[i][j] -= fact * S[k][j] return min(n, m) # snip}