microsoft-visualbasic-runtime/Extensions/Collection/Matrix.vb

301 lines
9.5 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::44bec93731efa49cd5c9e88b17824d27, Microsoft.VisualBasic.Core\Extensions\Collection\Matrix.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Module MatrixExtensions
'
' Function: DATA, GetCol, GetRow, GetSize, MAT
' (+2 Overloads) Matrix, Rectangle, RowIterator, SetCol, SetRow
' SizeOf, ToFloatMatrix, ToMatrix, ToVectorList
'
' /********************************************************************************/
#End Region
Imports System.Drawing
Imports System.Runtime.CompilerServices
Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
Imports Microsoft.VisualBasic.Language
Imports Microsoft.VisualBasic.Linq
Public Module MatrixExtensions
''' <summary>
''' 将数据集之中的虽有属性值取出来构建一个矩阵
''' </summary>
''' <param name="data"></param>
''' <returns></returns>
Public Iterator Function Matrix(Of T, DataSet As DynamicPropertyBase(Of T))(data As IEnumerable(Of DataSet)) As IEnumerable(Of T())
With data.ToArray
Dim allFields = .Select(Function(x) x.Properties.Keys) _
.IteratesALL _
.Distinct _
.ToArray
For Each x As DataSet In .ByRef
' 利用属性名列表做subset得到每一个数据对象的属性向量
Yield x.ItemValue(allFields)
Next
End With
End Function
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension>
Public Function Matrix(Of DataSet As DynamicPropertyBase(Of Double))(data As IEnumerable(Of DataSet)) As IEnumerable(Of Double())
Return Matrix(Of Double, DataSet)(data)
End Function
'<MethodImpl(MethodImplOptions.AggressiveInlining)>
'<Extension>
'Public Function Matrix(Of DataSet As DynamicPropertyBase(Of String))(data As IEnumerable(Of DataSet)) As IEnumerable(Of String())
' Return Matrix(Of String, DataSet)(data)
'End Function
''' <summary>
''' Converts a <see cref="DataTable"/> to a 2-dimensional array
''' </summary>
''' <param name="table">A System.Data.DataTable containing data to cluster</param>
''' <returns>A 2-dimensional array containing data to cluster</returns>
<Extension> Public Function ToFloatMatrix(table As DataTable) As Double(,)
Dim rowCount As Integer = table.Rows.Count
Dim fieldCount As Integer = table.Columns.Count
Dim dataPoints As Double(,)
Dim fieldValue As Double = 0.0
Dim row As DataRow
dataPoints = New Double(rowCount - 1, fieldCount - 1) {}
For rowPosition As Integer = 0 To rowCount - 1
row = table.Rows(rowPosition)
For fieldPosition As Integer = 0 To fieldCount - 1
Try
fieldValue = Double.Parse(row(fieldPosition).ToString())
Catch ex As Exception
Dim msg$ = $"Invalid row at {rowPosition.ToString()} and field {fieldPosition.ToString()}"
ex = New InvalidCastException(msg, ex)
ex.PrintException
Throw ex
End Try
dataPoints(rowPosition, fieldPosition) = fieldValue
Next
Next
Return dataPoints
End Function
''' <summary>
''' Gets property field data from a generic data frame
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="dataframe"></param>
''' <param name="property$"></param>
''' <returns></returns>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension>
Public Function DATA(Of T)(dataframe As IEnumerable(Of DynamicPropertyBase(Of T)), property$) As T()
Return dataframe.Select(Function(d) d([property])).ToArray
End Function
''' <summary>
''' Create an empty matrix with m row and n cols.
''' (生成一个有m行n列的矩阵但是是使用数组来表示的)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="m">m Rows</param>
''' <param name="n">n Cols</param>
''' <returns></returns>
Public Function MAT(Of T)(m%, n%) As T()()
Dim newMAT As T()() = New T(m - 1)() {}
For i As Integer = 0 To m - 1
newMAT(i) = New T(n - 1) {}
Next
Return newMAT
End Function
<Extension>
Public Function Rectangle(type As Type, m%, n%) As Array
Dim newMatrix As Array = Array.CreateInstance(type.MakeArrayType, m)
For i As Integer = 0 To m - 1
Call newMatrix.SetValue(Array.CreateInstance(type, n), i)
Next
Return newMatrix
End Function
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension>
Public Function SizeOf(Of T)(rect As T()()) As Size
Return New Size With {
.Width = rect(Scan0).Length,
.Height = rect.Length
}
End Function
''' <summary>
''' Convert the data collection into a matrix value.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="source">The elements number in each collection should be agreed!(要求集合之中的每一列之中的数据的元素数目都相等)</param>
''' <returns></returns>
''' <remarks></remarks>
<Extension> Public Function ToMatrix(Of T)(source As IEnumerable(Of IEnumerable(Of T))) As T(,)
Dim array As IEnumerable(Of T)() = source.ToArray
Dim width As Integer = array(Scan0).Count
Dim height As Integer = array.Length
Dim M As T(,) = New T(height - 1, width - 1) {}
For i As Integer = 0 To height - 1
Dim V As T() = array(i).ToArray
For j As Integer = 0 To width - 1
M(i, j) = V(j)
Next
Next
Return M
End Function
''' <summary>
''' Convert the matrix data into a collection of collection data type.(将矩阵对象转换为集合的集合的类型)
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="MAT"></param>
''' <returns></returns>
''' <remarks></remarks>
'''
<MethodImpl(MethodImplOptions.AggressiveInlining)>
<Extension> Public Function ToVectorList(Of T)(MAT As T(,)) As List(Of T())
Return MAT.RowIterator.AsList
End Function
#Region "Matrix Accessor Helper"
''' <summary>
''' Get matrix width and height values.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="m"></param>
''' <returns></returns>
<Extension>
Public Function GetSize(Of T)(m As T(,)) As Size
Dim w As Integer = m.GetLength(1)
Dim h As Integer = m.GetLength(0)
Return New Size With {
.Width = w,
.Height = h
}
End Function
''' <summary>
''' Iterates each row data in a matrix type array.
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="MAT"></param>
''' <returns></returns>
<Extension>
Public Iterator Function RowIterator(Of T)(MAT As T(,)) As IEnumerable(Of T())
Dim size As Size = MAT.GetSize
Dim temp As T()
For i As Integer = 0 To size.Height - 1
temp = New T(size.Width - 1) {}
For j As Integer = 0 To size.Width - 1
temp(j) = MAT(i, j)
Next
Yield temp
Next
End Function
<Extension>
Public Iterator Function GetRow(Of T)(m As T(,), i%) As IEnumerable(Of T)
Dim size As Size = m.GetSize
For j As Integer = 0 To size.Width - 1
Yield m(i, j)
Next
End Function
<Extension>
Public Function SetRow(Of T)(m As T(,), i%, data As IEnumerable(Of T)) As T(,)
Dim size As Size = m.GetSize
Dim j% = Scan0
For Each x As T In data
m(i, j) = x
j += 1
If j = size.Width Then
Exit For
End If
Next
Return m
End Function
<Extension>
Public Iterator Function GetCol(Of T)(m As T(,), j%) As IEnumerable(Of T)
Dim size As Size = m.GetSize
For i As Integer = 0 To size.Height - 1
Yield m(i, j)
Next
End Function
<Extension>
Public Function SetCol(Of T)(m As T(,), j%, data As IEnumerable(Of T)) As T(,)
Dim size As Size = m.GetSize
Dim i% = Scan0
For Each x As T In data
m(i, j) = x
i += 1
If i = size.Height Then
Exit For
End If
Next
Return m
End Function
#End Region
End Module