pickRandom.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createPickRandom = void 0;
  6. var _array = require("../../utils/array.js");
  7. var _factory = require("../../utils/factory.js");
  8. var _is = require("../../utils/is.js");
  9. var _seededRNG = require("./util/seededRNG.js");
  10. var name = 'pickRandom';
  11. var dependencies = ['typed', 'config', '?on'];
  12. var createPickRandom = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  13. var typed = _ref.typed,
  14. config = _ref.config,
  15. on = _ref.on;
  16. // seeded pseudo random number generator
  17. var rng = (0, _seededRNG.createRng)(config.randomSeed);
  18. if (on) {
  19. on('config', function (curr, prev) {
  20. if (curr.randomSeed !== prev.randomSeed) {
  21. rng = (0, _seededRNG.createRng)(curr.randomSeed);
  22. }
  23. });
  24. }
  25. /**
  26. * Random pick one or more values from a one dimensional array.
  27. * Array elements are picked using a random function with uniform or weighted distribution.
  28. *
  29. * Syntax:
  30. *
  31. * math.pickRandom(array)
  32. * math.pickRandom(array, number)
  33. * math.pickRandom(array, weights)
  34. * math.pickRandom(array, number, weights)
  35. * math.pickRandom(array, weights, number)
  36. * math.pickRandom(array, { weights, number, elementWise })
  37. *
  38. * Examples:
  39. *
  40. * math.pickRandom([3, 6, 12, 2]) // returns one of the values in the array
  41. * math.pickRandom([3, 6, 12, 2], 2) // returns an array of two of the values in the array
  42. * math.pickRandom([3, 6, 12, 2], { number: 2 }) // returns an array of two of the values in the array
  43. * math.pickRandom([3, 6, 12, 2], [1, 3, 2, 1]) // returns one of the values in the array with weighted distribution
  44. * math.pickRandom([3, 6, 12, 2], 2, [1, 3, 2, 1]) // returns an array of two of the values in the array with weighted distribution
  45. * math.pickRandom([3, 6, 12, 2], [1, 3, 2, 1], 2) // returns an array of two of the values in the array with weighted distribution
  46. *
  47. * math.pickRandom([{x: 1.0, y: 2.0}, {x: 1.1, y: 2.0}], { elementWise: false })
  48. * // returns one of the items in the array
  49. *
  50. * See also:
  51. *
  52. * random, randomInt
  53. *
  54. * @param {Array | Matrix} array A one dimensional array
  55. * @param {Int} number An int or float
  56. * @param {Array | Matrix} weights An array of ints or floats
  57. * @return {number | Array} Returns a single random value from array when number is 1 or undefined.
  58. * Returns an array with the configured number of elements when number is > 1.
  59. */
  60. return typed(name, {
  61. 'Array | Matrix': function ArrayMatrix(possibles) {
  62. return _pickRandom(possibles, {});
  63. },
  64. 'Array | Matrix, Object': function ArrayMatrixObject(possibles, options) {
  65. return _pickRandom(possibles, options);
  66. },
  67. 'Array | Matrix, number': function ArrayMatrixNumber(possibles, number) {
  68. return _pickRandom(possibles, {
  69. number: number
  70. });
  71. },
  72. 'Array | Matrix, Array | Matrix': function ArrayMatrixArrayMatrix(possibles, weights) {
  73. return _pickRandom(possibles, {
  74. weights: weights
  75. });
  76. },
  77. 'Array | Matrix, Array | Matrix, number': function ArrayMatrixArrayMatrixNumber(possibles, weights, number) {
  78. return _pickRandom(possibles, {
  79. number: number,
  80. weights: weights
  81. });
  82. },
  83. 'Array | Matrix, number, Array | Matrix': function ArrayMatrixNumberArrayMatrix(possibles, number, weights) {
  84. return _pickRandom(possibles, {
  85. number: number,
  86. weights: weights
  87. });
  88. }
  89. });
  90. /**
  91. * @param {Array | Matrix} possibles
  92. * @param {{
  93. * number?: number,
  94. * weights?: Array | Matrix,
  95. * elementWise: boolean
  96. * }} options
  97. * @returns {number | Array}
  98. * @private
  99. */
  100. function _pickRandom(possibles, _ref2) {
  101. var number = _ref2.number,
  102. weights = _ref2.weights,
  103. _ref2$elementWise = _ref2.elementWise,
  104. elementWise = _ref2$elementWise === void 0 ? true : _ref2$elementWise;
  105. var single = typeof number === 'undefined';
  106. if (single) {
  107. number = 1;
  108. }
  109. var createMatrix = (0, _is.isMatrix)(possibles) ? possibles.create : (0, _is.isMatrix)(weights) ? weights.create : null;
  110. possibles = possibles.valueOf(); // get Array
  111. if (weights) {
  112. weights = weights.valueOf(); // get Array
  113. }
  114. if (elementWise === true) {
  115. possibles = (0, _array.flatten)(possibles);
  116. weights = (0, _array.flatten)(weights);
  117. }
  118. var totalWeights = 0;
  119. if (typeof weights !== 'undefined') {
  120. if (weights.length !== possibles.length) {
  121. throw new Error('Weights must have the same length as possibles');
  122. }
  123. for (var i = 0, len = weights.length; i < len; i++) {
  124. if (!(0, _is.isNumber)(weights[i]) || weights[i] < 0) {
  125. throw new Error('Weights must be an array of positive numbers');
  126. }
  127. totalWeights += weights[i];
  128. }
  129. }
  130. var length = possibles.length;
  131. var result = [];
  132. var pick;
  133. while (result.length < number) {
  134. if (typeof weights === 'undefined') {
  135. pick = possibles[Math.floor(rng() * length)];
  136. } else {
  137. var randKey = rng() * totalWeights;
  138. for (var _i = 0, _len = possibles.length; _i < _len; _i++) {
  139. randKey -= weights[_i];
  140. if (randKey < 0) {
  141. pick = possibles[_i];
  142. break;
  143. }
  144. }
  145. }
  146. result.push(pick);
  147. }
  148. return single ? result[0] : createMatrix ? createMatrix(result) : result;
  149. }
  150. });
  151. exports.createPickRandom = createPickRandom;