/*----------------------------------------*/ /*FUNCIONES OPERACIONALES (MATRIZ INVERSA)*/ /*----------------------------------------*/ public MMatrix invMatrix(MMatrix coeffs, MMatrix ind) { //Aqui calculamos la matriz inversa de la que necesitamos MMatrix matrizInversa = new MMatrix(pMatrixOperations.instance.inverse(coeffs)); //Aqui hacemos una multiplicacion de matrices entre la matriz inversa y la matriz de los terminos independientes MMatrix resultado = new MMatrix(pMatrixOperations.instance.multiply(matrizInversa, ind)); return resultado; }
/*------------------------------------------------------*/ /*LLAMADAS DE INFERFAZ (BOTONES | LABELS | CAMPOS | ETC)*/ /*------------------------------------------------------*/ /* Nombre: bCalcOperation_Click * Descripción: Realiza la operación seleccionada acorde a la cantidad de matrices disponibles. * * Fecha de Creación: 24/04/2016 * Autor Original: Luis Arzola * * Última Fecha de Modificación: 26/04/2016 * Autor Última Moficiación: Luis Arzola * * Programas que Llama: Ninguno * Programas que lo Llaman: scalar | sum | substract | multiply | transposed | inverse | determinant*/ private void bCalcOperation_Click(object sender, EventArgs e) { lFeedback.Text = ""; rtbResults.Text = ""; mvResult.Hide(); if (tbScalarA.Text.Equals("")) { tbScalarA.Text = "1"; } if (tbScalarB.Text.Equals("")) { tbScalarB.Text = "1"; } double det = 0; try { MMatrix tmpR = new MMatrix(1, 1);//Debe tener al menos una columna al momento de sobreescribirla MMatrix tmpA = new MMatrix(scalar(mvMatrixA.Data, double.Parse(tbScalarA.Text))); MMatrix tmpB = new MMatrix(scalar(mvMatrixB.Data, double.Parse(tbScalarB.Text))); if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.A || cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.B) { switch (cbOperation1.SelectedIndex) { case (int)Operations1.Determinante: if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.A) { if (rowsA != colsA) { throw new NotSquareException(); } tmpR = tmpA; if ((det = determinant(tmpA.Matrix)) != 0) { rtbResults.Text = "Se obtuvo el determinante de la matriz A.\nTiene un valor de " + det; } else { rtbResults.Text = "El valor determinante de la matriz A es 0.\nHay demasiados datos iguales o cercanos a 0, lo que impide que tenga determinante."; } } else { if (rowsB != colsB) { throw new NotSquareException(); } tmpR = tmpB; if (( det = determinant(tmpB.Matrix)) != 0) { rtbResults.Text = "Se obtuvo el determinante de la matriz B.\nTiene un valor de " + det; } else { rtbResults.Text = "El valor determinante de la matriz B es 0.\nHay demasiados datos iguales o cercanos a 0, lo que impide que tenga determinante."; } } break; case (int)Operations1.Inversa: if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.A) { if (rowsA != colsA) { throw new NotSquareException(); } tmpR = new MMatrix(inverse(tmpA)); rtbResults.Text += "Se obtuvo la matriz inversa de A.\n\nEs la mostrada a continuación."; } else { if (rowsB != colsB) { throw new NotSquareException(); } tmpR = new MMatrix(inverse(tmpB)); rtbResults.Text += "Se obtuvo la matriz inversa de B.\n\nEs la mostrada a continuación."; } break; case (int)Operations1.Transpuesta: rtbResults.Text = "Se obtuvo la matriz transpuesta de "; if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.A) { tmpR = new MMatrix(transposed(tmpA)); rtbResults.Text += "A.\nSiendo esta una matriz de " + rowsA + "x" + colsA + ".\n\nLo que da por resultado una matriz de " + colsA + "x" + rowsA + "."; } else { tmpR = new MMatrix(transposed(tmpB)); rtbResults.Text += "B.\nSiendo esta una matriz de " + rowsB + "x" + colsB + ".\n\nLo que da por resultado una matriz de " + colsB + "x" + rowsB + "."; } break; case (int)Operations1.SoloEscalar: rtbResults.Text = "Se obtuvo la matriz con un valor escalar de: "; if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.A) { tmpR = tmpA; rtbResults.Text += "" + tbScalarA.Text + " de la matriz A.\n\nEs la mostrada a continuación."; } else { tmpR = tmpB; rtbResults.Text += "" + tbScalarB.Text + " de la matriz B.\n\nEs la mostrada a continuación."; } break; default: break; } }// Fin de if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.A || cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.B) else if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.AB) { switch (cbOperation2.SelectedIndex) { case (int)Operations2.MultiplicaciónAB: if (colsA != rowsB) { throw new NotSameNException(); } rtbResults.Text = "Se realizó la operación: " + tbScalarA.Text + "A x " + tbScalarB.Text + "B." + "\n\nDonde A es una matriz de " + rowsA + "x" + colsA + "." + "\nY B una matriz de " + rowsB + "x" + colsB + "." + "\n\nDando como resultado una matriz de " + rowsA + "x" + colsB + "."; tmpR = new MMatrix(multiply(tmpA, tmpB)); break; case (int)Operations2.MultiplicaciónBA: if (colsB != rowsA) { throw new NotSameNException(); } rtbResults.Text = "Se realizó la operación: " + tbScalarB.Text + "B x " + tbScalarA.Text + "A." + "\n\nDonde A es una matriz de " + rowsA + "x" + colsA + "." + "\nY B una matriz de " + rowsB + "x" + colsB + "." + "\n\nDando como resultado una matriz de " + rowsB + "x" + colsA + "."; tmpR = new MMatrix(multiply(tmpB, tmpA)); break; case (int)Operations2.RestaAB: if (rowsA != rowsB || colsA != colsB) { throw new NotSameSizeException(); } rtbResults.Text = "Se realizó la operación: " + tbScalarA.Text + "A - " + tbScalarB.Text + "B." + "\n\nDonde A es una matriz de " + rowsA + "x" + colsA + "." + "\nY B una matriz de " + rowsB + "x" + colsB + "." + "\n\nDando como resultado una matriz de " + rowsB + "x" + colsA + "."; tmpR = new MMatrix(substract(tmpA, tmpB)); break; case (int)Operations2.RestaBA: if (rowsA != rowsB || colsA != colsB) { throw new NotSameSizeException(); } rtbResults.Text = "Se realizó la operación: " + tbScalarB.Text + "B - " + tbScalarA.Text + "A." + "\n\nDonde A es una matriz de " + rowsA + "x" + colsA + "." + "\nY B una matriz de " + rowsB + "x" + colsB + "." + "\n\nDando como resultado una matriz de " + rowsB + "x" + colsA + "."; tmpR = new MMatrix(substract(tmpB, tmpA)); break; case (int)Operations2.Suma: if (rowsA != rowsB || colsA != colsB) { throw new NotSameSizeException(); } rtbResults.Text = "Se realizó la operación: " + tbScalarA.Text + "A + " + tbScalarB.Text + "B." + "\n\nDonde A es una matriz de " + rowsA + "x" + colsA + "." + "\nY B una matriz de " + rowsB + "x" + colsB + "." + "\n\nDando como resultado una matriz de " + rowsB + "x" + colsA + "."; tmpR = new MMatrix(sum(tmpA, tmpB)); break; default: break; }//Fin de Switch }//Fin de else if (cbMatrixToUse.SelectedIndex == (int)SelectedMatrix.AB) mvResult.Data = tmpR; mvResult.Show(); }//Fin de try catch (NotSameSizeException nsse) { lFeedback.Text = "Ha ocurrido un error. Las matrices son de tamaños diferentes.\nPara realizar esta operacion las matrices deben tener el mismo número de filas y columnas."; } catch (NotSameNException nsne) { lFeedback.Text = "Ha ocurrido un error. Las matrices no son compatibles para multiplicación.\nPara realizar esta operación, la cantidad de columnas de la 1ra matriz debe ser igual a la cantidad de filas de la 2da."; } catch (NotSquareException nse) { lFeedback.Text = "Ha ocurrido un error. La matriz debe ser cuadrada para esta operación.\nRevise el número de filas y columnas de la matriz seleccionada."; } catch (Exception exception) { lFeedback.Text = "Ha ocurrido un error. Se ha introducido un valor inválido.\nAsegúrese que todos los campos contengan valores numéricos. (Los decimales son válidos)"; } }
/* Nombre: transposed * Descripción: Regresa la matriz transpuesta. * * Fecha de Creación: 26/04/2016 * Autor Original: Luis Arzola * * Última Fecha de Modificación: 26/04/2016 * Autor Última Moficiación: Luis Arzola * * Programas que Llama: Ninguno * Programas que lo Llaman: bCalcOperation_Click | inverse*/ public double[,] transposed(MMatrix matrix) { double[,] tmpMatrix = new double[matrix.Matrix.GetLength(1), matrix.Matrix.GetLength(0)]; //Por cada fila for (int row = 0; row < tmpMatrix.GetLength(0); row++) { //Por cada Columna for (int col = 0; col < tmpMatrix.GetLength(1); col++) { tmpMatrix[row, col] = matrix.Matrix[col, row]; } } return tmpMatrix; }
/* Nombre: sum * Descripción: Regresa la suma de dos matrices. * * Fecha de Creación: 26/04/2016 * Autor Original: Luis Arzola * * Última Fecha de Modificación: 26/04/2016 * Autor Última Moficiación: Luis Arzola * * Programas que Llama: Ninguno * Programas que lo Llaman: bCalcOperation_Click */ public double[,] sum(MMatrix matrixA, MMatrix matrixB) { double[,] tmpMatrix = matrixA.Matrix; //Por cada fila for (int row = 0; row < matrixA.Matrix.GetLength(0); row++) { //Por cada Columna for (int col = 0; col < matrixA.Matrix.GetLength(1); col++) { tmpMatrix[row, col] += matrixB.Matrix[row, col]; } } return tmpMatrix; }
/*--------------------------------------------------*/ /*FUNCIONES OPERACIONALES (OPERACIONES CON MATRICES)*/ /*--------------------------------------------------*/ /* Nombre: scalar * Descripción: Regresa una matriz aumentada a un valor escalar. * * Fecha de Creación: 24/04/2016 * Autor Original: Luis Arzola * * Última Fecha de Modificación: 24/04/2016 * Autor Última Moficiación: Luis Arzola * * Programas que Llama: Ninguno * Programas que lo Llaman: bCalcOperation_Click | inverse */ public double[,] scalar(MMatrix matrix, double scalarValue) { double[,] tmpMatrix = matrix.Matrix; //Por cada fila for (int row = 0; row < matrix.Matrix.GetLength(0); row++) { //Por cada Columna for (int col = 0; col < matrix.Matrix.GetLength(1); col++) { tmpMatrix[row, col] *= scalarValue; } } return tmpMatrix; }
/* Nombre: multiply * Descripción: Regresa el producto punto de la matriz A por la B. * * Fecha de Creación: 26/04/2016 * Autor Original: Luis Arzola * * Última Fecha de Modificación: 26/04/2016 * Autor Última Moficiación: Luis Arzola * * Programas que Llama: Ninguno * Programas que lo Llaman: bCalcOperation_Click | invMatrix | multivariable */ public double[,] multiply(MMatrix matrixA, MMatrix matrixB) { double[,] tmpMatrix = new double[matrixA.Matrix.GetLength(0), matrixB.Matrix.GetLength(1)]; double tmpAns = 0; //Por cada fila de la matriz resultante for (int row = 0; row < tmpMatrix.GetLength(0); row++) { //Por cada Columna de la matriz resultante for (int col = 0; col < tmpMatrix.GetLength(1); col++) { //Esto itera a lo largo de una fila de A, por lo tanto de una columna de B, ya que tienen el mismo numero de elementos. for (int colArowA = 0; colArowA < matrixA.Matrix.GetLength(1); colArowA++) { tmpAns += matrixA.Matrix[row, colArowA] * matrixB.Matrix[colArowA, col]; } tmpMatrix[row, col] = tmpAns; tmpAns = 0; } } return tmpMatrix; }
/* Nombre: inverse * Descripción: Regresa la inversa de la matriz seleccionada. * * Fecha de Creación: 26/04/2016 * Autor Original: Luis Arzola * * Última Fecha de Modificación: 26/04/2016 * Autor Última Moficiación: Luis Arzola * * Programas que Llama: determinant | scalar | transposed * Programas que lo Llaman: bCalcOperation_Click | invMatrix| multivariable*/ public double[,] inverse(MMatrix matrix) { double det; double[,] tmpMat = (double[,])matrix.Matrix.Clone(); if ((det = determinant(tmpMat)) == 0) { return new MMatrix(tmpMat).Matrix; }//No hay inversa si no hay determinante. int matSize = tmpMat.GetLength(0); double[,] tmpDetMat = new double[matSize - 1, matSize - 1];//Matriz para almacenar submatrices double[,] nMatrix = new double[matSize, matSize];//Matriz de determinantes int colIgnored = 0; int rowIgnored = 0; //Calcular la matriz n, elaborada a base de determinantes de submatrices for (int rowN = 0; rowN < matSize; rowN++) { for (int colN = 0; colN < matSize; colN++) { //[rowN,colN] nos permitirá recorrer cada casilla de nMatrix, para ir calculando los determinantes de sus submatrices //Ahora, por cada celda, se recorrerá toda la matriz con los datos, sacando la submatriz que no toca ni su columna o fila for (int row = 0; row < matSize; row++) { if (row == rowN) { rowIgnored = -1; } else { for (int col = 0; col < matSize; col++) { if (colN == col) { colIgnored = -1; } else { tmpDetMat[row + rowIgnored, col + colIgnored] = tmpMat[row, col]; } } colIgnored = 0; } } rowIgnored = 0; nMatrix[rowN, colN] = determinant(tmpDetMat); } } //Alternar signos desde la esquina superior izquierda, hasta la inferior derecha, empezando con +. int sign = -1; if (matSize % 2 == 0) { sign = 1; } for (int row = 0; row < matSize; row++) { if (matSize % 2 == 0) { sign *= -1; } for (int col = 0; col < matSize; col++) { nMatrix[row, col] *= (sign *= -1); } } nMatrix = transposed(new MMatrix(nMatrix)); nMatrix = scalar(new MMatrix(nMatrix), (1 / det)); return nMatrix; }