simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

pickRandom.js (5725B)


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