1 #Region "Microsoft.VisualBasic::770f5e7f5ea7cffe09c396c96c35ff4a, Microsoft.VisualBasic.Core\Extensions\Math\Correlations\Ranks.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 Ranks
35     
36     '         Function: Best, Sort
37     '         Class Ranking
38     
39     '             Properties: Evaluate, Max, Weight
40     
41     '             Function: Sort
42     
43     
44     
45     
46     ' /********************************************************************************/
47
48 #End Region
49
50 Imports Microsoft.VisualBasic.Linq
51
52 Namespace Math
53
54     Public Module Ranks
55
56         Public Class Ranking(Of T)
57
58             Public Property Evaluate As Func(Of T, Double)
59             ''' <summary>
60             ''' The sort direction
61             ''' </summary>
62             ''' <returns></returns>
63             Public Property Max As Boolean
64             ''' <summary>
65             ''' 默认不加权重
66             ''' </summary>
67             ''' <returns></returns>
68             Public Property Weight As Double = 1
69
70             Public Function Sort(source As IEnumerable(Of T)) As SeqValue(Of (T, Double))()
71                 Dim Evaluate As Func(Of T, Double) = Me.Evaluate
72                 Dim LQuery = (From x As T In source Select x, v = Evaluate(x)).ToArray
73                 Dim result As SeqValue(Of (T, Double))()
74                 Dim weights As IEnumerable(Of Double) = _Weight.Repeats(LQuery.Length)
75
76                 If Max Then   ' 由于后面需要进行加权计算,所以在这里是反过来求最大的
77                     result = (From x In LQuery Select x Order By x.v Ascending) _
78                         .Select(Function(x) x.x) _
79                         .Tuple(weights) _
80                         .SeqTuple _
81                         .ToArray
82                 Else
83                     result = (From x In LQuery Select x Order By x.v Descending) _
84                         .Select(Function(x) x.x) _
85                         .Tuple(weights) _
86                         .SeqTuple _
87                         .ToArray
88                 End If
89
90                 Return result
91             End Function
92         End Class
93
94         ''' <summary>
95         ''' 
96         ''' </summary>
97         ''' <typeparam name="T"></typeparam>
98         ''' <param name="source"></param>
99         ''' <param name="Evaluate"></param>
100         ''' <returns>Ranks值最小的是认为最好的</returns>
101         Public Function Best(Of T)(source As IEnumerable(Of T), Evaluate As IEnumerable(Of Ranking(Of T))) As T
102             Dim array As T() = Sort(source, Evaluate).ToArray
103             Return array.FirstOrDefault
104         End Function
105
106         Public Function Sort(Of T)(source As IEnumerable(Of T), Evaluate As IEnumerable(Of Ranking(Of T))) As IEnumerable(Of T)
107             Dim LQuery As IEnumerable(Of SeqValue(Of (item As T, weight As Double))) =
108                 (From method As Ranking(Of T)
109                  In Evaluate.AsParallel
110                  Select method.Sort(source)).IteratesALL
111             Dim groups = (From x In LQuery Select x Group x By x.value Into Group).ToArray
112             Dim ranks = (From x
113                          In groups.AsParallel
114                          Let rank = x.Group.Sum(Function(o) o.i * o.value.weight)  ' 加权重计算
115                          Select x.value, rank
116                          Order By rank Descending).ToArray
117             Return ranks.Select(Function(x) x.value)
118         End Function
119     End Module
120 End Namespace