/// <summary> /// Same as <see cref="Cern.Colt.Partitioning.Partition(int[], int, int, int[], int, int, int[])"/> /// except that it <i>synchronously</i> partitions the rows of the given matrix by the values of the given matrix column; /// This is essentially the same as partitioning a list of composite objects by some instance variable; /// In other words, two entire rows of the matrix are swapped, whenever two column values indicate so. /// <p> /// Let's say, a "row" is an "object" (tuple, d-dimensional point). /// A "column" is the list of "object" values of a given variable (field, dimension). /// A "matrix" is a list of "objects" (tuples, points). /// <p> /// Now, rows (objects, tuples) are partially sorted according to their values in one given variable (dimension). /// Two entire rows of the matrix are swapped, whenever two column values indicate so. /// <p> /// Note that arguments are not checked for validity. /// </summary> /// <param name="matrix"> /// the matrix to be partitioned. /// </param> /// <param name="column"> /// the index of the column to partition on. /// </param> /// <param name="splitters"> /// the values at which the rows shall be split into intervals. /// Must be sorted ascending and must not contain multiple identical values. /// These preconditions are not checked; be sure that they are met. /// </param> /// <param name="splitIndexes"> /// a list into which this method fills the indexes of rows delimiting intervals. /// Therefore, must satisfy <i>splitIndexes.Length >= splitters.Length</i>. /// </param> /// <returns>a new matrix view having rows partitioned by the given column and splitters.</returns> /// <example> /// <table border="1" cellspacing="0"> /// <tr nowrap> /// <td valign="top"><i>8 x 3 matrix:<br> /// 23, 22, 21<br> /// 20, 19, 18<br> /// 17, 16, 15<br> /// 14, 13, 12<br> /// 11, 10, 9<br> /// 8, 7, 6<br> /// 5, 4, 3<br> /// 2, 1, 0 </i></td> /// <td align="left" valign="top"> /// <i>column = 0;<br> /// splitters = {5,10,12}<br> /// partition(matrix,column,splitters,splitIndexes);<br> /// ==><br> /// splitIndexes == {0, 2, 3}</i></p> /// </td> /// <td valign="top"> /// The matrix IS NOT REORDERED.<br> /// The new VIEW IS REORDERED:<br> /// <i>8 x 3 matrix:<br> /// 2, 1, 0<br> /// 5, 4, 3<br> /// 8, 7, 6<br> /// 11, 10, 9<br> /// 23, 22, 21<br> /// 20, 19, 18<br> /// 17, 16, 15<br> /// 14, 13, 12 </i></td> /// </tr> /// </table> /// </example> public static DoubleMatrix2D Partition(DoubleMatrix2D matrix, int column, double[] splitters, int[] splitIndexes) { int rowFrom = 0; int rowTo = matrix.Rows - 1; int splitFrom = 0; int splitTo = splitters.Length - 1; int[] rowIndexes = new int[matrix.Rows]; // row indexes to reorder instead of matrix itself for (int i = rowIndexes.Length; --i >= 0;) { rowIndexes[i] = i; } Partition(matrix, rowIndexes, rowFrom, rowTo, column, splitters, splitFrom, splitTo, splitIndexes); // take all columns in the original order int[] columnIndexes = new int[matrix.Columns]; for (int i = columnIndexes.Length; --i >= 0;) { columnIndexes[i] = i; } // view the matrix according to the reordered row indexes return(matrix.ViewSelection(rowIndexes, columnIndexes)); }
/// <summary> /// Sorts the matrix rows into ascending order, according to the <i>natural ordering</i> of the matrix values in the given column. /// </summary> /// <param name="matrix"> /// The matrix to be sorted. /// </param> /// <param name="column"> /// The index of the column inducing the order. /// </param> /// <returns> /// A new matrix view having rows sorted by the given column. /// </returns> /// <exception cref="IndexOutOfRangeException"> /// If <i>column < 0 || column >= matrix.columns()</i>. /// </exception> public DoubleMatrix2D Sort(DoubleMatrix2D matrix, int column) { if (column < 0 || column >= matrix.Columns) { throw new IndexOutOfRangeException("column=" + column + ", matrix=" + AbstractFormatter.Shape(matrix)); } var rowIndexes = new int[matrix.Rows]; // row indexes to reorder instead of matrix itself for (int i = rowIndexes.Length; --i >= 0;) { rowIndexes[i] = i; } DoubleMatrix1D col = matrix.ViewColumn(column); RunSort( rowIndexes, 0, rowIndexes.Length, (a, b) => { double av = col[a]; double bv = col[b]; if (Double.IsNaN(av) || Double.IsNaN(bv)) { return(CompareNaN(av, bv)); // swap NaNs to the end } return(av < bv ? -1 : (av == bv ? 0 : 1)); }); // view the matrix according to the reordered row indexes // take all columns in the original order return(matrix.ViewSelection(rowIndexes, null)); }
/// <summary> /// Sorts the matrix rows into ascending order, according to the <i>natural ordering</i> of the matrix values in the virtual column <i>aggregates</i>; /// Particularly efficient when comparing expensive aggregates, because aggregates need not be recomputed time and again, as is the case for comparator based sorts. /// Essentially, this algorithm makes expensive comparisons cheap. /// Normally each element of <i>aggregates</i> is a summary measure of a row. /// Speedup over comparator based sorting = <i>2*log(rows)</i>, on average. /// For this operation, quicksort is usually faster. /// </summary> /// <param name="matrix"> /// The matrix to be sorted. /// </param> /// <param name="aggregates"> /// The values to sort ond (As a side effect, this array will also get sorted). /// </param> /// <returns> /// A new matrix view having rows sorted. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// If <i>aggregates.Length != matrix.rows()</i>. /// </exception> public DoubleMatrix2D Sort(DoubleMatrix2D matrix, double[] aggregates) { int rows = matrix.Rows; if (aggregates.Length != rows) { throw new ArgumentOutOfRangeException("aggregates", "aggregates.Length != matrix.rows()"); } // set up index reordering var indexes = new int[rows]; for (int i = rows; --i >= 0;) { indexes[i] = i; } // sort indexes and aggregates RunSort( 0, rows, (x, y) => { double a = aggregates[x]; double b = aggregates[y]; if (Double.IsNaN(a) || Double.IsNaN(b)) { return(CompareNaN(a, b)); // swap NaNs to the end } return(a < b ? -1 : (a == b) ? 0 : 1); }, (x, y) => { int t1 = indexes[x]; indexes[x] = indexes[y]; indexes[y] = t1; double t2 = aggregates[x]; aggregates[x] = aggregates[y]; aggregates[y] = t2; }); // view the matrix according to the reordered row indexes // take all columns in the original order return(matrix.ViewSelection(indexes, null)); }
/// <summary> /// Sorts the matrix rows according to the order induced by the specified comparator. /// </summary> /// <param name="matrix"> /// The matrix to be sorted. /// </param> /// <param name="c"> /// The comparator to determine the order. /// </param> /// <returns> /// A new matrix view having rows sorted as specified. /// </returns> public DoubleMatrix2D Sort(DoubleMatrix2D matrix, DoubleMatrix1DComparator c) { var rowIndexes = new int[matrix.Rows]; // row indexes to reorder instead of matrix itself for (int i = rowIndexes.Length; --i >= 0;) { rowIndexes[i] = i; } var views = new DoubleMatrix1D[matrix.Rows]; // precompute views for speed for (int i = views.Length; --i >= 0;) { views[i] = matrix.ViewRow(i); } RunSort(rowIndexes, 0, rowIndexes.Length, (a, b) => c(views[a], views[b])); // view the matrix according to the reordered row indexes // take all columns in the original order return(matrix.ViewSelection(rowIndexes, null)); }
public static DoubleMatrix2D Permute(DoubleMatrix2D A, int[] rowIndexes, int[] columnIndexes) { return(A.ViewSelection(rowIndexes, columnIndexes)); }