Compare commits
	
		
			11 Commits
		
	
	
		
			7ab770e3f6
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 32a8bd9dc6 | |||
| 9075fc3c8d | |||
| 75514a194f | |||
| efcc4abf0a | |||
| 70851add1d | |||
| a680f4bbd9 | |||
| 4113d9885b | |||
| 9ddeaaf907 | |||
| 6eb450ddbe | |||
| 5b7c29a262 | |||
| a70b6fd0b7 | 
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
								
							| @ -1,2 +1,23 @@ | ||||
| # 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 time | ||||
| import datetime | ||||
| 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 | ||||
| def inmat(rowcol) : | ||||
| @ -12,7 +24,11 @@ def inmat(rowcol) : | ||||
|         mat[i]=input().split(" ") | ||||
|         for j in range(len(mat[i])) : | ||||
|             # convert list using nsimplify in order to take rational number symbolically | ||||
|             mat[i][j] = sp.nsimplify(mat[i][j]) | ||||
|             try : | ||||
|                 mat[i][j] = sp.nsimplify(mat[i][j]) | ||||
|             except errs : return False | ||||
|     try : mat = sp.Matrix(mat) | ||||
|     except errs : return False | ||||
|     return mat | ||||
| 
 | ||||
| # multcheck function to check if two matrices are multiplied together | ||||
| @ -20,38 +36,66 @@ def multcheck(a, b, rowcol, intmax) : | ||||
|     sp.pprint(b) | ||||
|     print("Multiply these two matrices 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 | ||||
| def detcheck(a, b, rowcol, intmax): | ||||
|     det = sp.det(a) | ||||
|     # 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 | ||||
| def invcheck(a, b, rowcol, intmax): | ||||
|     det = a.det() | ||||
|     if det != 0 : | ||||
|         # return bool based on if input equals inverse of matrix | ||||
|         print("What is the inverse of this matrix?") | ||||
|         return (sp.Matrix(inmat(rowcol)) == a.inv()) | ||||
|     # return bool based on if input equals inverse of matrix | ||||
|     print("What is the inverse of this matrix?") | ||||
|     return (inmat(rowcol) == a.inv()) | ||||
| 
 | ||||
| # eigcheck function to check if the eigenvalues are correct | ||||
| def eigcheck(a, b, rowcol, intmax): | ||||
|     eigs = a.eigenvals() | ||||
|     for i in range(len(eigs)) : | ||||
|         val = sp.nsimplify(input("Input eigenvalue: ")) | ||||
|         if not (val in eigs and eigs[val] == sp.nsimplify(input("Input its algebraic multiplicity: "))) : | ||||
|         try : | ||||
|             val = sp.nsimplify(input("Input eigenvalue: ")) | ||||
|             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 | ||||
|     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 | ||||
| def practice(t) : | ||||
|     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 | ||||
|     if t == "mult" : | ||||
| @ -62,24 +106,56 @@ def practice(t) : | ||||
|         f = invcheck | ||||
|     elif t == "eig" : | ||||
|         f = eigcheck | ||||
|     elif t == "diag" : | ||||
|         f = diagcheck | ||||
|     elif t == "triang" : | ||||
|         f = triangcheck | ||||
|     else : | ||||
|         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 | ||||
|     tic = time.perf_counter() | ||||
| 
 | ||||
|     # infinite loop of practice | ||||
|     while True : | ||||
|         # generate a random matrices | ||||
|         a = sp.randMatrix(rowcol, rowcol, 0, intmax) | ||||
|         b = sp.randMatrix(rowcol, rowcol, 0, 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() | ||||
|         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 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  | ||||
|         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) | ||||
|             # if return of function is True | ||||
|             if f(a, b, rowcol, intmax) : | ||||
| @ -89,7 +165,7 @@ def practice(t) : | ||||
|                 # increment count | ||||
|                 count += 1 | ||||
|                 # 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 | ||||
|             else : | ||||
|                 # print failure message | ||||
| @ -97,5 +173,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) ") | ||||
| t = input("What do you want to practice? (mult, det, inv, eig, diag, triang) ") | ||||
| practice(t) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user