gt22

Untitled

May 14th, 2020
2,036
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.12 KB | None | 0 0
  1. import numpy as np
  2.  
  3. g = np.array([[1, 2, 1], [2, 1, 1], [1, 1, 1]])
  4. f = np.array([[3, 4, 6], [5, 2, 4], [3, 3, 3]])
  5.  
  6. matr = np.concatenate([g.T, f.T], axis=1)
  7.  
  8. # matr = np.array([
  9. #     [4, 2, 1, 2, 1, 1],
  10. #     [1, 1, 1, 3, -1, 3],
  11. #     [3, 2, 1, 3, 1, 2]
  12. # ])
  13.  
  14. n, m = matr.shape
  15. aug = 3
  16.  
  17.  
  18. def swap(i, j):
  19.     matr[i], matr[j] = matr[j].copy(), matr[i].copy()
  20.     return f"\\vec{{ {i + 1} }} \\leftrightarrow \\vec {{ {j + 1} }}"
  21.  
  22.  
  23. def multiply(i, k):
  24.     matr[i] *= k
  25.     return f"\\vec{{ {i + 1} }} \\to \\cdot {k}"
  26.  
  27.  
  28. def divide(i, k):
  29.     matr[i] //= k
  30.     return f"\\vec{{ {i + 1} }} \\to /{k}"
  31.  
  32.  
  33. def first_nonzero(i):
  34.     for k in range(m):
  35.         if matr[i, k] != 0:
  36.             return k
  37.     return -1
  38.  
  39.  
  40. def subtract(i, reverse=False):
  41.     r = first_nonzero(i)
  42.     gen = range(i - 1, -1, -1) if reverse else range(i + 1, n)
  43.     for j in gen:
  44.         k = first_nonzero(i) if reverse else first_nonzero(j)
  45.         if k == -1 or k > r:
  46.             continue
  47.         if matr[j, k] % matr[i, r] != 0:
  48.             raise ValueError("Not divisible")
  49.         matr[j] -= (matr[j, k] // matr[i, r]) * matr[i]
  50.     return f"-k \\cdot \\vec {{ {i + 1} }}"
  51.  
  52.  
  53. def matrix_to_latex(linebreak):
  54.     latex = ""
  55.     if not linebreak:
  56.         latex += "&"
  57.     else:
  58.         latex += "&&"
  59.     latex += "\\begin{bmatrix}\n\t" if aug == 0 else f"\\begin{{abmatrix}}[{m - aug}]{{{aug}}}\n\t"
  60.     latex += "\\\\\n\t".join([" & ".join([str(k) for k in j]) for j in matr])
  61.     latex += "\n\\end{bmatrix}" if aug == 0 else "\n\\end{abmatrix}"
  62.     if linebreak:
  63.         latex += "\\\\"
  64.     return latex
  65.  
  66.  
  67. def print_op(latex, linebreak):
  68.     if linebreak:
  69.         print("&&", end='')
  70.     print(f"\\underset {{ {latex} }} {{\\sim}}\n{matrix_to_latex(linebreak)}")
  71.     return not linebreak
  72.  
  73.  
  74. def gauss_step(normalized_lines, linebreak):
  75.     for i in range(n):
  76.         k = first_nonzero(i)
  77.         if k != -1 and matr[i, k] < 0:
  78.             linebreak = print_op(multiply(i, -1), linebreak)
  79.  
  80.     nonzero_left = min(first_nonzero(i) for i in range(normalized_lines, n))
  81.     line_to_raise = min(((matr[i, nonzero_left], i)
  82.                         for i in range(normalized_lines, n) if matr[i, nonzero_left] != 0), default=(-1, -1))[1]
  83.     if line_to_raise == -1:
  84.         return n
  85.     if line_to_raise != normalized_lines:
  86.         linebreak = print_op(swap(normalized_lines, line_to_raise), linebreak)
  87.     main_line = matr[normalized_lines]
  88.     main_elem = main_line[nonzero_left]
  89.     for i in range(normalized_lines + 1, n):
  90.         cur_elem = matr[i, first_nonzero(i)]
  91.         k = np.lcm(main_elem, cur_elem) // cur_elem
  92.         if k != 1:
  93.             linebreak = print_op(multiply(i, k), linebreak)
  94.     linebreak = print_op(subtract(normalized_lines), linebreak)
  95.     return 1, linebreak
  96.  
  97.  
  98. def normalize_step(linebreak):
  99.     for i in range(0, n):
  100.         k = first_nonzero(i)
  101.         gg = matr[i, k]
  102.         for e in range(k, m):
  103.             gg = np.gcd(gg, matr[i, e])
  104.         if gg != 1:
  105.             linebreak = print_op(divide(i, gg), linebreak)
  106.             return True, linebreak
  107.     for i in range(n-1, -1, -1):
  108.         k = first_nonzero(i)
  109.  
  110.         if any(matr[e, k] != 0 for e in range(i - 1, -1, -1)):
  111.             for e in range(i - 1, -1, -1):
  112.                 ll = np.lcm(matr[i, k], matr[e, k])
  113.                 if ll != matr[e, k]:
  114.                     linebreak = print_op(multiply(e, ll // matr[e, k]), linebreak)
  115.             linebreak = print_op(subtract(i, True), linebreak)
  116.             return True, linebreak
  117.     return False, linebreak
  118.  
  119.  
  120. def gauss():
  121.     print(matrix_to_latex(False))
  122.     linebreak = True
  123.     normalized_lines = 0
  124.     while normalized_lines < n:
  125.         lines_diff, linebreak_new = gauss_step(normalized_lines, linebreak)
  126.         normalized_lines += lines_diff
  127.         linebreak = linebreak_new
  128.     return linebreak
  129.  
  130.  
  131. def normalize(linebreak):
  132.     while True:
  133.         diff, linebreak_new = normalize_step(linebreak)
  134.         if not diff:
  135.             break
  136.         linebreak = linebreak_new
  137.  
  138.  
  139. def main():
  140.     normalize(gauss())
  141.  
  142.  
  143. if __name__ == '__main__':
  144.     main()
Advertisement
Add Comment
Please, Sign In to add comment