util_random.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package gago
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "time"
  6. )
  7. // newRandomNumberGenerator returns a new random number generator with a random
  8. // seed.
  9. func newRandomNumberGenerator() *rand.Rand {
  10. return rand.New(rand.NewSource(time.Now().UnixNano()))
  11. }
  12. // Sample k unique integers in range [min, max) using reservoir sampling,
  13. // specifically Vitter's Algorithm R.
  14. func randomInts(k, min, max int, rng *rand.Rand) (ints []int) {
  15. ints = make([]int, k)
  16. for i := 0; i < k; i++ {
  17. ints[i] = i + min
  18. }
  19. for i := k; i < max-min; i++ {
  20. var j = rng.Intn(i + 1)
  21. if j < k {
  22. ints[j] = i + min
  23. }
  24. }
  25. return
  26. }
  27. // Sample k unique integers from a slice of n integers without replacement.
  28. func sampleInts(ints []int, k int, rng *rand.Rand) ([]int, []int, error) {
  29. if k > len(ints) {
  30. return nil, nil, fmt.Errorf("Cannot sample %d elements from array of length %d", k, len(ints))
  31. }
  32. var (
  33. sample = make([]int, k)
  34. idxs = make([]int, k)
  35. )
  36. for i, idx := range randomInts(k, 0, len(ints), rng) {
  37. sample[i] = ints[idx]
  38. idxs[i] = idx
  39. }
  40. return sample, idxs, nil
  41. }
  42. // Generate random weights that sum up to 1.
  43. func randomWeights(size int) []float64 {
  44. var (
  45. weights = make([]float64, size)
  46. total float64
  47. )
  48. for i := range weights {
  49. weights[i] = rand.Float64()
  50. total += weights[i]
  51. }
  52. var normalized = divide(weights, total)
  53. return normalized
  54. }
  55. const (
  56. letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  57. letterIdxBits = 6 // 6 bits to represent a letter index
  58. letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
  59. letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
  60. )
  61. func randString(n int, rng *rand.Rand) string {
  62. b := make([]byte, n)
  63. for i, cache, remain := n-1, rng.Int63(), letterIdxMax; i >= 0; {
  64. if remain == 0 {
  65. cache, remain = rng.Int63(), letterIdxMax
  66. }
  67. if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
  68. b[i] = letterBytes[idx]
  69. i--
  70. }
  71. cache >>= letterIdxBits
  72. remain--
  73. }
  74. return string(b)
  75. }