internal DenseDoubleMatrixImplementor( int numberOfRows, int numberOfColumns, double[] data, StorageOrder storageOrder) { Debug.Assert(numberOfRows > 0); Debug.Assert(numberOfColumns > 0); Debug.Assert(data is not null); Debug.Assert( (StorageOrder.ColumnMajor == storageOrder) || (StorageOrder.RowMajor == storageOrder)); int matrixLength = numberOfRows * numberOfColumns; Debug.Assert(data.Length == matrixLength); this.storage = new double[matrixLength]; data.CopyTo(this.storage, 0); if (StorageOrder.RowMajor == storageOrder) { ImplementationServices.ConvertStorageToColMajorOrdered( numberOfRows, numberOfColumns, this.storage); } this.numberOfRows = numberOfRows; this.numberOfColumns = numberOfColumns; this.storageOrder = StorageOrder.ColumnMajor; this.storageScheme = StorageScheme.Dense; }
internal sealed override MatrixImplementor <double> this[IndexCollection linearIndexes] { get { // Check if any linearIndex is outside the range defined by the matrix dimensions if (linearIndexes.maxIndex >= this.Count) { throw new ArgumentOutOfRangeException( nameof(linearIndexes), ImplementationServices.GetResourceString("STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } int[] linears = linearIndexes.indexes; DenseDoubleMatrixImplementor subMatrix = new(linears.Length, 1); double[] subStorage = subMatrix.storage; for (int l = 0; l < linears.Length; l++) { subStorage[l] = this.storage[linears[l]]; } return(subMatrix); } }
internal sealed override double this[int linearIndex] { get { // Check if the linear index is outside the range defined by the matrix dimensions if (linearIndex < 0 || this.storage.Length <= linearIndex) { throw new ArgumentOutOfRangeException( nameof(linearIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } return(this.storage[linearIndex]); } set { if (linearIndex < 0 || this.storage.Length <= linearIndex) { throw new ArgumentOutOfRangeException( nameof(linearIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } this.storage[linearIndex] = value; } }
internal sealed override double this[int rowIndex, int columnIndex] { get { // Check if any row index is outside the range defined by matrix dimensions if (rowIndex < 0 || this.numberOfRows <= rowIndex) { throw new ArgumentOutOfRangeException( nameof(rowIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } // Check if any column index is outside the range defined by matrix dimensions if (columnIndex < 0 || this.numberOfColumns <= columnIndex) { throw new ArgumentOutOfRangeException( nameof(columnIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } return(this.storage[rowIndex + columnIndex * this.numberOfRows]); } set { // Check if any row index is outside the range defined by matrix dimensions if (rowIndex < 0 || this.numberOfRows <= rowIndex) { throw new ArgumentOutOfRangeException( nameof(rowIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } // Check if any column index is outside the range defined by matrix dimensions if (columnIndex < 0 || this.numberOfColumns <= columnIndex) { throw new ArgumentOutOfRangeException( nameof(columnIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } this.storage[rowIndex + columnIndex * this.numberOfRows] = value; } }
internal DenseDoubleMatrixImplementor( int numberOfRows, int numberOfColumns, IEnumerable <double> data, StorageOrder storageOrder) { Debug.Assert(numberOfRows > 0); Debug.Assert(numberOfColumns > 0); Debug.Assert(data is not null); Debug.Assert( (StorageOrder.ColumnMajor == storageOrder) || (StorageOrder.RowMajor == storageOrder)); int matrixLength = numberOfRows * numberOfColumns; Debug.Assert(data.Count() == matrixLength); double[] dataStorage = new double[matrixLength]; int l = 0; foreach (double d in data) { dataStorage[l] = d; l++; } if (StorageOrder.RowMajor == storageOrder) { ImplementationServices.ConvertStorageToColMajorOrdered( numberOfRows, numberOfColumns, dataStorage); } this.storage = dataStorage; this.numberOfRows = numberOfRows; this.numberOfColumns = numberOfColumns; this.storageOrder = StorageOrder.ColumnMajor; this.storageScheme = StorageScheme.Dense; }
internal sealed override MatrixImplementor <double> this[string rowIndexes, IndexCollection columnIndexes] { get { // Check if any column index is outside the range defined by matrix dimensions if (columnIndexes.maxIndex >= this.numberOfColumns) { throw new ArgumentOutOfRangeException( nameof(columnIndexes), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } int thisNumberOfRows = this.numberOfRows; int[] columns = columnIndexes.indexes; int rowsLength = thisNumberOfRows; int columnsLength = columns.Length; var subMatrix = new DenseDoubleMatrixImplementor(rowsLength, columnsLength); double[] subStorage = subMatrix.storage; double[] thisStorage = this.storage; int offset, index = 0; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * columns[j]; for (int i = 0; i < rowsLength; i++, index++) { subStorage[index] = thisStorage[i + offset]; } } return(subMatrix); } set { // Check if any column index is outside the range defined by matrix dimensions if (columnIndexes.maxIndex >= this.numberOfColumns) { throw new ArgumentOutOfRangeException( nameof(columnIndexes), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } int thisNumberOfRows = this.numberOfRows; // Test for mismatched matrix dimensions ImplementationServices.ThrowOnMismatchedMatrixDimensions(thisNumberOfRows, columnIndexes.Count, value); MatrixImplementor <double> sourceImplementor; // if the source is this, clone the data before writing if (object.ReferenceEquals(this, value)) { sourceImplementor = (MatrixImplementor <double>)value.Clone(); } else { sourceImplementor = value; } int offset; int[] columns = columnIndexes.indexes; switch (sourceImplementor.StorageScheme) { case StorageScheme.CompressedRow: { var source = (SparseCsr3DoubleMatrixImplementor)sourceImplementor; var sourceValues = source.values; for (int j = 0; j < columns.Length; j++) { offset = thisNumberOfRows * columns[j]; for (int i = 0; i < thisNumberOfRows; i++) { if (source.TryGetPosition(i, j, out int index)) { this.storage[i + offset] = sourceValues[index]; } } } } break; case StorageScheme.Dense: { var source = (DenseDoubleMatrixImplementor)sourceImplementor; double[] sourceStorage = source.storage; int index = 0; for (int j = 0; j < columns.Length; j++) { offset = thisNumberOfRows * columns[j]; for (int i = 0; i < thisNumberOfRows; i++, index++) { this.storage[i + offset] = sourceStorage[index]; } } } break; } } }
internal sealed override MatrixImplementor <double> this[int rowIndex, string columnIndexes] { get { // Check if any row index is outside the range defined by matrix dimensions if (rowIndex < 0 || this.numberOfRows <= rowIndex) { throw new ArgumentOutOfRangeException( nameof(rowIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } int thisNumberOfRows = this.numberOfRows; int columnsLength = this.numberOfColumns; var subMatrix = new DenseDoubleMatrixImplementor(1, columnsLength); double[] subStorage = subMatrix.storage; double[] thisStorage = this.storage; int offset; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * j; subStorage[j] = thisStorage[rowIndex + offset]; } return(subMatrix); } set { // Check if any row index is outside the range defined by matrix dimensions if (rowIndex < 0 || this.numberOfRows <= rowIndex) { throw new ArgumentOutOfRangeException( nameof(rowIndex), ImplementationServices.GetResourceString( "STR_EXCEPT_TAB_INDEX_EXCEEDS_DIMS")); } // Test for mismatched matrix dimensions ImplementationServices.ThrowOnMismatchedMatrixDimensions( 1, this.numberOfColumns, value); MatrixImplementor <double> sourceImplementor; // if the source is this, clone the data before writing if (object.ReferenceEquals(this, value)) { sourceImplementor = (MatrixImplementor <double>)value.Clone(); } else { sourceImplementor = value; } int thisNumberOfRows = this.numberOfRows; int offset; int columnsLength = this.numberOfColumns; switch (sourceImplementor.StorageScheme) { case StorageScheme.CompressedRow: { var source = (SparseCsr3DoubleMatrixImplementor)sourceImplementor; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * j; this.storage[rowIndex + offset] = source.GetValue(j); } } break; case StorageScheme.Dense: { var source = (DenseDoubleMatrixImplementor)sourceImplementor; double[] sourceStorage = source.storage; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * j; this.storage[rowIndex + offset] = sourceStorage[j]; } } break; } } }
internal sealed override MatrixImplementor <double> this[string rowIndexes, string columnIndexes] { get { int thisNumberOfRows = this.numberOfRows; int rowsLength = thisNumberOfRows; int columnsLength = this.numberOfColumns; var subMatrix = new DenseDoubleMatrixImplementor(rowsLength, columnsLength); double[] subStorage = subMatrix.storage; double[] thisStorage = this.storage; int offset, index = 0; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * j; for (int i = 0; i < rowsLength; i++, index++) { subStorage[index] = thisStorage[i + offset]; } } return(subMatrix); } set { // Test for mismatched matrix dimensions ImplementationServices.ThrowOnMismatchedMatrixDimensions(this.numberOfRows, this.numberOfColumns, value); // if the source is this, nothing has to be done if (object.ReferenceEquals(this, value)) { return; } MatrixImplementor <double> sourceImplementor = value; int offset; int thisNumberOfRows = this.numberOfRows; int rowsLength = thisNumberOfRows; int columnsLength = this.numberOfColumns; switch (sourceImplementor.StorageScheme) { case StorageScheme.CompressedRow: { var source = (SparseCsr3DoubleMatrixImplementor)sourceImplementor; var sourceValues = source.values; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * j; for (int i = 0; i < rowsLength; i++) { if (source.TryGetPosition(i, j, out int index)) { this.storage[i + offset] = sourceValues[index]; } } } } break; case StorageScheme.Dense: { var source = (DenseDoubleMatrixImplementor)sourceImplementor; double[] sourceStorage = source.storage; int index = 0; for (int j = 0; j < columnsLength; j++) { offset = thisNumberOfRows * j; for (int i = 0; i < rowsLength; i++, index++) { this.storage[i + offset] = sourceStorage[index]; } } } break; } } }
/// <summary> /// Gets the bins for a sequence of numerical and target data. /// </summary> /// <param name="numericalData">The numerical data.</param> /// <param name="targetData">The target data.</param> /// <returns>The collection of <see cref="NumericalBin"/> instances /// corresponding to the specified numerical and target data.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="numericalData"/> is <b>null</b>. <br/> /// -or- <br/> /// <paramref name="targetData"/> is <b>null</b>. /// </exception> /// <exception cref="ArgumentException"> /// Parameter <paramref name="targetData"/> has not the /// same <see cref="DoubleMatrix.Count"/> of /// parameter <paramref name="numericalData"/>. /// </exception> public static List <NumericalBin> GetNumericalBins( DoubleMatrix numericalData, DoubleMatrix targetData) { #region Input validation if (numericalData is null) { throw new ArgumentNullException(nameof(numericalData)); } if (targetData is null) { throw new ArgumentNullException(nameof(targetData)); } if (numericalData.Count != targetData.Count) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, ImplementationServices.GetResourceString( "STR_EXCEPT_PAR_MUST_HAVE_SAME_COUNT"), nameof(numericalData)), nameof(targetData)); } #endregion List <NumericalBin> bins; if (numericalData.Count == 1) { bins = new List <NumericalBin>(1); var bin = new NumericalBin( 0, numericalData[0], targetData.GetStorage()) { lastPosition = 0 }; bin.targetFrequencyDistribution[targetData[0]]++; bins.Add(bin); return(bins); } bins = new List <NumericalBin>(); // Identify boundary points SortIndexResults sortResults = Stat.SortIndex( numericalData, SortDirection.Ascending); var sortedAttributeData = sortResults.SortedData; var sortedClassData = targetData.Vec(sortResults.SortedIndexes); var targetCodes = sortedClassData.Distinct().OrderBy( (code) => { return(code); }).ToArray(); double currentClass, currentAttributeValue, nextAttributeValue = Double.NaN; int lastcycledPosition = sortedAttributeData.Count - 2; bool createBin = true; NumericalBin currentBin = null; // Create attribute bins (a bin is a collection of positions // in the attribute ordering which are occupied by a same // attribute value for (int i = 0; i < lastcycledPosition + 1; i++) { // Create a new bin if needed. currentAttributeValue = sortedAttributeData[i]; if (createBin) { currentBin = new NumericalBin( i, currentAttributeValue, targetCodes); createBin = false; } // Update the class distribution in the current bin. currentClass = sortedClassData[i]; currentBin.targetFrequencyDistribution[currentClass]++; int nextPosition = i + 1; nextAttributeValue = sortedAttributeData[nextPosition]; bool cutPointDetected = currentAttributeValue != nextAttributeValue; if (i < lastcycledPosition) { if (cutPointDetected) { currentBin.lastPosition = i; bins.Add(currentBin); createBin = true; } } else { // A cut point exists between the last two positions // (final cut point) if (cutPointDetected) { // Finalize the current bin currentBin.lastPosition = i; bins.Add(currentBin); // Add a last bin consisting of the last position currentBin = new NumericalBin( nextPosition, nextAttributeValue, targetCodes) { lastPosition = nextPosition }; currentBin.targetFrequencyDistribution[ sortedClassData[nextPosition]]++; bins.Add(currentBin); } else // No final cut point { currentBin.lastPosition = nextPosition; currentBin.targetFrequencyDistribution[ sortedClassData[nextPosition]]++; bins.Add(currentBin); } } } return(bins); }