322 lines
12 KiB
VB.net
322 lines
12 KiB
VB.net
#Region "Microsoft.VisualBasic::1da58685ed6ef204d07121ad3a8890fd, Microsoft.VisualBasic.Core\Extensions\Math\Random\RandomExtensions.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:
|
|
|
|
' Delegate Function
|
|
'
|
|
'
|
|
' Delegate Function
|
|
'
|
|
'
|
|
' Module RandomExtensions
|
|
'
|
|
' Properties: seeds
|
|
'
|
|
' Function: GetNextBetween, (+2 Overloads) GetRandomValue, NextBoolean, (+2 Overloads) NextDouble, (+2 Overloads) NextGaussian
|
|
' NextInteger, NextTriangular, Permutation, randf, RandomSingle
|
|
' Seed
|
|
'
|
|
' Sub: SetSeed, (+3 Overloads) Shuffle
|
|
'
|
|
'
|
|
'
|
|
'
|
|
'
|
|
' /********************************************************************************/
|
|
|
|
#End Region
|
|
|
|
Imports System.Runtime.CompilerServices
|
|
Imports Microsoft.VisualBasic.CommandLine.Reflection
|
|
Imports Microsoft.VisualBasic.ComponentModel.Ranges.Model
|
|
Imports Microsoft.VisualBasic.Scripting.MetaData
|
|
Imports stdNum = System.Math
|
|
|
|
Namespace Math
|
|
|
|
''' <summary>
|
|
''' Generates a random number.
|
|
''' (事实上这个函数指针的功能仅仅是返回一个实数,所以这里不仅仅是局限于随机数,也可以是一个固定值的实数)
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Delegate Function IValueProvider() As Double
|
|
|
|
''' <summary>
|
|
''' Tells the function how to generates a new random seed?
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Delegate Function IRandomSeeds() As Random
|
|
|
|
''' <summary>
|
|
''' Some extension methods for <see cref="System.Random"/> for creating a few more kinds of random stuff.
|
|
''' </summary>
|
|
''' <remarks>Imports from https://github.com/rvs76/superbest-random.git </remarks>
|
|
'''
|
|
<Package("Random", Publisher:="rvs76", Description:="Some extension methods for Random for creating a few more kinds of random stuff.")>
|
|
Public Module RandomExtensions
|
|
|
|
''' <summary>
|
|
''' A number used to calculate a starting value for the pseudo-random number sequence.
|
|
''' If a negative number is specified, the absolute value of the number is used.
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Function Seed() As Integer
|
|
Return stdNum.Abs(CInt(stdNum.Log10(Rnd() * Now.ToBinary + 1) + 1) * (100 + 10000 * Rnd()))
|
|
End Function
|
|
|
|
Public Sub SetSeed(seed As Integer)
|
|
_seeds = New Random(seed)
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' 返回<paramref name="min"/>到<paramref name="max"/>区间之内的一个和实数
|
|
''' </summary>
|
|
''' <param name="min"></param>
|
|
''' <param name="max"></param>
|
|
''' <returns></returns>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Function randf(min As Double, max As Double) As Double
|
|
Return seeds.NextDouble(min, max)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' 一般来说,在获取随机数的时候并不推荐重新构建一个新的随机数发生器
|
|
''' 可以在全局范围内重复使用这个随机数发生器
|
|
''' 不同的代码重复使用这个种子,这样子可以尽量的模拟出真正的随机行为
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public ReadOnly Property seeds As New Random(Now.Millisecond * Now.Second + 1)
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
Public Function RandomSingle() As Double
|
|
Return seeds.NextDouble()
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a non-negative random integer that is less than the specified maximum.
|
|
''' </summary>
|
|
''' <param name="upper">
|
|
''' The exclusive upper bound of the random number to be generated. maxValue must
|
|
''' be greater than or equal to 0.</param>
|
|
''' <returns>
|
|
''' A 32-bit signed integer that is greater than or equal to 0, and less than maxValue;
|
|
''' that is, the range of return values ordinarily includes 0 but not maxValue. However,
|
|
''' if maxValue equals 0, maxValue is returned.
|
|
''' </returns>
|
|
Public Function NextInteger(upper As Integer) As Integer
|
|
SyncLock seeds
|
|
Return seeds.Next(upper)
|
|
End SyncLock
|
|
End Function
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<Extension>
|
|
Public Function GetNextBetween(r As Random, min#, max#) As Double
|
|
Return (max - min) * r.NextDouble + min
|
|
End Function
|
|
|
|
<Extension>
|
|
Public Function GetRandomValue(rng As DoubleRange) As Double
|
|
SyncLock seeds
|
|
Return seeds.NextDouble(range:=rng)
|
|
End SyncLock
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns a random floating-point number that is greater than or equal to min of the range,
|
|
''' and less than the max of the range.
|
|
''' </summary>
|
|
''' <param name="rnd"></param>
|
|
''' <param name="range"></param>
|
|
''' <returns></returns>
|
|
'''
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<Extension>
|
|
Public Function NextDouble(rnd As Random, range As DoubleRange) As Double
|
|
Return range.Length * rnd.NextDouble + range.Min
|
|
End Function
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<Extension>
|
|
Public Function NextDouble(rand As Random, min#, max#) As Double
|
|
Return (max - min) * rand.NextDouble + min
|
|
End Function
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<Extension>
|
|
Public Function GetRandomValue(rng As IntRange) As Integer
|
|
Return rng.Length * seeds.NextDouble + rng.Min
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' 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.
|
|
''' </summary>
|
|
''' <param name="r"></param>
|
|
''' <param name = "mu">Mean of the distribution</param>
|
|
''' <param name = "sigma">Standard deviation</param>
|
|
''' <returns></returns>
|
|
'''
|
|
<ExportAPI("NextGaussian")>
|
|
<Extension> Public Function NextGaussian(r As Random, Optional mu As Double = 0, Optional sigma As Double = 1) As Double
|
|
Dim u1 As Double = r.NextDouble()
|
|
Dim u2 As Double = r.NextDouble()
|
|
|
|
Dim rand_std_normal = stdNum.Sqrt(-2.0 * stdNum.Log(u1)) * stdNum.Sin(2.0 * stdNum.PI * u2)
|
|
Dim rand_normal = mu + sigma * rand_std_normal
|
|
|
|
Return rand_normal
|
|
End Function
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<ExportAPI("NextGaussian")>
|
|
Public Function NextGaussian(Optional mu As Double = 0, Optional sigma As Double = 1) As Double
|
|
Return seeds.NextGaussian(mu, sigma)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Generates values from a triangular distribution.
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' See http://en.wikipedia.org/wiki/Triangular_distribution for a description of the triangular
|
|
''' probability distribution and the algorithm for generating one.
|
|
''' </remarks>
|
|
''' <param name="r"></param>
|
|
''' <param name = "a">Minimum</param>
|
|
''' <param name = "b">Maximum</param>
|
|
''' <param name = "c">Mode (most frequent value)</param>
|
|
''' <returns></returns>
|
|
'''
|
|
<ExportAPI("NextTriangular")>
|
|
<Extension> Public Function NextTriangular(r As Random, a As Double, b As Double, c As Double) As Double
|
|
Dim u As Double = r.NextDouble()
|
|
Return If(u < (c - a) / (b - a), a + stdNum.Sqrt(u * (b - a) * (c - a)), b - stdNum.Sqrt((1 - u) * (b - a) * (b - c)))
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Equally likely to return true or false. Uses <see cref="Random.Next(Integer)"/>.
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
''' <remarks>
|
|
''' ```vbnet
|
|
''' 1 > 0 OR 0 > 0
|
|
''' ```
|
|
''' </remarks>
|
|
<ExportAPI("NextBoolean")>
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<Extension> Public Function NextBoolean(r As Random) As Boolean
|
|
Return r.[Next](2) > 0 ' 1 > 0 OR 0 > 0
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Shuffles a list in O(n) time by using the Fisher-Yates/Knuth algorithm.
|
|
''' </summary>
|
|
''' <param name="r"></param>
|
|
''' <param name = "list"></param>
|
|
<Extension> Public Sub Shuffle(Of T)(r As Random, ByRef list As List(Of T))
|
|
Dim j As Integer
|
|
Dim temp As T
|
|
|
|
For i As Integer = 0 To list.Count - 1
|
|
j = r.[Next](0, i + 1)
|
|
temp = list(j)
|
|
list(j) = list(i)
|
|
list(i) = temp
|
|
Next
|
|
End Sub
|
|
|
|
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
|
<Extension>
|
|
Public Sub Shuffle(Of T)(ByRef list As List(Of T))
|
|
SyncLock seeds
|
|
Call seeds.Shuffle(list)
|
|
End SyncLock
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Shuffles a list in O(n) time by using the Fisher-Yates/Knuth algorithm.
|
|
''' </summary>
|
|
''' <param name="r"></param>
|
|
''' <param name = "list"></param>
|
|
'''
|
|
<ExportAPI("Shuffle")>
|
|
Public Sub Shuffle(r As Random, ByRef list As IList)
|
|
Dim j As Integer
|
|
Dim temp As Object
|
|
|
|
For i As Integer = 0 To list.Count - 1
|
|
j = r.[Next](0, i + 1)
|
|
temp = list(j)
|
|
list(j) = list(i)
|
|
list(i) = temp
|
|
Next
|
|
End Sub
|
|
|
|
''' <summary>
|
|
''' Returns n unique random numbers in the range ``[1, n]``, inclusive.
|
|
''' This is equivalent to getting the first n numbers of some random permutation of the sequential
|
|
''' numbers from 1 to max.
|
|
'''
|
|
''' Runs in ``O(k^2)`` time.
|
|
''' </summary>
|
|
''' <param name="rand"></param>
|
|
''' <param name="n">Maximum number possible.(最大值)</param>
|
|
''' <param name="k">How many numbers to return.(返回的数据的数目)</param>
|
|
''' <returns></returns>
|
|
'''
|
|
<ExportAPI("Permutation")>
|
|
<Extension>
|
|
Public Iterator Function Permutation(rand As Random, n As Integer, k As Integer) As IEnumerable(Of Integer)
|
|
Dim sorted As New SortedSet(Of Integer)()
|
|
|
|
For i As Integer = 0 To k - 1
|
|
Dim r = rand.[Next](1, n + 1 - i)
|
|
|
|
For Each q As Integer In sorted
|
|
If r >= q Then
|
|
r += 1
|
|
End If
|
|
Next
|
|
|
|
Call sorted.Add(r)
|
|
|
|
Yield r
|
|
Next
|
|
End Function
|
|
End Module
|
|
End Namespace
|