Compare commits
	
		
			11 Commits
		
	
	
		
			7ab770e3f6
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 32a8bd9dc6 | |||
| 9075fc3c8d | |||
| 75514a194f | |||
| efcc4abf0a | |||
| 70851add1d | |||
| a680f4bbd9 | |||
| 4113d9885b | |||
| 9ddeaaf907 | |||
| 6eb450ddbe | |||
| 5b7c29a262 | |||
| a70b6fd0b7 | 
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							| @ -1,2 +1,23 @@ | |||||||
| # LinAlg-Practice | # LinAlg-Practice | ||||||
| TUI program to practice linear algebra computations (multiplications, determinants, inverses, eigenvalues, etc). Written in python by leveraging the sympy library. | TUI program to practice linear algebra computations (multiplications, determinants, inverses, eigenvalues, etc). Written in python by leveraging the sympy library. | ||||||
|  | 
 | ||||||
|  | ## Usage | ||||||
|  | To use: run the program with your favourite python interpreter | ||||||
|  | ```sh | ||||||
|  | python linalg-practice.py | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You will be prompted for selecting which settings you want to use | ||||||
|  | 
 | ||||||
|  | ## Features | ||||||
|  | * Multiplication of two matrices | ||||||
|  | * Determinant computation | ||||||
|  | * Inverse computation | ||||||
|  | * Eigenvalue computation | ||||||
|  | * Finding diagonalisations | ||||||
|  | * Finding triangularisations | ||||||
|  | 
 | ||||||
|  | ## Planned: | ||||||
|  | * Linear systems | ||||||
|  | * Row-echelon form | ||||||
|  | * GUI?? | ||||||
|  | |||||||
| @ -1,6 +1,18 @@ | |||||||
| import sympy as sp | import sympy as sp | ||||||
| import time | import time | ||||||
|  | import datetime | ||||||
| import random | import random | ||||||
|  | import readline | ||||||
|  | 
 | ||||||
|  | errs = (ValueError, TypeError) | ||||||
|  | 
 | ||||||
|  | def genmatrix(rowcol, intmax, dif) : | ||||||
|  |     # generate a random matrices | ||||||
|  |     a = sp.randMatrix(rowcol, rowcol, -intmax, intmax) | ||||||
|  |     # if determinant non-zero, radnom value less than difficulty, set a to its inverse | ||||||
|  |     if a.det() != 0 and random.random() <= dif : | ||||||
|  |         a = a.inv() | ||||||
|  |     return a | ||||||
| 
 | 
 | ||||||
| # in function to take arbitrary matrix input from user | # in function to take arbitrary matrix input from user | ||||||
| def inmat(rowcol) : | def inmat(rowcol) : | ||||||
| @ -12,7 +24,11 @@ def inmat(rowcol) : | |||||||
|         mat[i]=input().split(" ") |         mat[i]=input().split(" ") | ||||||
|         for j in range(len(mat[i])) : |         for j in range(len(mat[i])) : | ||||||
|             # convert list using nsimplify in order to take rational number symbolically |             # convert list using nsimplify in order to take rational number symbolically | ||||||
|  |             try : | ||||||
|                 mat[i][j] = sp.nsimplify(mat[i][j]) |                 mat[i][j] = sp.nsimplify(mat[i][j]) | ||||||
|  |             except errs : return False | ||||||
|  |     try : mat = sp.Matrix(mat) | ||||||
|  |     except errs : return False | ||||||
|     return mat |     return mat | ||||||
| 
 | 
 | ||||||
| # multcheck function to check if two matrices are multiplied together | # multcheck function to check if two matrices are multiplied together | ||||||
| @ -20,38 +36,66 @@ def multcheck(a, b, rowcol, intmax) : | |||||||
|     sp.pprint(b) |     sp.pprint(b) | ||||||
|     print("Multiply these two matrices together") |     print("Multiply these two matrices together") | ||||||
|     # return bool based on if input equals the two matrices multiplied together |     # return bool based on if input equals the two matrices multiplied together | ||||||
|     return (sp.Matrix(inmat(rowcol)) == a*b) |     return (inmat(rowcol) == a*b) | ||||||
| 
 | 
 | ||||||
| # detcheck function to check if the determinant of the matrix is correct | # detcheck function to check if the determinant of the matrix is correct | ||||||
| def detcheck(a, b, rowcol, intmax): | def detcheck(a, b, rowcol, intmax): | ||||||
|     det = sp.det(a) |     det = sp.det(a) | ||||||
|     # return bool based on if input equals determinant |     # return bool based on if input equals determinant | ||||||
|     return (det == sp.nsimplify(input("What is the determinant of this matrix?: "))) |     try : d = sp.nsimplify(input("What is the determinant of this matrix?: ")) | ||||||
|  |     except errs : return False | ||||||
|  |     return (det == d) | ||||||
| 
 | 
 | ||||||
| # invcheck function to check if the inverse of the matrix is correct | # invcheck function to check if the inverse of the matrix is correct | ||||||
| def invcheck(a, b, rowcol, intmax): | def invcheck(a, b, rowcol, intmax): | ||||||
|     det = a.det() |  | ||||||
|     if det != 0 : |  | ||||||
|     # return bool based on if input equals inverse of matrix |     # return bool based on if input equals inverse of matrix | ||||||
|     print("What is the inverse of this matrix?") |     print("What is the inverse of this matrix?") | ||||||
|         return (sp.Matrix(inmat(rowcol)) == a.inv()) |     return (inmat(rowcol) == a.inv()) | ||||||
| 
 | 
 | ||||||
| # eigcheck function to check if the eigenvalues are correct | # eigcheck function to check if the eigenvalues are correct | ||||||
| def eigcheck(a, b, rowcol, intmax): | def eigcheck(a, b, rowcol, intmax): | ||||||
|     eigs = a.eigenvals() |     eigs = a.eigenvals() | ||||||
|     for i in range(len(eigs)) : |     for i in range(len(eigs)) : | ||||||
|  |         try : | ||||||
|             val = sp.nsimplify(input("Input eigenvalue: ")) |             val = sp.nsimplify(input("Input eigenvalue: ")) | ||||||
|         if not (val in eigs and eigs[val] == sp.nsimplify(input("Input its algebraic multiplicity: "))) : |             algm = sp.nsimplify(input("Input its algebraic multiplicity: ")) | ||||||
|  |         except errs : return False | ||||||
|  |         if not (val in eigs and eigs[val] == algm) : | ||||||
|             # return false if the eigenvalue not in dictionary and wrong alg multiplicity |             # return false if the eigenvalue not in dictionary and wrong alg multiplicity | ||||||
|             return False |             return False | ||||||
|     return True |     return True | ||||||
| 
 | 
 | ||||||
|  | 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 | # practice function | ||||||
| def practice(t) : | def practice(t) : | ||||||
|     count = 0 |     count = 0 | ||||||
|     rowcol = int(input("What size of matrix do you want to practice with? ")) |  | ||||||
|     intmax = int(input("What maximum size of integer do you want the matrix to be made out of? ")) |  | ||||||
|     dif = float(input("What difficulty (probability for a matrix of rational values between 0, 1) do you want? ")) |  | ||||||
| 
 | 
 | ||||||
|     # choose the function of the program that you want |     # choose the function of the program that you want | ||||||
|     if t == "mult" : |     if t == "mult" : | ||||||
| @ -62,24 +106,56 @@ def practice(t) : | |||||||
|         f = invcheck |         f = invcheck | ||||||
|     elif t == "eig" : |     elif t == "eig" : | ||||||
|         f = eigcheck |         f = eigcheck | ||||||
|  |     elif t == "diag" : | ||||||
|  |         f = diagcheck | ||||||
|  |     elif t == "triang" : | ||||||
|  |         f = triangcheck | ||||||
|     else : |     else : | ||||||
|         exit() |         exit() | ||||||
| 
 | 
 | ||||||
|  |     while True : | ||||||
|  |         try : | ||||||
|  |             rowcol = abs(int(input("What size of matrix do you want to practice with? "))) | ||||||
|  |             intmax = abs(int(input("What maximum size of integer do you want the matrix to be made out of? "))) | ||||||
|  |             dif = float(input("What difficulty (probability for a matrix of rational values between 0, 1) do you want? ")) | ||||||
|  |             break | ||||||
|  |         except errs: | ||||||
|  |             continue | ||||||
|  | 
 | ||||||
|     # initialise time measurement |     # initialise time measurement | ||||||
|     tic = time.perf_counter() |     tic = time.perf_counter() | ||||||
| 
 | 
 | ||||||
|     # infinite loop of practice |     # infinite loop of practice | ||||||
|     while True : |     while True : | ||||||
|         # generate a random matrices |         a = genmatrix(rowcol, intmax, dif) | ||||||
|         a = sp.randMatrix(rowcol, rowcol, 0, intmax) |         b = genmatrix(rowcol, intmax, dif) | ||||||
|         b = sp.randMatrix(rowcol, rowcol, 0, intmax) |         if t == "triang" : | ||||||
| 
 |             while True : | ||||||
|         # if determinant non-zero, radnom value less than difficulty, set a to its inverse |                 # generate matrices with smaller integers | ||||||
|         if a.det() != 0 and random.random() <= dif : |                 a = genmatrix(rowcol, intmax//rowcol, dif) | ||||||
|             a = a.inv() |                 # 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 or 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  |         # infinite loop until user succeeds  | ||||||
|         while True : |         while True : | ||||||
|  |             # if diagcheck, make sure the matrix is diagonalizable | ||||||
|  |             if t == "diag" : | ||||||
|  |                 while not a.is_diagonalizable : | ||||||
|  |                     a = genmatrix(rowcol, intmax, dif) | ||||||
|  |             if t == "inv" : | ||||||
|  |                 while a.det() == 0 : | ||||||
|  |                     a = genmatrix(rowcol, intmax, dif) | ||||||
|             sp.pprint(a) |             sp.pprint(a) | ||||||
|             # if return of function is True |             # if return of function is True | ||||||
|             if f(a, b, rowcol, intmax) : |             if f(a, b, rowcol, intmax) : | ||||||
| @ -89,7 +165,7 @@ def practice(t) : | |||||||
|                 # increment count |                 # increment count | ||||||
|                 count += 1 |                 count += 1 | ||||||
|                 # print success message |                 # print success message | ||||||
|                 print("Correct! You have solved", count, "problems in %.2f seconds" %tictoc) |                 print("Correct! You have solved", count, "problems in", str(datetime.timedelta(seconds=round(tictoc)))) | ||||||
|                 break |                 break | ||||||
|             else : |             else : | ||||||
|                 # print failure message |                 # print failure message | ||||||
| @ -97,5 +173,5 @@ def practice(t) : | |||||||
|                 continue |                 continue | ||||||
| 
 | 
 | ||||||
| # take input from user on the type of practice they want to do | # 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) ") | t = input("What do you want to practice? (mult, det, inv, eig, diag, triang) ") | ||||||
| practice(t) | practice(t) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user