def scalarDiv(const, mat): """Divides constant terms with Matrix Arguments: const {string}--- constant value mat {visma.matrix.structure.Matrix} -- matrix token Returns: matRes {visma.matrix.structure.Matrix} -- result matrix token """ if const != 0: matRes = Matrix() matRes.empty([mat.dim[0], mat.dim[1]]) for i in range(mat.dim[0]): for j in range(mat.dim[1]): if len(mat.value[i][j]) != 1: matRes.value[i][j].append(Expression(mat.value[i][j])) else: matRes.value[i][j].extend(mat.value[i][j]) matRes.value[i][j].append(Binary('/')) matRes.value[i][j].append(Constant(int(const))) matRes = simplifyMatrix(matRes) return matRes else: logger.error("ZeroDivisionError: Cannot divide matrix by zero")
def multiplyMatrix(matA, matB): """Multiplies two matrices Arguments: matA {visma.matrix.structure.Matrix} -- matrix token matB {visma.matrix.structure.Matrix} -- matrix token Returns: matPro {visma.matrix.structure.Matrix} -- product matrix token Note: Make mulitplyCheck before calling multiplyMatrix Not commutative """ matPro = Matrix() matPro.empty([matA.dim[0], matB.dim[1]]) for i in range(matA.dim[0]): for j in range(matB.dim[1]): for k in range(matA.dim[1]): if matPro.value[i][j] != []: matPro.value[i][j].append(Binary('+')) if len(matA.value[i][k]) != 1: matPro.value[i][j].append(Expression(matA.value[i][k])) else: matPro.value[i][j].extend(matA.value[i][k]) matPro.value[i][j].append(Binary('*')) if len(matB.value[k][j]) != 1: matPro.value[i][j].append(Expression(matB.value[k][j])) else: matPro.value[i][j].extend(matB.value[k][j]) matPro = simplifyMatrix(matPro) return matPro
def scalarSub(const, mat): """ Subtracts constant terms with Matrix Arguments: const {string}--- constant value mat {visma.matrix.structure.Matrix} -- matrix token Returns: matRes {visma.matrix.structure.Matrix} -- subtracted matrix token Note: This scalar addition follows the following equation {mat} - {lambda}{identity mat} """ matRes = Matrix() matRes.empty([mat.dim[0], mat.dim[1]]) for i in range(mat.dim[0]): for j in range(mat.dim[1]): if i != j: matRes.value[i][j].extend(mat.value[i][j]) else: if len(mat.value[i][j]) != 1: matRes.value[i][j].append(Expression(mat.value[i][j])) else: matRes.value[i][j].extend(mat.value[i][j]) matRes.value[i][j].append(Binary('-')) matRes.value[i][j].append(Constant(int(const))) matRes = simplifyMatrix(matRes) return matRes
def addMatrix(matA, matB): """Adds two matrices Arguments: matA {visma.matrix.structure.Matrix} -- matrix token matB {visma.matrix.structure.Matrix} -- matrix token Returns: matSum {visma.matrix.structure.Matrix} -- sum matrix token Note: Make dimCheck before calling addMatrix """ matSum = Matrix() matSum.empty(matA.dim) for i in range(matA.dim[0]): for j in range(matA.dim[1]): matSum.value[i][j].extend(matA.value[i][j]) matSum.value[i][j].append(Binary('+')) matSum.value[i][j].extend(matB.value[i][j]) matSum = simplifyMatrix(matSum) return matSum
def subMatrix(matA, matB): """Subtracts two matrices Arguments: matA {visma.matrix.structure.Matrix} -- matrix token matB {visma.matrix.structure.Matrix} -- matrix token Returns: matSub {visma.matrix.structure.Matrix} -- subtracted matrix token Note: Make dimCheck before calling subMatrix """ matSub = Matrix() matSub.empty(matA.dim) for i in range(matA.dim[0]): for j in range(matA.dim[1]): matSub.value[i][j].extend(matA.value[i][j]) matSub.value[i][j].append(Binary('-')) matSub.value[i][j].extend(matB.value[i][j]) matSub = simplifyMatrix(matSub) return matSub
def gauss_elim(mat): """ Returns calculated values of unknown variables Arguments: mat {visma.matrix.structure.Matrix} -- matrix token Returns: result {visma.matrix.structure.Matrix} -- result matrix token Note: result is a Nx1 matrix """ echelon = Matrix() echelon = row_echelon(mat) result = Matrix() result.empty([mat.dim[0], 1]) N = mat.dim[0] M = mat.dim[1] index = N - 1 for i in range(N - 1, -1, -1): sum_ = [] temp = [] if echelon.value[i][i][ 0].value == 0.0: # no unique solution for this case return -1 for j in range(i + 1, M - 1): temp = [] temp.extend(echelon.value[i][j]) temp.append(Binary('*')) temp.extend(result.value[j][0]) temp, _, _, _, _ = simplify(temp) sum_.extend(temp) if j != M - 2: sum_.append(Binary('+')) sum_, _, _, _, _ = simplify(sum_) result.value[index][0].extend(echelon.value[i][M - 1]) if sum_: if sum_[0].value < 0: result.value[index][0].append( Binary('-') ) # negative sign makes the negative sign in value positive else: result.value[index][0].append(Binary('-')) result.value[index][0].extend(sum_) result.value[index][0], _, _, _, _ = simplify(result.value[index][0]) result.value[index][0].append(Binary('/')) result.value[index][0].extend(echelon.value[i][i]) result.value[index][0], _, _, _, _ = simplify(result.value[index][0]) index -= 1 return result
def scalarMult(const, mat): """Multiplies constant terms with Matrix Arguments: const {string}--- constant value mat {visma.matrix.structure.Matrix} -- matrix token Returns: matRes {visma.matrix.structure.Matrix} -- product matrix token """ matRes = Matrix() matRes.empty([mat.dim[0], mat.dim[1]]) for i in range(mat.dim[0]): for j in range(mat.dim[1]): if len(mat.value[i][j]) != 1: matRes.value[i][j].append(Expression(mat.value[i][j])) else: matRes.value[i][j].extend(mat.value[i][j]) matRes.value[i][j].append(Binary('*')) matRes.value[i][j].append(Constant(int(const))) matRes = simplifyMatrix(matRes) return matRes
def interactionMode(self): if not self.matrix: self.enableQSolver = False renderQuickSol(self, self.qSol, self.enableQSolver) cursor = self.textedit.textCursor() interactionText = cursor.selectedText() if str(interactionText) == '': self.mode = 'normal' self.input = str(self.textedit.toPlainText()) else: self.input = str(interactionText) self.mode = 'interaction' showbuttons = True if len(self.input) == 0: return self.warning("No input given!") self.simul = False self.combi = False self.matrix = False self.dualOperandMatrix = False self.scalarOperationsMatrix = False self.nonMatrixResult = False if self.input[0:4] == 'mat_': self.input = self.input[4:] self.input = self.input[0:-1] self.input = self.input[1:] self.matrix = True if not self.matrix: if ';' in self.input: self.simul = True if (self.input.count(';') == 2): afterSplit = self.input.split(';') eqStr1 = afterSplit[0] eqStr2 = afterSplit[1] eqStr3 = afterSplit[2] elif (self.input.count(';') == 1): self.combi = True afterSplit = self.input.split(';') eqStr1 = afterSplit[0] eqStr2 = afterSplit[1] eqStr3 = '' if self.simul: self.tokens = [tokenizer(eqStr1), tokenizer(eqStr2), tokenizer(eqStr3)] self.addEquation() operations = ['solve'] if self.combi: operations.extend(['combination', 'permutation']) self.solutionType = 'equation' else: self.tokens = tokenizer(self.input) # DBP: print(self.tokens) self.addEquation() lhs, rhs = getLHSandRHS(self.tokens) self.lTokens = lhs self.rTokens = rhs operations, self.solutionType = checkTypes(lhs, rhs) if isinstance(operations, list) and showbuttons: opButtons = [] if len(operations) > 0: if len(operations) == 1: if (operations[0] not in ['integrate', 'differentiate', 'find roots', 'factorize']) and (not self.simul): opButtons = ['simplify'] else: opButtons = ['simplify'] for operation in operations: if operation == '+': opButtons.append("addition") elif operation == '-': opButtons.append("subtraction") elif operation == '*': opButtons.append("multiplication") elif operation == '/': opButtons.append("division") else: opButtons.append(operation) else: if ',' in self.input: self.dualOperandMatrix = True [inputEquation1, inputEquation2] = self.input.split(', ') if '[' in inputEquation1: inputEquation1 = inputEquation1[1:][:-1] inputEquation1 = inputEquation1.split('; ') matrixOperand1 = [] for row in inputEquation1: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand1.append(row1) self.Matrix1 = Matrix() self.Matrix1.value = matrixOperand1 inputEquation2 = inputEquation2[1:][:-1] inputEquation2 = inputEquation2.split('; ') matrixOperand2 = [] for row in inputEquation2: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand2.append(row1) self.Matrix2 = Matrix() self.Matrix2.value = matrixOperand2 else: self.scalarOperationsMatrix = True inputEquation2 = inputEquation2[1:][:-1] inputEquation2 = inputEquation2.split('; ') matrixOperand2 = [] for row in inputEquation2: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand2.append(row1) self.Matrix2 = Matrix() self.Matrix2.value = matrixOperand2 else: self.dualOperandMatrix = False inputEquation = self.input[:-2] inputEquation = inputEquation[:-1][1:] inputEquation = inputEquation.split('; ') matrixOperand = [] for row in inputEquation: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand.append(row1) self.Matrix0 = Matrix() self.Matrix0.value = matrixOperand opButtons = [] if ',' in self.input: opButtons.extend(['Addition', 'Subtraction', 'Multiply']) else: opButtons.extend(['Determinant', 'Trace', 'Inverse']) if self.buttonSet: for i in reversed(range(self.solutionOptionsBox.count())): self.solutionOptionsBox.itemAt(i).widget().setParent(None) for i in range(int(len(opButtons) / 2) + 1): for j in range(2): if len(opButtons) > (i * 2 + j): self.solutionButtons[(i, j)] = QtWidgets.QPushButton( opButtons[i * 2 + j]) self.solutionButtons[(i, j)].resize(100, 100) self.solutionButtons[(i, j)].clicked.connect( self.onSolvePress(opButtons[i * 2 + j])) self.solutionOptionsBox.addWidget( self.solutionButtons[(i, j)], i, j) else: self.bottomButton.setParent(None) self.solutionWidget = QWidget() for i in range(int(len(opButtons) / 2) + 1): for j in range(2): if len(opButtons) > (i * 2 + j): self.solutionButtons[(i, j)] = QtWidgets.QPushButton( opButtons[i * 2 + j]) self.solutionButtons[(i, j)].resize(100, 100) self.solutionButtons[(i, j)].clicked.connect( self.onSolvePress(opButtons[i * 2 + j])) self.solutionOptionsBox.addWidget( self.solutionButtons[(i, j)], i, j) self.solutionWidget.setLayout(self.solutionOptionsBox) self.buttonSplitter.addWidget(self.solutionWidget) self.buttonSet = True
def commandExec(command): operation = command.split('(', 1)[0] inputEquation = command.split('(', 1)[1][:-1] matrix = False # True when matrices operations are present in the code. if operation[0:4] == 'mat_': matrix = True if not matrix: """ This part handles the cases when VisMa is NOT dealing with matrices. Boolean flags used in code below: simul -- {True} when VisMa is dealing with simultaneous equations & {False} in all other cases """ varName = None if ',' in inputEquation: varName = inputEquation.split(',')[1] varName = "".join(varName.split()) inputEquation = inputEquation.split(',')[0] simul = False # True when simultaneous equation is present if (inputEquation.count(';') == 2) and (operation == 'solve'): simul = True afterSplit = inputEquation.split(';') eqStr1 = afterSplit[0] eqStr2 = afterSplit[1] eqStr3 = afterSplit[2] lhs = [] rhs = [] solutionType = '' lTokens = [] rTokens = [] equationTokens = [] comments = [] if simul: tokens = [tokenizer(eqStr1), tokenizer(eqStr2), tokenizer(eqStr3)] else: tokens = tokenizer(inputEquation) if '=' in inputEquation: lhs, rhs = getLHSandRHS(tokens) lTokens = lhs rTokens = rhs _, solutionType = checkTypes(lhs, rhs) else: solutionType = 'expression' lhs, rhs = getLHSandRHS(tokens) lTokens = lhs rTokens = rhs if operation == 'plot': app = QApplication(sys.argv) App(tokens) sys.exit(app.exec_()) elif operation == 'simplify': if solutionType == 'expression': tokens, _, _, equationTokens, comments = simplify(tokens) else: lTokens, rTokens, _, _, equationTokens, comments = simplifyEquation( lTokens, rTokens) elif operation == 'addition': if solutionType == 'expression': tokens, _, _, equationTokens, comments = addition(tokens, True) else: lTokens, rTokens, _, _, equationTokens, comments = additionEquation( lTokens, rTokens, True) elif operation == 'subtraction': if solutionType == 'expression': tokens, _, _, equationTokens, comments = subtraction( tokens, True) else: lTokens, rTokens, _, _, equationTokens, comments = subtractionEquation( lTokens, rTokens, True) elif operation == 'multiplication': if solutionType == 'expression': tokens, _, _, equationTokens, comments = multiplication( tokens, True) else: lTokens, rTokens, _, _, equationTokens, comments = multiplicationEquation( lTokens, rTokens, True) elif operation == 'division': if solutionType == 'expression': tokens, _, _, equationTokens, comments = division(tokens, True) else: lTokens, rTokens, _, _, equationTokens, comments = divisionEquation( lTokens, rTokens, True) elif operation == 'factorize': tokens, _, _, equationTokens, comments = factorize(tokens) elif operation == 'find-roots': lTokens, rTokens, _, _, equationTokens, comments = rootFinder( lTokens, rTokens) elif operation == 'solve': if simul: if varName is not None: _, equationTokens, comments = simulSolver( tokens[0], tokens[1], tokens[2], varName) else: _, equationTokens, comments = simulSolver( tokens[0], tokens[1], tokens[2]) solutionType = equationTokens else: lhs, rhs = getLHSandRHS(tokens) lTokens, rTokens, _, _, equationTokens, comments = solveFor( lTokens, rTokens, varName) elif operation == 'factorial': tokens, _, _, equationTokens, comments = factorial(tokens) elif operation == 'combination': n = tokenizer(inputEquation) r = tokenizer(varName) tokens, _, _, equationTokens, comments = combination(n, r) elif operation == 'permutation': n = tokenizer(inputEquation) r = tokenizer(varName) tokens, _, _, equationTokens, comments = permutation(n, r) elif operation == 'integrate': lhs, rhs = getLHSandRHS(tokens) lTokens, _, _, equationTokens, comments = integrate( lTokens, varName) elif operation == 'differentiate': lhs, rhs = getLHSandRHS(tokens) lTokens, _, _, equationTokens, comments = differentiate( lTokens, varName) if operation != 'plot': # FIXME: when either plotting window or GUI window is opened from CLI and after it is closed entire CLI exits, it would be better if it is avoided final_string = resultStringCLI(equationTokens, operation, comments, solutionType, simul) print(final_string) else: """ This part handles the cases when VisMa is dealing with matrices. Boolean flags used in code below: dualOperand -- {True} when the matrix operations require two operands (used in operations like addition, subtraction etc) nonMatrixResult -- {True} when the result after performing operations on the Matrix is not a Matrix (in operations like Determinant, Trace etc.) scalarOperations -- {True} when one of the operand in a scalar (used in operations like Scalar Addition, Scalar Subtraction etc.) """ operation = operation[4:] dualOperand = False nonMatrixResult = False scalarOperations = False if ', ' in inputEquation: dualOperand = True [inputEquation1, inputEquation2] = inputEquation.split(', ') if '[' in inputEquation1: inputEquation1 = inputEquation1[1:][:-1] inputEquation1 = inputEquation1.split('; ') matrixOperand1 = [] for row in inputEquation1: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand1.append(row1) Matrix1 = Matrix() Matrix1.value = matrixOperand1 inputEquation2 = inputEquation2[1:][:-1] inputEquation2 = inputEquation2.split('; ') matrixOperand2 = [] for row in inputEquation2: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand2.append(row1) Matrix2 = Matrix() Matrix2.value = matrixOperand2 Matrix1_copy = copy.deepcopy(Matrix1) Matrix2_copy = copy.deepcopy(Matrix2) else: scalarOperations = True scalar = inputEquation1 scalarTokens = scalar # scalarTokens = tokenizer(scalar) inputEquation2 = inputEquation2[1:][:-1] inputEquation2 = inputEquation2.split('; ') matrixOperand2 = [] for row in inputEquation2: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand2.append(row1) Matrix2 = Matrix() Matrix2.value = matrixOperand2 scalarTokens_copy = copy.deepcopy(scalarTokens) Matrix2_copy = copy.deepcopy(Matrix2) else: inputEquation = inputEquation[1:][:-1] inputEquation = inputEquation.split('; ') matrixOperand = [] for row in inputEquation: row1 = row.split(' ') for i, _ in enumerate(row1): row1[i] = tokenizer(row1[i]) matrixOperand.append(row1) Matrix0 = Matrix() Matrix0.value = matrixOperand Matrix0_copy = copy.deepcopy(Matrix0) if operation == 'simplify': MatrixResult = simplifyMatrix(Matrix0) elif operation == 'add': MatrixResult = addMatrix(Matrix1, Matrix2) elif operation == 'sub': MatrixResult = subMatrix(Matrix1, Matrix2) elif operation == 'mult': MatrixResult = multiplyMatrix(Matrix1, Matrix2) elif operation == 'determinant': nonMatrixResult = True sqMatrix = SquareMat() sqMatrix.value = Matrix0.value result = sqMatrix.determinant() elif operation == 'trace': nonMatrixResult = True sqMatrix = SquareMat() sqMatrix.value = Matrix0.value result = sqMatrix.traceMat() elif operation == 'inverse': sqMatrix = SquareMat() sqMatrix.value = Matrix0.value MatrixResult = SquareMat() MatrixResult = sqMatrix.inverse() finalCLIstring = '' if dualOperand: if not scalarOperations: finalCLIstring = resultMatrixString(operation=operation, operand1=Matrix1_copy, operand2=Matrix2_copy, result=MatrixResult) else: finalCLIstring = resultMatrixString(operation=operation, operand1=scalarTokens_copy, operand2=Matrix2_copy, result=MatrixResult) else: if nonMatrixResult: finalCLIstring = resultMatrixString(operation=operation, operand1=Matrix0_copy, nonMatrixResult=True, result=result) else: finalCLIstring = resultMatrixString(operation=operation, operand1=Matrix0_copy, result=MatrixResult) print(finalCLIstring)