Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- g = np.array([[1, 2, 1], [2, 1, 1], [1, 1, 1]])
- f = np.array([[3, 4, 6], [5, 2, 4], [3, 3, 3]])
- matr = np.concatenate([g.T, f.T], axis=1)
- # matr = np.array([
- # [4, 2, 1, 2, 1, 1],
- # [1, 1, 1, 3, -1, 3],
- # [3, 2, 1, 3, 1, 2]
- # ])
- n, m = matr.shape
- aug = 3
- def swap(i, j):
- matr[i], matr[j] = matr[j].copy(), matr[i].copy()
- return f"\\vec{{ {i + 1} }} \\leftrightarrow \\vec {{ {j + 1} }}"
- def multiply(i, k):
- matr[i] *= k
- return f"\\vec{{ {i + 1} }} \\to \\cdot {k}"
- def divide(i, k):
- matr[i] //= k
- return f"\\vec{{ {i + 1} }} \\to /{k}"
- def first_nonzero(i):
- for k in range(m):
- if matr[i, k] != 0:
- return k
- return -1
- def subtract(i, reverse=False):
- r = first_nonzero(i)
- gen = range(i - 1, -1, -1) if reverse else range(i + 1, n)
- for j in gen:
- k = first_nonzero(i) if reverse else first_nonzero(j)
- if k == -1 or k > r:
- continue
- if matr[j, k] % matr[i, r] != 0:
- raise ValueError("Not divisible")
- matr[j] -= (matr[j, k] // matr[i, r]) * matr[i]
- return f"-k \\cdot \\vec {{ {i + 1} }}"
- def matrix_to_latex(linebreak):
- latex = ""
- if not linebreak:
- latex += "&"
- else:
- latex += "&&"
- latex += "\\begin{bmatrix}\n\t" if aug == 0 else f"\\begin{{abmatrix}}[{m - aug}]{{{aug}}}\n\t"
- latex += "\\\\\n\t".join([" & ".join([str(k) for k in j]) for j in matr])
- latex += "\n\\end{bmatrix}" if aug == 0 else "\n\\end{abmatrix}"
- if linebreak:
- latex += "\\\\"
- return latex
- def print_op(latex, linebreak):
- if linebreak:
- print("&&", end='')
- print(f"\\underset {{ {latex} }} {{\\sim}}\n{matrix_to_latex(linebreak)}")
- return not linebreak
- def gauss_step(normalized_lines, linebreak):
- for i in range(n):
- k = first_nonzero(i)
- if k != -1 and matr[i, k] < 0:
- linebreak = print_op(multiply(i, -1), linebreak)
- nonzero_left = min(first_nonzero(i) for i in range(normalized_lines, n))
- line_to_raise = min(((matr[i, nonzero_left], i)
- for i in range(normalized_lines, n) if matr[i, nonzero_left] != 0), default=(-1, -1))[1]
- if line_to_raise == -1:
- return n
- if line_to_raise != normalized_lines:
- linebreak = print_op(swap(normalized_lines, line_to_raise), linebreak)
- main_line = matr[normalized_lines]
- main_elem = main_line[nonzero_left]
- for i in range(normalized_lines + 1, n):
- cur_elem = matr[i, first_nonzero(i)]
- k = np.lcm(main_elem, cur_elem) // cur_elem
- if k != 1:
- linebreak = print_op(multiply(i, k), linebreak)
- linebreak = print_op(subtract(normalized_lines), linebreak)
- return 1, linebreak
- def normalize_step(linebreak):
- for i in range(0, n):
- k = first_nonzero(i)
- gg = matr[i, k]
- for e in range(k, m):
- gg = np.gcd(gg, matr[i, e])
- if gg != 1:
- linebreak = print_op(divide(i, gg), linebreak)
- return True, linebreak
- for i in range(n-1, -1, -1):
- k = first_nonzero(i)
- if any(matr[e, k] != 0 for e in range(i - 1, -1, -1)):
- for e in range(i - 1, -1, -1):
- ll = np.lcm(matr[i, k], matr[e, k])
- if ll != matr[e, k]:
- linebreak = print_op(multiply(e, ll // matr[e, k]), linebreak)
- linebreak = print_op(subtract(i, True), linebreak)
- return True, linebreak
- return False, linebreak
- def gauss():
- print(matrix_to_latex(False))
- linebreak = True
- normalized_lines = 0
- while normalized_lines < n:
- lines_diff, linebreak_new = gauss_step(normalized_lines, linebreak)
- normalized_lines += lines_diff
- linebreak = linebreak_new
- return linebreak
- def normalize(linebreak):
- while True:
- diff, linebreak_new = normalize_step(linebreak)
- if not diff:
- break
- linebreak = linebreak_new
- def main():
- normalize(gauss())
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment