| 1 | #Region "Microsoft.VisualBasic::33776f60c24dae9f2254b706bc01cec0, Microsoft.VisualBasic.Core\Extensions\Math\Random\RandomExtensions.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 | ' Delegate Function |
| 35 | ' |
| 36 | ' |
| 37 | ' Delegate Function |
| 38 | ' |
| 39 | ' |
| 40 | ' Module RandomExtensions |
| 41 | ' |
| 42 | ' Function: (+2 Overloads) GetRandomValue, NextBoolean, (+2 Overloads) NextDouble, NextGaussian, NextTriangular |
| 43 | ' Permutation, randf, RandomSingle, Seed |
| 44 | ' |
| 45 | ' Sub: (+2 Overloads) Shuffle |
| 46 | ' |
| 47 | ' |
| 48 | ' |
| 49 | ' |
| 50 | ' |
| 51 | ' /********************************************************************************/ |
| 52 | |
| 53 | #End Region |
| 54 | |
| 55 | Imports System.Runtime.CompilerServices |
| 56 | Imports Microsoft.VisualBasic.CommandLine.Reflection |
| 57 | Imports Microsoft.VisualBasic.ComponentModel.Ranges.Model |
| 58 | Imports Microsoft.VisualBasic.Language.C |
| 59 | Imports Microsoft.VisualBasic.Scripting.MetaData |
| 60 | Imports sys = System.Math |
| 61 | |
| 62 | Namespace Math |
| 63 | |
| 64 | ''' <summary> |
| 65 | ''' Generates a random number. |
| 66 | ''' (事实上这个函数指针的功能仅仅是返回一个实数,所以这里不仅仅是局限于随机数,也可以是一个固定值的实数) |
| 67 | ''' </summary> |
| 68 | ''' <returns></returns> |
| 69 | Public Delegate Function IValueProvider() As Double |
| 70 | |
| 71 | ''' <summary> |
| 72 | ''' Tells the function how to generates a new random seed? |
| 73 | ''' </summary> |
| 74 | ''' <returns></returns> |
| 75 | Public Delegate Function IRandomSeeds() As Random |
| 76 | |
| 77 | ''' <summary> |
| 78 | ''' Some extension methods for <see cref="System.Random"/> for creating a few more kinds of random stuff. |
| 79 | ''' </summary> |
| 80 | ''' <remarks>Imports from https://github.com/rvs76/superbest-random.git </remarks> |
| 81 | ''' |
| 82 | <Package("Random", Publisher:="rvs76", Description:="Some extension methods for Random for creating a few more kinds of random stuff.")> |
| 83 | Public Module RandomExtensions |
| 84 | |
| 85 | ''' <summary> |
| 86 | ''' A number used to calculate a starting value for the pseudo-random number sequence. |
| 87 | ''' If a negative number is specified, the absolute value of the number is used. |
| 88 | ''' </summary> |
| 89 | ''' <returns></returns> |
| 90 | Public Function Seed() As Integer |
| 91 | Dim seeds& = CLng(Integer.MaxValue) * 2 |
| 92 | Randomize() |
| 93 | seeds = (Rnd() * SecurityString.ToLong(SecurityString.GetMd5Hash(Now.ToString))) / seeds |
| 94 | Return CInt(seeds) |
| 95 | End Function |
| 96 | |
| 97 | Const RandfMultiply# = 10000 |
| 98 | |
| 99 | ''' <summary> |
| 100 | ''' 返回<paramref name="min"/>到<paramref name="max"/>区间之内的一个和实数 |
| 101 | ''' </summary> |
| 102 | ''' <param name="min"></param> |
| 103 | ''' <param name="max"></param> |
| 104 | ''' <returns></returns> |
| 105 | Public Function randf(min As Double, max As Double) As Double |
| 106 | Dim minInteger& = CLng(sys.Truncate(min * RandfMultiply)) |
| 107 | Dim maxInteger& = CLng(sys.Truncate(max * RandfMultiply)) |
| 108 | Dim randInteger& = CLng(RandomNumbers.rand()) * CLng(RandomNumbers.rand()) |
| 109 | Dim diffInteger& = maxInteger - minInteger |
| 110 | Dim resultInteger& = randInteger Mod diffInteger + minInteger |
| 111 | |
| 112 | Return resultInteger / RandfMultiply |
| 113 | End Function |
| 114 | |
| 115 | ReadOnly seeds As New Random(Rnd() * 10000) |
| 116 | |
| 117 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
| 118 | Public Function RandomSingle() As Single |
| 119 | Return seeds.NextDouble() |
| 120 | End Function |
| 121 | |
| 122 | <Extension> |
| 123 | Public Function GetRandomValue(rng As DoubleRange) As Double |
| 124 | SyncLock seeds |
| 125 | Return seeds.NextDouble(range:=rng) |
| 126 | End SyncLock |
| 127 | End Function |
| 128 | |
| 129 | ''' <summary> |
| 130 | ''' Returns a random floating-point number that is greater than or equal to min of the range, |
| 131 | ''' and less than the max of the range. |
| 132 | ''' </summary> |
| 133 | ''' <param name="rnd"></param> |
| 134 | ''' <param name="range"></param> |
| 135 | ''' <returns></returns> |
| 136 | <Extension> |
| 137 | Public Function NextDouble(rnd As Random, range As DoubleRange) As Double |
| 138 | Return range.Length * rnd.NextDouble + range.Min |
| 139 | End Function |
| 140 | |
| 141 | <Extension> |
| 142 | Public Function NextDouble(rand As Random, min#, max#) As Double |
| 143 | Return (max - min) * rand.NextDouble + min |
| 144 | End Function |
| 145 | |
| 146 | <Extension> |
| 147 | Public Function GetRandomValue(rng As IntRange) As Integer |
| 148 | Return rng.Length * seeds.NextDouble + rng.Min |
| 149 | End Function |
| 150 | |
| 151 | ''' <summary> |
| 152 | ''' Generates normally distributed numbers. Each operation makes two Gaussians for the price of one, and apparently they can be cached or something for better performance, but who cares. |
| 153 | ''' </summary> |
| 154 | ''' <param name="r"></param> |
| 155 | ''' <param name = "mu">Mean of the distribution</param> |
| 156 | ''' <param name = "sigma">Standard deviation</param> |
| 157 | ''' <returns></returns> |
| 158 | ''' |
| 159 | <ExportAPI("NextGaussian")> |
| 160 | <Extension> Public Function NextGaussian(r As Random, Optional mu As Double = 0, Optional sigma As Double = 1) As Double |
| 161 | Dim u1 As Double = r.NextDouble() |
| 162 | Dim u2 As Double = r.NextDouble() |
| 163 | |
| 164 | Dim rand_std_normal = sys.Sqrt(-2.0 * sys.Log(u1)) * sys.Sin(2.0 * sys.PI * u2) |
| 165 | Dim rand_normal = mu + sigma * rand_std_normal |
| 166 | |
| 167 | Return rand_normal |
| 168 | End Function |
| 169 | |
| 170 | ''' <summary> |
| 171 | ''' Generates values from a triangular distribution. |
| 172 | ''' </summary> |
| 173 | ''' <remarks> |
| 174 | ''' See http://en.wikipedia.org/wiki/Triangular_distribution for a description of the triangular probability distribution and the algorithm for generating one. |
| 175 | ''' </remarks> |
| 176 | ''' <param name="r"></param> |
| 177 | ''' <param name = "a">Minimum</param> |
| 178 | ''' <param name = "b">Maximum</param> |
| 179 | ''' <param name = "c">Mode (most frequent value)</param> |
| 180 | ''' <returns></returns> |
| 181 | ''' |
| 182 | <ExportAPI("NextTriangular")> |
| 183 | <Extension> Public Function NextTriangular(r As Random, a As Double, b As Double, c As Double) As Double |
| 184 | Dim u As Double = r.NextDouble() |
| 185 | Return If(u < (c - a) / (b - a), a + sys.Sqrt(u * (b - a) * (c - a)), b - sys.Sqrt((1 - u) * (b - a) * (b - c))) |
| 186 | End Function |
| 187 | |
| 188 | ''' <summary> |
| 189 | ''' Equally likely to return true or false. Uses <see cref="Random.Next(Integer)"/>. |
| 190 | ''' </summary> |
| 191 | ''' <returns></returns> |
| 192 | ''' <remarks> |
| 193 | ''' ```vbnet |
| 194 | ''' 1 > 0 OR 0 > 0 |
| 195 | ''' ``` |
| 196 | ''' </remarks> |
| 197 | <ExportAPI("NextBoolean")> |
| 198 | <Extension> Public Function NextBoolean(r As Random) As Boolean |
| 199 | Return r.[Next](2) > 0 ' 1 > 0 OR 0 > 0 |
| 200 | End Function |
| 201 | |
| 202 | ''' <summary> |
| 203 | ''' Shuffles a list in O(n) time by using the Fisher-Yates/Knuth algorithm. |
| 204 | ''' </summary> |
| 205 | ''' <param name="r"></param> |
| 206 | ''' <param name = "list"></param> |
| 207 | <Extension> Public Sub Shuffle(Of T)(r As Random, ByRef list As List(Of T)) |
| 208 | For i As Integer = 0 To list.Count - 1 |
| 209 | Dim j As Integer = r.[Next](0, i + 1) |
| 210 | Dim temp As T = list(j) |
| 211 | list(j) = list(i) |
| 212 | list(i) = temp |
| 213 | Next |
| 214 | End Sub |
| 215 | |
| 216 | ''' <summary> |
| 217 | ''' Shuffles a list in O(n) time by using the Fisher-Yates/Knuth algorithm. |
| 218 | ''' </summary> |
| 219 | ''' <param name="r"></param> |
| 220 | ''' <param name = "list"></param> |
| 221 | ''' |
| 222 | <ExportAPI("Shuffle")> |
| 223 | Public Sub Shuffle(r As Random, ByRef list As IList) |
| 224 | For i As Integer = 0 To list.Count - 1 |
| 225 | Dim j As Integer = r.[Next](0, i + 1) |
| 226 | Dim temp = list(j) |
| 227 | list(j) = list(i) |
| 228 | list(i) = temp |
| 229 | Next |
| 230 | End Sub |
| 231 | |
| 232 | ''' <summary> |
| 233 | ''' Returns n unique random numbers in the range [1, n], inclusive. |
| 234 | ''' This is equivalent to getting the first n numbers of some random permutation of the sequential numbers from 1 to max. |
| 235 | ''' Runs in O(k^2) time. |
| 236 | ''' </summary> |
| 237 | ''' <param name="rand"></param> |
| 238 | ''' <param name="n">Maximum number possible.(最大值)</param> |
| 239 | ''' <param name="k">How many numbers to return.(返回的数据的数目)</param> |
| 240 | ''' <returns></returns> |
| 241 | ''' |
| 242 | <ExportAPI("Permutation")> |
| 243 | <Extension> Public Function Permutation(rand As Random, n As Integer, k As Integer) As Integer() |
| 244 | Dim result As New List(Of Integer)() |
| 245 | Dim sorted As New SortedSet(Of Integer)() |
| 246 | |
| 247 | For i As Integer = 0 To k - 1 |
| 248 | Dim r = rand.[Next](1, n + 1 - i) |
| 249 | |
| 250 | For Each q As Integer In sorted |
| 251 | If r >= q Then |
| 252 | r += 1 |
| 253 | End If |
| 254 | Next |
| 255 | |
| 256 | result.Add(r) |
| 257 | sorted.Add(r) |
| 258 | Next |
| 259 | |
| 260 | Return result.ToArray() |
| 261 | End Function |
| 262 | End Module |
| 263 | End Namespace |