add pickMultipleRandom function

This commit is contained in:
Mathias Polligkeit 2016-06-30 02:19:09 +02:00
parent 7511d4288d
commit c5e40b40ef
12 changed files with 195 additions and 8 deletions

View File

@ -8,7 +8,7 @@ module.exports = {
'description':
'Create a distribution object of a specific type. ' +
'A distribution object contains functions `random([size,] [min,] [max])`, ' +
'`randomInt([size,] [min,] [max])`, and `pickRandom(array)`. ' +
'`randomInt([size,] [min,] [max])`, `pickRandom(array)` and `pickMultipleRandom(array)`. ' +
'Available types of distributions: "uniform", "normal". ' +
'Note that the function distribution is currently not available via the expression parser.',
'examples': [

View File

@ -0,0 +1,13 @@
module.exports = {
'name': 'pickMultipleRandom',
'category': 'Probability',
'syntax': [
'pickMultipleRandom(array, number)'
],
'description':
'Pick a given number of random entries from a given array.',
'examples': [
'pickRandom([1, 3, 1, 6], 2)'
],
'seealso': ['random', 'randomInt', 'pickRandom']
};

View File

@ -16,5 +16,5 @@ module.exports = {
'random(10, 20)',
'random([2, 3])'
],
'seealso': ['pickRandom', 'randomInt']
'seealso': ['pickRandom', 'pickMultipleRandom', 'randomInt']
};

View File

@ -14,5 +14,5 @@ module.exports = {
'randInt(10, 20)',
'randInt([2, 3], 10)'
],
'seealso': ['pickRandom', 'random']
'seealso': ['pickRandom', 'pickMultipleRandom', 'random']
};

View File

@ -207,6 +207,7 @@ function factory (construction, config, load, typed) {
docs.multinomial = require('./function/probability/multinomial');
docs.permutations = require('./function/probability/permutations');
docs.pickRandom = require('./function/probability/pickRandom');
docs.pickMultipleRandom = require('./function/probability/pickMultipleRandom');
docs.random = require('./function/probability/random');
docs.randomInt = require('./function/probability/randomInt');

View File

@ -24,13 +24,14 @@ function factory (type, config, load, typed) {
*
* See also:
*
* random, randomInt, pickRandom
* random, randomInt, pickRandom, pickMultipleRandom
*
* @param {string} name Name of a distribution. Choose from 'uniform', 'normal'.
* @return {Object} Returns a distribution object containing functions:
* `random([size] [, min] [, max])`,
* `randomInt([min] [, max])`,
* `pickRandom(array)`
* `pickRandom(array)`,
* `pickMultipleRandom(array, number)`
*/
function distribution(name) {
if (!distributions.hasOwnProperty(name))
@ -142,8 +143,43 @@ function factory (type, config, load, typed) {
// TODO: add support for multi dimensional matrices
return possibles[Math.floor(Math.random() * possibles.length)];
}
},
pickMultipleRandom: function(possibles, number) {
if (arguments.length !== 2) {
throw new ArgumentsError('pickMultipleRandom', arguments.length, 2);
}
if (possibles && possibles.isMatrix === true) {
possibles = possibles.valueOf(); // get Array
}
else if (!Array.isArray(possibles)) {
throw new TypeError('Unsupported type of value in function pickMultipleRandom');
}
if (array.size(possibles).length > 1) {
throw new Error('Only one dimensional vectors supported');
}
var length = possibles.length;
if (length == 0) {
return [];
} else if (number >= length) {
return possibles;
}
var result = [];
var pick;
while (result.length < number) {
pick = possibles[Math.floor(Math.random() * length)];
if (result.indexOf(pick) == -1) {
result.push(pick);
}
}
return result;
}
};
var _random = function(min, max) {

View File

@ -7,6 +7,7 @@ module.exports = [
require('./multinomial'),
require('./permutations'),
require('./pickRandom'),
require('./pickMultipleRandom'),
require('./random'),
require('./randomInt')
];

View File

@ -0,0 +1,34 @@
'use strict';
function factory (type, config, load, typed) {
var distribution = load(require('./distribution'));
/**
* Random pick a specified number of values from a one dimensional array.
* Array elements are picked using a random function with uniform distribution.
*
* Syntax:
*
* math.pickMultipleRandom(array, int)
*
* Examples:
*
* math.pickMultipleRandom([3, 6, 12, 2], 2); // returns two of the values in the array
*
* See also:
*
* random, randomInt, pickRandom, pickMultipleRandom
*
* @param {Array} array A one dimensional array
* @param {number} num A one dimensional array
* @return {array} An array with n elements of the provided input array
*/
var pickMultipleRandom = distribution('uniform').pickMultipleRandom;
pickMultipleRandom.toTex = undefined; // use default template
return pickMultipleRandom;
}
exports.name = 'pickMultipleRandom';
exports.factory = factory;

View File

@ -25,7 +25,7 @@ function factory (type, config, load, typed) {
*
* See also:
*
* randomInt, pickRandom
* randomInt, pickRandom, pickMultipleRandom
*
* @param {Array | Matrix} [size] If provided, an array or matrix with given
* size and filled with random values is returned

View File

@ -23,7 +23,7 @@ function factory (type, config, load, typed) {
*
* See also:
*
* random, pickRandom
* random, pickRandom, pickMultipleRandom
*
* @param {Array | Matrix} [size] If provided, an array or matrix with given
* size and filled with random values is returned

View File

@ -282,6 +282,91 @@ describe('distribution', function () {
});
});
describe('pickMultipleRandom', function() {
it('should pick the given number of values from the given array', function() {
var possibles = [11, 22, 33, 44, 55],
number = 3,
picked = [];
assert.equal(uniformDistrib.pickMultipleRandom(possibles, number).length, number);
});
it('should return the given array if the given number is equal its length', function() {
var possibles = [11, 22, 33, 44, 55],
number = 5,
picked = [];
assert.equal(uniformDistrib.pickMultipleRandom(possibles, number), possibles);
});
it('should return the given array if the given number is greater than its length', function() {
var possibles = [11, 22, 33, 44, 55],
number = 6,
picked = [];
assert.equal(uniformDistrib.pickMultipleRandom(possibles, number), possibles);
});
it('should pick numbers from the given array following an uniform distribution', function() {
var possibles = [11, 22, 33, 44, 55],
number = 2,
picked = [],
count;
_.times(1000, function() {
picked.push(uniformDistrib.pickMultipleRandom(possibles, number));
});
count = _.filter(picked, function(val) { return val.indexOf(11) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(22) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(33) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(44) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(55) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
});
it('should pick numbers from the given matrix following an uniform distribution', function() {
var possibles = math.matrix([11, 22, 33, 44, 55]),
number = 3,
picked = [],
count;
_.times(1000, function() {
picked.push(uniformDistrib.pickMultipleRandom(possibles, number));
});
count = _.filter(picked, function(val) { return val.indexOf(11) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(22) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(33) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(44) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
count = _.filter(picked, function(val) { return val.indexOf(55) !== -1 }).length;
assert.equal(math.round(count/(picked.length*number), 1), 0.2);
});
it('should throw an error when providing a multi dimensional matrix', function() {
assert.throws(function () {
uniformDistrib.pickMultipleRandom(math.matrix([[1,2], [3,4]]), 2);
}, /Only one dimensional vectors supported/);
});
});
describe('distribution.normal', function() {
it('should pick numbers in [0, 1] following a normal distribution', function() {

View File

@ -0,0 +1,17 @@
var assert = require('assert'),
math = require('../../../index');
describe('pickMultipleRandom', function () {
// Note: pickMultipleRandom is a convenience function generated by distribution
// it is tested in distribution.test.js
it('should have a function pickMultipleRandom', function () {
assert.equal(typeof math.pickMultipleRandom, 'function');
})
it('should LaTeX pickMultipleRandom', function () {
var expression = math.parse('pickMultipleRandom([1,2,3], 2)');
assert.equal(expression.toTex(), '\\mathrm{pickMultipleRandom}\\left(\\begin{bmatrix}1\\\\2\\\\3\\\\\\end{bmatrix},2\\right)');
});
});