public void Smooth(ref double[,] inputValues) { // TODO: Using the matrix works, but does a lot of data accesses. Can improve by working out all the data access myself? I might be able to cut down on number of data accesses, but not sure. var inputMatrix = new DenseMatrix(inputValues.GetLength(0), inputValues.GetLength(1)); for (int i = 0; i < inputMatrix.RowCount; i++) { inputMatrix.SetRow(i, Smooth(inputMatrix.Row(i).ToArray())); } for (int i = 0; i < inputMatrix.ColumnCount; i++) { inputMatrix.SetColumn(i, Smooth(inputMatrix.Column(i).ToArray())); } inputValues = inputMatrix.ToArray(); }
/// <summary> /// Run example /// </summary> public void Run() { // Format vector output to console var formatProvider = (CultureInfo)CultureInfo.InvariantCulture.Clone(); formatProvider.TextInfo.ListSeparator = " "; // Create new empty square matrix var matrix = new DenseMatrix(10); Console.WriteLine(@"Empty matrix"); Console.WriteLine(matrix.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 1. Fill matrix by data using indexer [] var k = 0; for (var i = 0; i < matrix.RowCount; i++) { for (var j = 0; j < matrix.ColumnCount; j++) { matrix[i, j] = k++; } } Console.WriteLine(@"1. Fill matrix by data using indexer []"); Console.WriteLine(matrix.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 2. Fill matrix by data using At. The element is set without range checking. for (var i = 0; i < matrix.RowCount; i++) { for (var j = 0; j < matrix.ColumnCount; j++) { matrix.At(i, j, k--); } } Console.WriteLine(@"2. Fill matrix by data using At"); Console.WriteLine(matrix.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 3. Clone matrix var clone = matrix.Clone(); Console.WriteLine(@"3. Clone matrix"); Console.WriteLine(clone.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 4. Clear matrix clone.Clear(); Console.WriteLine(@"4. Clear matrix"); Console.WriteLine(clone.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 5. Copy matrix into another matrix matrix.CopyTo(clone); Console.WriteLine(@"5. Copy matrix into another matrix"); Console.WriteLine(clone.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 6. Get submatrix into another matrix var submatrix = matrix.SubMatrix(2, 2, 3, 3); Console.WriteLine(@"6. Copy submatrix into another matrix"); Console.WriteLine(submatrix.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 7. Get part of the row as vector. In this example: get 4 elements from row 5 starting from column 3 var row = matrix.Row(5, 3, 4); Console.WriteLine(@"7. Get part of the row as vector"); Console.WriteLine(row.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 8. Get part of the column as vector. In this example: get 3 elements from column 2 starting from row 6 var column = matrix.Column(2, 6, 3); Console.WriteLine(@"8. Get part of the column as vector"); Console.WriteLine(column.ToString("#0.00\t", formatProvider)); Console.WriteLine(); // 9. Get columns using column enumerator. If you need all columns you may use ColumnEnumerator without parameters Console.WriteLine(@"9. Get columns using column enumerator"); foreach (var keyValuePair in matrix.ColumnEnumerator(2, 4)) { Console.WriteLine(@"Column {0}: {1}", keyValuePair.Item1, keyValuePair.Item2.ToString("#0.00\t", formatProvider)); } Console.WriteLine(); // 10. Get rows using row enumerator. If you need all rows you may use RowEnumerator without parameters Console.WriteLine(@"10. Get rows using row enumerator"); foreach (var keyValuePair in matrix.RowEnumerator(4, 3)) { Console.WriteLine(@"Row {0}: {1}", keyValuePair.Item1, keyValuePair.Item2.ToString("#0.00\t", formatProvider)); } Console.WriteLine(); // 11. Convert matrix into multidimensional array var data = matrix.ToArray(); Console.WriteLine(@"11. Convert matrix into multidimensional array"); for (var i = 0; i < data.GetLongLength(0); i++) { for (var j = 0; j < data.GetLongLength(1); j++) { Console.Write(data[i, j].ToString("#0.00\t")); } Console.WriteLine(); } Console.WriteLine(); // 12. Convert matrix into row-wise array var rowwise = matrix.ToRowWiseArray(); Console.WriteLine(@"12. Convert matrix into row-wise array"); for (var i = 0; i < matrix.RowCount; i++) { for (var j = 0; j < matrix.ColumnCount; j++) { Console.Write(rowwise[(i * matrix.ColumnCount) + j].ToString("#0.00\t")); } Console.WriteLine(); } Console.WriteLine(); // 13. Convert matrix into column-wise array var columnise = matrix.ToColumnWiseArray(); Console.WriteLine(@"13. Convert matrix into column-wise array"); for (var i = 0; i < matrix.RowCount; i++) { for (var j = 0; j < matrix.ColumnCount; j++) { Console.Write(columnise[(j * matrix.RowCount) + i].ToString("#0.00\t")); } Console.WriteLine(); } Console.WriteLine(); // 14. Get matrix diagonal as vector var diagonal = matrix.Diagonal(); Console.WriteLine(@"14. Get matrix diagonal as vector"); Console.WriteLine(diagonal.ToString("#0.00\t", formatProvider)); Console.WriteLine(); }
private void optimize(DenseMatrix coefficients, DenseVector objFunValues, bool artifical) { //for calculations on the optimal solution row int cCounter, width = coefficients.ColumnCount; DenseVector cBVect = new DenseVector(basics.Count); //Sets up the b matrix DenseMatrix b = new DenseMatrix(basics.Count, 1); //basics will have values greater than coefficients.ColumnCount - 1 if there are still artificial variables //or if Nathan is bad and didn't get rid of them correctly foreach (int index in basics) { b = (DenseMatrix)b.Append(DenseVector.OfVector(coefficients.Column(index)).ToColumnMatrix()); } // removes the first column b = (DenseMatrix)b.SubMatrix(0, b.RowCount, 1, b.ColumnCount - 1); double[] cPrimes = new double[width]; double[] rhsOverPPrime; DenseMatrix[] pPrimes = new DenseMatrix[width]; DenseMatrix bInverse; int newEntering, exitingRow; bool optimal = false; if(artifical) { rhsOverPPrime = new double[numConstraints + 1]; } else { rhsOverPPrime = new double[numConstraints]; } while (!optimal) { //calculates the inverse of b for this iteration bInverse = (DenseMatrix)b.Inverse(); //updates the C vector with the most recent basic variables cCounter = 0; foreach (int index in basics) { cBVect[cCounter++] = objFunValues.At(index); } //calculates the pPrimes and cPrimes for (int i = 0; i < coefficients.ColumnCount; i++) { if (!basics.Contains(i)) { pPrimes[i] = (DenseMatrix)bInverse.Multiply((DenseMatrix)coefficients.Column(i).ToColumnMatrix()); //c' = objFunVals - cB * P'n //At(0) to turn it into a double cPrimes[i] = objFunValues.At(i) - (pPrimes[i].LeftMultiply(cBVect)).At(0); } else { pPrimes[i] = null; } } //RHS' xPrime = (DenseMatrix)bInverse.Multiply((DenseMatrix)rhsValues.ToColumnMatrix()); //Starts newEntering as the first nonbasic newEntering = -1; int iter = 0; while(newEntering == -1) { if(!basics.Contains(iter)) { newEntering = iter; } iter++; } //new entering becomes the small cPrime that corresponds to a non-basic value for (int i = 0; i < cPrimes.Length; i++) { if (cPrimes[i] < cPrimes[newEntering] && !basics.Contains(i)) { newEntering = i; } } //if the smallest cPrime is >= 0, ie they are all positive if (cPrimes[newEntering] >= 0) { optimal = true; } else { //fix me to deal with if all these values are negative exitingRow = 0; for (int i = 0; i < xPrime.RowCount; i++) { double[,] pPrime = pPrimes[newEntering].ToArray(); rhsOverPPrime[i] = xPrime.ToArray()[i, 0] / pPrime[i, 0]; if (rhsOverPPrime[i] < rhsOverPPrime[exitingRow] && rhsOverPPrime[i] > 0 ) { exitingRow = i; } } //translates from the index in the basics list to the actual row exitingRow = basics[exitingRow]; //make sure you're not being stupid here!!!! int tempIndex = basics.IndexOf(exitingRow); basics.Remove(exitingRow); basics.Insert(tempIndex, newEntering); b.SetColumn(basics.IndexOf(newEntering), coefficients.Column(newEntering)); } } }