Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ml-random

Package Overview
Dependencies
Maintainers
5
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ml-random - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

5

History.md

@@ -0,1 +1,6 @@

<a name="0.3.0"></a>
# [0.3.0](https://github.com/mljs/random/compare/v0.2.0...v0.3.0) (2018-05-23)
<a name="0.2.0"></a>

@@ -2,0 +7,0 @@ # [0.2.0](https://github.com/mljs/random/compare/v0.1.0...v0.2.0) (2018-05-16)

35

lib-es6/choice.js
function randomChoice(values, options = {}, random = Math.random) {
const { size = 1, replace = false } = options;
const { size = 1, replace = false, probabilities } = options;
let valuesArr;
let cumSum;
if (typeof values === 'number') {

@@ -10,2 +11,18 @@ valuesArr = getArray(values);

}
if (probabilities) {
if (!replace) {
throw new Error('choice with probabilities and no replacement is not implemented');
}
// check input is sane
if (probabilities.length !== valuesArr.length) {
throw new Error('the length of probabilities option should be equal to the number of choices');
}
cumSum = [probabilities[0]];
for (let i = 1; i < probabilities.length; i++) {
cumSum[i] = cumSum[i - 1] + probabilities[i];
}
if (Math.abs(1 - cumSum[cumSum.length - 1]) > Number.EPSILON) {
throw new Error('probabilities should sum to 1');
}
}
if (replace === false && size > valuesArr.length) {

@@ -16,3 +33,3 @@ throw new Error('size option is too large');

for (let i = 0; i < size; i++) {
const index = randomIndex(valuesArr.length, random);
const index = randomIndex(valuesArr.length, random, cumSum);
result.push(valuesArr[index]);

@@ -32,5 +49,15 @@ if (!replace) {

}
function randomIndex(n, random) {
return Math.floor(random() * n);
function randomIndex(n, random, cumSum) {
const rand = random();
if (!cumSum) {
return Math.floor(rand * n);
}
else {
let idx = 0;
while (rand > cumSum[idx]) {
idx++;
}
return idx;
}
}
export default randomChoice;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function randomChoice(values, options = {}, random = Math.random) {
const { size = 1, replace = false } = options;
const { size = 1, replace = false, probabilities } = options;
let valuesArr;
let cumSum;
if (typeof values === 'number') {

@@ -12,2 +13,18 @@ valuesArr = getArray(values);

}
if (probabilities) {
if (!replace) {
throw new Error('choice with probabilities and no replacement is not implemented');
}
// check input is sane
if (probabilities.length !== valuesArr.length) {
throw new Error('the length of probabilities option should be equal to the number of choices');
}
cumSum = [probabilities[0]];
for (let i = 1; i < probabilities.length; i++) {
cumSum[i] = cumSum[i - 1] + probabilities[i];
}
if (Math.abs(1 - cumSum[cumSum.length - 1]) > Number.EPSILON) {
throw new Error('probabilities should sum to 1');
}
}
if (replace === false && size > valuesArr.length) {

@@ -18,3 +35,3 @@ throw new Error('size option is too large');

for (let i = 0; i < size; i++) {
const index = randomIndex(valuesArr.length, random);
const index = randomIndex(valuesArr.length, random, cumSum);
result.push(valuesArr[index]);

@@ -34,5 +51,15 @@ if (!replace) {

}
function randomIndex(n, random) {
return Math.floor(random() * n);
function randomIndex(n, random, cumSum) {
const rand = random();
if (!cumSum) {
return Math.floor(rand * n);
}
else {
let idx = 0;
while (rand > cumSum[idx]) {
idx++;
}
return idx;
}
}
exports.default = randomChoice;

@@ -13,2 +13,6 @@ /**

replace?: boolean;
/**
* The probabilities associated with each element. Probabilities should sum to 1 and be the same length as the values. If not specified a uniform distribution is assumed.
*/
probabilities?: number[];
}

3

package.json
{
"name": "ml-random",
"version": "0.2.0",
"version": "0.3.0",
"description": "choose randomly from a selection of elements",

@@ -15,2 +15,3 @@ "main": "lib/index.js",

"test-only": "jest",
"test-coverage": "jest --coverage",
"tsc": "run-s clean tsc-es6 tsc-es5",

@@ -17,0 +18,0 @@ "tsc-es5": "tsc",

@@ -53,2 +53,36 @@ import * as XSAdd from 'ml-xsadd';

});
it('should produce choice given probabilities', () => {
const samples = 10000;
const r = random.choice(2, {
size: samples,
replace: true,
probabilities: [0.3, 0.7]
});
const count = r.reduce(
(prev, current) => (current === 0 ? prev + 1 : prev),
0
);
expect(count / samples).toBeCloseTo(0.3, 2);
});
it('should throw if probabilities option has the wrong size', () => {
expect(() => {
random.choice(3, { replace: true, probabilities: [0.5, 0.5] });
}).toThrow(
'the length of probabilities option should be equal to the number of choices'
);
});
it('should throw if probabilities option does not sum to 1', () => {
expect(() => {
random.choice(3, { replace: true, probabilities: [0.1, 0.5, 0.4001] });
}).toThrow('probabilities should sum to 1');
});
it('choice with probabilities and no replacement not implemented', () => {
expect(() => {
random.choice(3, { replace: false, probabilities: [0.1, 0.5, 0.4] });
}).toThrow(/not implemented/);
});
});

@@ -55,0 +89,0 @@

@@ -19,4 +19,6 @@ import { IChoiceOptions } from './Options';

): Array<T | number> {
const { size = 1, replace = false } = options;
const { size = 1, replace = false, probabilities } = options;
let valuesArr;
let cumSum;
if (typeof values === 'number') {

@@ -28,2 +30,24 @@ valuesArr = getArray(values);

if (probabilities) {
if (!replace) {
throw new Error(
'choice with probabilities and no replacement is not implemented'
);
}
// check input is sane
if (probabilities.length !== valuesArr.length) {
throw new Error(
'the length of probabilities option should be equal to the number of choices'
);
}
cumSum = [probabilities[0]];
for (let i = 1; i < probabilities.length; i++) {
cumSum[i] = cumSum[i - 1] + probabilities[i];
}
if (Math.abs(1 - cumSum[cumSum.length - 1]) > Number.EPSILON) {
throw new Error('probabilities should sum to 1');
}
}
if (replace === false && size > valuesArr.length) {

@@ -34,3 +58,3 @@ throw new Error('size option is too large');

for (let i = 0; i < size; i++) {
const index = randomIndex(valuesArr.length, random);
const index = randomIndex(valuesArr.length, random, cumSum);
result.push(valuesArr[index]);

@@ -52,6 +76,15 @@ if (!replace) {

function randomIndex(n: number, random: IRandomGenerator) {
return Math.floor(random() * n);
function randomIndex(n: number, random: IRandomGenerator, cumSum?: number[]) {
const rand = random();
if (!cumSum) {
return Math.floor(rand * n);
} else {
let idx = 0;
while (rand > cumSum[idx]) {
idx++;
}
return idx;
}
}
export default randomChoice;

@@ -13,2 +13,6 @@ /**

replace?: boolean;
/**
* The probabilities associated with each element. Probabilities should sum to 1 and be the same length as the values. If not specified a uniform distribution is assumed.
*/
probabilities?: number[];
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc