From efcc4abf0aa6b3716cf575bc02e2e690ffd0d9de Mon Sep 17 00:00:00 2001 From: Lukasz M Date: Thu, 25 Aug 2022 12:47:23 +0200 Subject: [PATCH] implement triangularisation (triangcheck) feature --- linalg-practice.py | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/linalg-practice.py b/linalg-practice.py index f5e8e18..d8e4288 100644 --- a/linalg-practice.py +++ b/linalg-practice.py @@ -67,6 +67,31 @@ def eigcheck(a, b, rowcol, intmax): def diagcheck(a, b, rowcol, intmax): return (a.diagonalize()[1] == inmat(rowcol)) +# pascalmat function to generate pascal matrices (used for generating unimodular matrices) +def pascalmat(n) : + mat = [] + # generate rows of binomial coefficients + for i in range(n) : + mat.append(sp.binomial_coefficients_list(i) + [0]*(n-1-i)) + mat = sp.Matrix(mat) + # make a lower triangular pascal matrix + lmat = mat.transpose() + rand = random.random() + # randomly pick either lower or upper triangular pascal matrix + if rand <= 1/2 : + mat = lmat + return mat + +def triangcheck(a, b, rowcol, intmax) : + print("Input triangularised matrix,") + T = inmat(rowcol) + print("Input basis change matrix (from standard basis)") + P_inv = inmat(rowcol) + # check if P_inv is invertible + if P_inv.det() == 0 : return False + # return false if T is not upper triangular and not similar to the original matrix + return (T.is_upper and a == P_inv.inv()*T*P_inv) + # practice function def practice(t) : count = 0 @@ -82,6 +107,8 @@ def practice(t) : f = eigcheck elif t == "diag" : f = diagcheck + elif t == "triang" : + f = triangcheck else : exit() @@ -101,6 +128,23 @@ def practice(t) : while True : a = genmatrix(rowcol, intmax, dif) b = genmatrix(rowcol, intmax, dif) + if t == "triang" : + while True : + # generate matrices with smaller integers + a = genmatrix(rowcol, intmax//rowcol, dif) + # ensure a is invertible + if a.det() == 0 : continue + # find a non-fractional upper trianagular matrix (ensures triangularisability) + c = a.LUdecompositionFF()[3] + croots = {k: k for k in sp.roots(c.charpoly()) if k not in sp.roots(c.charpoly(), filter='Z')} + # make sure only integer roots and c is not diagonalisable + if not (len(croots) != 0 and c.is_diagonalizable) : + a = c + pmat = pascalmat(rowcol) + # multiply by a pascal matrix to get a similar matrix with nice numbers + a = pmat.inv()*a*pmat + if a.is_upper: continue + break # infinite loop until user succeeds while True : @@ -128,5 +172,5 @@ def practice(t) : continue # take input from user on the type of practice they want to do -t = input("What do you want to practice? (mult, det, inv, eig, diag) ") +t = input("What do you want to practice? (mult, det, inv, eig, diag, triang) ") practice(t)