-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrref_calculator.py
154 lines (132 loc) · 5.74 KB
/
rref_calculator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This calculator makes any matrix of dimensions m by n into reduced row echelon form.
# Reduced row echelon form is very useful for solving large systems of equations.
# I used Gauss-Jordan elinination to make this calculator
# Uses NumPy; custom matrix
# Includes step by step instructions
# I have a Java version as well without any matrix library
# Note: The : means all the entries in that dimension. So inputMatrix[3,:] means the third row.
# Created by Hamza Patwa
# Happy reduced row echeloning!
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import numpy as np
import fractions
import argparse
np.set_printoptions(suppress=True)
np.set_printoptions(formatter={'all': lambda x: str(fractions.Fraction(x).limit_denominator())})
def parse_args():
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('-rownum', action='store', type=int)
parser.add_argument('-colnum', action='store', type=int)
parser.add_argument('-values', action='store', type=float, nargs='+')
parser.add_argument('-show_equations', action='store_true')
args = parser.parse_args()
return args
# Multiplies a row and a scalar
def multiplyRow(multiplier, rowNum):
if multiplier != 0.0:
inputMatrix[rowNum, :] *= multiplier
# Adds two rows and replaces that sum into the row inputed last
def addRows(sourceRow, targetRow):
inputMatrix[targetRow, :] += inputMatrix[sourceRow, :]
def switchRows(row1, row2):
inputMatrix[[row1, row2]] = inputMatrix[[row2, row1]]
# Checks a certain column if it is in RREF form
def checkValueRREF(row, column):
# Makes a column matrix equal to the correct RREF form it should be
RREFCol = np.empty([NUMROWS, 1], dtype='float')
# Makes a column matrix equal to the values of inputMatrix in a specific column
columnMatrix = np.empty([NUMROWS, 1], dtype='float')
for i in range(NUMROWS):
columnMatrix[i][0] = inputMatrix[i][column]
if i == column:
RREFCol[i][0] = 1
else:
RREFCol[i][0] = 0
if columnMatrix[row][0] == RREFCol[row][0]:
return True
else:
return False
# Makes an input column into RREF
def RREF(colNum):
for i in range(NUMROWS):
if inputMatrix[colNum][colNum] == 0:
for j in range(i, NUMROWS):
if inputMatrix[j][colNum] != 0:
print("Switch rows {} and {}: ".format(j, colNum))
switchRows(j, colNum)
print(inputMatrix)
# Makes the diagonal entry 1 in that column
if inputMatrix[colNum][colNum] != 1.0 and inputMatrix[colNum][colNum] != 0:
print("Divide row {} by {}(beg): ".format(colNum, inputMatrix[colNum][colNum]))
multiplyRow(1 / inputMatrix[colNum][colNum], colNum)
print(inputMatrix)
# The if statement says that if the [colNum][colNum] is not 1 or any other value is not 0, run the RREF code
if checkValueRREF(i, colNum) == False:
if inputMatrix[colNum][colNum] == -1:
multiplyRow(-1, colNum)
# Multiplies the row with a 1 by the negative of the entry you are trying to make 0
print("Multiply row {} by {}: ".format(colNum, -inputMatrix[i][colNum]))
multiplyRow(-inputMatrix[i][colNum], colNum)
print(inputMatrix)
# Adds the two rows, making one entry zero
print("Add row {} and row {} and replace that into row {}: ".format(i, colNum, i))
addRows(colNum, i)
print(inputMatrix)
# Makes the diagonal entry 1 again
if inputMatrix[colNum][colNum] != 1.0 and inputMatrix[colNum][colNum] != 0.0:
print("Divide row {} by {}(end): ".format(colNum, inputMatrix[colNum][colNum]))
multiplyRow((1 / inputMatrix[colNum][colNum]), colNum)
print(inputMatrix)
if i == (NUMROWS - 1):
return 1
def matrixFunction():
counter = 97
for i in range(NUMROWS):
if (np.count_nonzero(inputMatrix[i, :])) == 0:
return
for j in range(NUMCOLS - 1):
if j != 0:
if inputMatrix[i][j] != 0:
print("{0:+}{1} ".format(inputMatrix[i][j], chr(counter)), end='')
if j == 0:
if inputMatrix[i][j] != 0:
print("{}{} ".format(inputMatrix[i][j], chr(counter)), end='')
counter = counter + 1
print("= {}".format(inputMatrix[i][NUMCOLS - 1]))
counter = 97
def variablesEqual():
counter = 97
for i in range(NUMROWS):
print("{} ≈ {} ≈ {}".format(chr(counter), fractions.Fraction(inputMatrix[i][NUMCOLS - 1]).limit_denominator(),
round(inputMatrix[i][NUMCOLS - 1], 4)))
counter = counter + 1
# Main function where everything is run
def main():
global inputMatrix
global deleted
global NUMROWS
global NUMCOLS
deleted = 0
args = parse_args()
listofValues = args.values
inputMatrix = np.empty([len(args.values)])
for i in range(len(args.values)):
inputMatrix[i] = listofValues[i]
inputMatrix = inputMatrix.reshape(args.rownum, args.colnum)
NUMROWS = args.rownum
NUMCOLS = args.colnum
print("Your Matrix is: \n{}".format(inputMatrix))
print()
if args.show_equations is True:
print("This matrix represents the system of equations: ")
matrixFunction()
for i in range(NUMROWS):
ret = RREF(i)
if ret == 1:
print("RREF of your Matrix is: \n{}".format(inputMatrix))
if args.show_equations is True:
variablesEqual()
# Calls the main function
if __name__ == "__main__":
main()