1 #Region "Microsoft.VisualBasic::85535aa28678e76ae6415cfda4084efb, Microsoft.VisualBasic.Core\Extensions\Collection\Matrix.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     Module MatrixExtensions
35     
36     '     Function: DATA, GetCol, GetRow, GetSize, MAT
37     '               (+2 Overloads) Matrix, RowIterator, SetCol, SetRow, ToFloatMatrix
38     '               ToMatrix, ToVectorList
39     
40     ' /********************************************************************************/
41
42 #End Region
43
44 Imports System.Drawing
45 Imports System.Runtime.CompilerServices
46 Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
47 Imports Microsoft.VisualBasic.Language
48 Imports Microsoft.VisualBasic.Linq
49
50 Public Module MatrixExtensions
51
52     ''' <summary>
53     ''' 将数据集之中的虽有属性值取出来构建一个矩阵
54     ''' </summary>
55     ''' <param name="data"></param>
56     ''' <returns></returns>
57     Public Iterator Function Matrix(Of T, DataSet As DynamicPropertyBase(Of T))(data As IEnumerable(Of DataSet)) As IEnumerable(Of T())
58         With data.ToArray
59             Dim allFields = .Select(Function(x) x.Properties.Keys) _
60                             .IteratesALL _
61                             .Distinct _
62                             .ToArray
63
64             For Each x As DataSet In .ByRef
65                 ' 利用属性名列表做subset,得到每一个数据对象的属性向量
66                 Yield x.ItemValue(allFields)
67             Next
68         End With
69     End Function
70
71     <MethodImpl(MethodImplOptions.AggressiveInlining)>
72     <Extension>
73     Public Function Matrix(Of DataSet As DynamicPropertyBase(Of Double))(data As IEnumerable(Of DataSet)) As IEnumerable(Of Double())
74         Return Matrix(Of Double, DataSet)(data)
75     End Function
76
77     '<MethodImpl(MethodImplOptions.AggressiveInlining)>
78     '<Extension>
79     'Public Function Matrix(Of DataSet As DynamicPropertyBase(Of String))(data As IEnumerable(Of DataSet)) As IEnumerable(Of String())
80     '    Return Matrix(Of String, DataSet)(data)
81     'End Function
82
83     ''' <summary>
84     ''' Converts a <see cref="DataTable"/> to a 2-dimensional array
85     ''' </summary>
86     ''' <param name="table">A System.Data.DataTable containing data to cluster</param>
87     ''' <returns>A 2-dimensional array containing data to cluster</returns>
88     <Extension> Public Function ToFloatMatrix(table As DataTable) As Double(,)
89         Dim rowCount As Integer = table.Rows.Count
90         Dim fieldCount As Integer = table.Columns.Count
91         Dim dataPoints As Double(,)
92         Dim fieldValue As Double = 0.0
93         Dim row As DataRow
94
95         dataPoints = New Double(rowCount - 1, fieldCount - 1) {}
96
97         For rowPosition As Integer = 0 To rowCount - 1
98             row = table.Rows(rowPosition)
99
100             For fieldPosition As Integer = 0 To fieldCount - 1
101                 Try
102                     fieldValue = Double.Parse(row(fieldPosition).ToString())
103                 Catch ex As Exception
104                     Dim msg$ = $"Invalid row at {rowPosition.ToString()} and field {fieldPosition.ToString()}"
105                     ex = New InvalidCastException(msg, ex)
106                     ex.PrintException
107
108                     Throw ex
109                 End Try
110
111                 dataPoints(rowPosition, fieldPosition) = fieldValue
112             Next
113         Next
114
115         Return dataPoints
116     End Function
117
118     ''' <summary>
119     ''' Gets property field data from a generic data frame
120     ''' </summary>
121     ''' <typeparam name="T"></typeparam>
122     ''' <param name="dataframe"></param>
123     ''' <param name="property$"></param>
124     ''' <returns></returns>
125     ''' 
126     <MethodImpl(MethodImplOptions.AggressiveInlining)>
127     <Extension>
128     Public Function DATA(Of T)(dataframe As IEnumerable(Of DynamicPropertyBase(Of T)), property$) As T()
129         Return dataframe.Select(Function(d) d([property])).ToArray
130     End Function
131
132     ''' <summary>
133     ''' Create an empty matrix with m row and n cols.
134     ''' (生成一个有m行n列的矩阵,但是是使用数组来表示的)
135     ''' </summary>
136     ''' <typeparam name="T"></typeparam>
137     ''' <param name="m">m Rows</param>
138     ''' <param name="n">n Cols</param>
139     ''' <returns></returns>
140     Public Function MAT(Of T)(m%, n%) As T()()
141         Dim newMAT As T()() = New T(m - 1)() {}
142
143         For i As Integer = 0 To m - 1
144             newMAT(i) = New T(n - 1) {}
145         Next
146
147         Return newMAT
148     End Function
149
150     ''' <summary>
151     ''' Convert the data collection into a matrix value.
152     ''' </summary>
153     ''' <typeparam name="T"></typeparam>
154     ''' <param name="source">The elements number in each collection should be agreed!(要求集合之中的每一列之中的数据的元素数目都相等)</param>
155     ''' <returns></returns>
156     ''' <remarks></remarks>
157     <Extension> Public Function ToMatrix(Of T)(source As IEnumerable(Of IEnumerable(Of T))) As T(,)
158         Dim array As IEnumerable(Of T)() = source.ToArray
159         Dim width As Integer = array(Scan0).Count
160         Dim height As Integer = array.Length
161         Dim M As T(,) = New T(height - 1, width - 1) {}
162
163         For i As Integer = 0 To height - 1
164             Dim V As T() = array(i).ToArray
165
166             For j As Integer = 0 To width - 1
167                 M(i, j) = V(j)
168             Next
169         Next
170
171         Return M
172     End Function
173
174     ''' <summary>
175     ''' Convert the matrix data into a collection of collection data type.(将矩阵对象转换为集合的集合的类型)
176     ''' </summary>
177     ''' <typeparam name="T"></typeparam>
178     ''' <param name="MAT"></param>
179     ''' <returns></returns>
180     ''' <remarks></remarks>
181     ''' 
182     <MethodImpl(MethodImplOptions.AggressiveInlining)>
183     <Extension> Public Function ToVectorList(Of T)(MAT As T(,)) As List(Of T())
184         Return MAT.RowIterator.AsList
185     End Function
186
187 #Region "Matrix Accessor Helper"
188
189     ''' <summary>
190     ''' Get matrix width and height values.
191     ''' </summary>
192     ''' <typeparam name="T"></typeparam>
193     ''' <param name="m"></param>
194     ''' <returns></returns>
195     <Extension>
196     Public Function GetSize(Of T)(m As T(,)) As Size
197         Dim w As Integer = m.GetLength(1)
198         Dim h As Integer = m.GetLength(0)
199
200         Return New Size With {
201             .Width = w,
202             .Height = h
203         }
204     End Function
205
206     ''' <summary>
207     ''' Iterates each row data in a matrix type array.
208     ''' </summary>
209     ''' <typeparam name="T"></typeparam>
210     ''' <param name="MAT"></param>
211     ''' <returns></returns>
212     <Extension>
213     Public Iterator Function RowIterator(Of T)(MAT As T(,)) As IEnumerable(Of T())
214         Dim size As Size = MAT.GetSize
215         Dim temp As T()
216
217         For i As Integer = 0 To size.Height - 1
218             temp = New T(size.Width - 1) {}
219
220             For j As Integer = 0 To size.Width - 1
221                 temp(j) = MAT(i, j)
222             Next
223
224             Yield temp
225         Next
226     End Function
227
228     <Extension>
229     Public Iterator Function GetRow(Of T)(m As T(,), i%) As IEnumerable(Of T)
230         Dim size As Size = m.GetSize
231
232         For j As Integer = 0 To size.Width - 1
233             Yield m(i, j)
234         Next
235     End Function
236
237     <Extension>
238     Public Function SetRow(Of T)(m As T(,), i%, data As IEnumerable(Of T)) As T(,)
239         Dim size As Size = m.GetSize
240         Dim j% = Scan0
241
242         For Each x As T In data
243             m(i, j) = x
244             j += 1
245
246             If j = size.Width Then
247                 Exit For
248             End If
249         Next
250
251         Return m
252     End Function
253
254     <Extension>
255     Public Iterator Function GetCol(Of T)(m As T(,), j%) As IEnumerable(Of T)
256         Dim size As Size = m.GetSize
257
258         For i As Integer = 0 To size.Height - 1
259             Yield m(i, j)
260         Next
261     End Function
262
263     <Extension>
264     Public Function SetCol(Of T)(m As T(,), j%, data As IEnumerable(Of T)) As T(,)
265         Dim size As Size = m.GetSize
266         Dim i% = Scan0
267
268         For Each x As T In data
269             m(i, j) = x
270             i += 1
271
272             If i = size.Height Then
273                 Exit For
274             End If
275         Next
276
277         Return m
278     End Function
279 #End Region
280 End Module