think-bayes
Version:
An algorithm framework of probability and statistics for browser and Node.js environment.
500 lines (406 loc) • 15.5 kB
JavaScript
"use strict";
require("core-js/modules/es.symbol");
require("core-js/modules/es.symbol.description");
require("core-js/modules/es.symbol.iterator");
require("core-js/modules/es.array.concat");
require("core-js/modules/es.array.fill");
require("core-js/modules/es.array.iterator");
require("core-js/modules/es.array.map");
require("core-js/modules/es.array.reduce");
require("core-js/modules/es.object.to-string");
require("core-js/modules/es.regexp.to-string");
require("core-js/modules/es.string.iterator");
require("core-js/modules/es.string.sub");
require("core-js/modules/web.dom-collections.iterator");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.evalPoissonPmf = exports.evalBinomialPmf = exports.makeGaussianPdf = exports.evalGaussianPdf = exports.sampleSum = exports.randomSum = exports.pmfProbEqual = exports.pmfProbGreater = exports.pmfProbLess = exports.credibleInterval = exports.percentile = exports.probability2 = exports.probability = exports.odds = void 0;
var _utils = require("./utils");
var _math = _interopRequireDefault(require("./math"));
var _convertors = require("./convertors");
var _Pmf = _interopRequireDefault(require("./Pmf"));
var _num = require("./algorithm/num");
var _normal = require("./algorithm/normal");
var _binomial = require("./algorithm/binomial");
var _poisson = require("./algorithm/poisson");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
/**
* Computes odds for a given probability.
* **Example:** p=0.75 means 75 for and 25 against, or 3:1 odds in favor.
* **Note:** when p=1, the formula for odds divides by zero, which is
* normally undefined. But I think it is reasonable to define Odds(1)
* to be infinity, so that's what this function does.
* @param {number} p float 0~1
* @returns float odds
*/
var odds = function odds(p) {
if (!p || p < 0 || p > 1) throw new RangeError('Value of the probability must be a number greater than 0 and less than 1.');
return p === 1 ? Infinity : _math.default.div(p, _math.default.sub(1, p));
};
/**
* Computes the probability corresponding to given odds.
* **Example:** o=2 means 2:1 odds in favor, or 2/3 probability
* @param {number} o float odds, strictly positive
* @returns float probability
*/
exports.odds = odds;
var probability = function probability(o) {
if (!o || o < 0) throw new RangeError('Value of the odds must be a positive number.');
return _math.default.div(o, _math.default.add(o, 1));
};
/**
* Computes the probability corresponding to given odds.
* **Example:** yes=2, no=1 means 2:1 odds in favor, or 2/3 probability.
* @param {number} yes int or float odds in favor
* @param {number} no int or float odds in favor
*/
exports.probability = probability;
var probability2 = function probability2(yes, no) {
if (!yes || yes < 0 || !no || no < 0) throw new RangeError('Value of the odds must be a positive number.');
return _math.default.div(yes, _math.default.add(yes, no));
};
/**
* Computes a percentile of a given Pmf.
* @param {pmf} pmf
* @param {number} percentage float 0-100
*/
exports.probability2 = probability2;
var percentile = function percentile(pmf, percentage) {
if (p < 0 || p > 100) throw new RangeError('Value of the probability must be a number greater than 0 and less than 1.');
var p = percentage / 100;
var total = 0;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = pmf.items()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _step$value = _slicedToArray(_step.value, 2),
val = _step$value[0],
prob = _step$value[1];
total = _math.default.add(total, prob);
if (total > p) return val;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
throw new _utils.ValueError("Value not found in pmf for percentage: `".concat(percentage, "`, which means the total probability of pmf is less than ").concat(percentage / 100, "."));
};
/**
* Computes a credible interval for a given distribution.
* If percentage=90, computes the 90% CI.
* @param {pmf} pmf Pmf object representing a posterior distribution
* @param {number} percentage float between 0 and 100
* @returns sequence of two floats, low and high
*/
exports.percentile = percentile;
var credibleInterval = function credibleInterval(pmf) {
var percentage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 90;
var cdf = pmf.makeCdf(); // prob = (1 - percentage / 100.0) / 2
var prob = _math.default.div(_math.default.sub(1, _math.default.div(percentage, 100)), 2);
var interval = [cdf.value(prob), cdf.value(_math.default.sub(1, prob))];
return interval;
};
/**
* Probability that a value from pmf1 is less than a value from pmf2.
* @param {pmf} pmf1 Pmf object
* @param {pmf} pmf2 Pmf object
* @returns float probability
*/
exports.credibleInterval = credibleInterval;
var pmfProbLess = function pmfProbLess(pmf1, pmf2) {
var total = 0;
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = pmf1.items()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _step2$value = _slicedToArray(_step2.value, 2),
v1 = _step2$value[0],
p1 = _step2$value[1];
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = pmf2.items()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var _step3$value = _slicedToArray(_step3.value, 2),
v2 = _step3$value[0],
p2 = _step3$value[1];
if (v1 < v2) total = _math.default.add(total, _math.default.mult(p1, p2));
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
return total;
};
/**
* Probability that a value from pmf1 is greater than a value from pmf2.
* @param {pmf} pmf1 Pmf object
* @param {pmf} pmf2 Pmf object
* @returns float probability
*/
exports.pmfProbLess = pmfProbLess;
var pmfProbGreater = function pmfProbGreater(pmf1, pmf2) {
var total = 0;
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = pmf1.items()[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var _step4$value = _slicedToArray(_step4.value, 2),
v1 = _step4$value[0],
p1 = _step4$value[1];
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = pmf2.items()[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var _step5$value = _slicedToArray(_step5.value, 2),
v2 = _step5$value[0],
p2 = _step5$value[1];
if (v1 > v2) total = _math.default.add(total, _math.default.mult(p1, p2));
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5.return != null) {
_iterator5.return();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
return total;
};
/**
* Probability that a value from pmf1 equals a value from pmf2.
* @param {pmf} pmf1 Pmf object
* @param {pmf} pmf2 Pmf object
* @returns float probability
*/
exports.pmfProbGreater = pmfProbGreater;
var pmfProbEqual = function pmfProbEqual(pmf1, pmf2) {
var total = 0;
var _iteratorNormalCompletion6 = true;
var _didIteratorError6 = false;
var _iteratorError6 = undefined;
try {
for (var _iterator6 = pmf1.items()[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
var _step6$value = _slicedToArray(_step6.value, 2),
v1 = _step6$value[0],
p1 = _step6$value[1];
var _iteratorNormalCompletion7 = true;
var _didIteratorError7 = false;
var _iteratorError7 = undefined;
try {
for (var _iterator7 = pmf2.items()[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
var _step7$value = _slicedToArray(_step7.value, 2),
v2 = _step7$value[0],
p2 = _step7$value[1];
if (v1 === v2) total = _math.default.add(total, _math.default.mult(p1, p2));
}
} catch (err) {
_didIteratorError7 = true;
_iteratorError7 = err;
} finally {
try {
if (!_iteratorNormalCompletion7 && _iterator7.return != null) {
_iterator7.return();
}
} finally {
if (_didIteratorError7) {
throw _iteratorError7;
}
}
}
}
} catch (err) {
_didIteratorError6 = true;
_iteratorError6 = err;
} finally {
try {
if (!_iteratorNormalCompletion6 && _iterator6.return != null) {
_iterator6.return();
}
} finally {
if (_didIteratorError6) {
throw _iteratorError6;
}
}
}
return total;
};
/**
* Chooses a random value from each dist and returns the sum.
* @param {array} dists sequence of Pmf or Cdf objects
* @returns numerical sum
*/
exports.pmfProbEqual = pmfProbEqual;
var randomSum = function randomSum(dists) {
var total = dists.reduce(function (prev, curr) {
return _math.default.add(prev, curr.random());
}, 0);
return total;
};
/**
* Draws a sample of sums from a list of distributions.
* @param {array} dists sequence of Pmf or Cdf objects
* @param {number} n sample size
* @returns new Pmf of sums
*/
exports.randomSum = randomSum;
var sampleSum = function sampleSum(dists, n) {
var list = new Array(n).fill(0).map(function () {
return randomSum(dists);
});
var pmf = (0, _convertors.makePmfFromList)(list);
return pmf;
};
/**
* Computes the unnormalized PDF of the normal distribution.
* @param {number} x value
* @param {number} mu mean
* @param {number} sigma standard deviation
* @returns float probability density
*/
exports.sampleSum = sampleSum;
var evalGaussianPdf = function evalGaussianPdf(x, mu, sigma) {
return (0, _normal.normalPdf)(x, mu, sigma);
};
/**
* Makes a PMF discrete approx to a Gaussian distribution.
* @param {number} mu float mean
* @param {number} sigma float standard deviation
* @param {number} numSigmas how many sigmas to extend in each direction
* @param {number} n number of values in the Pmf
* @returns normalized Pmf
*/
exports.evalGaussianPdf = evalGaussianPdf;
var makeGaussianPdf = function makeGaussianPdf(mu, sigma, numSigmas) {
var n = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 201;
var pmf = new _Pmf.default(); // low = mu - numSigmas * sigma;
var low = _math.default.sub(mu, _math.default.mult(numSigmas, sigma)); // high = mu + numSigmas * sigma;
var high = _math.default.add(mu, _math.default.mult(numSigmas, sigma));
var _iteratorNormalCompletion8 = true;
var _didIteratorError8 = false;
var _iteratorError8 = undefined;
try {
for (var _iterator8 = (0, _num.linspace)(low, high, n)[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
var x = _step8.value;
var p = evalGaussianPdf(x, mu, sigma);
pmf.set(x, p);
}
} catch (err) {
_didIteratorError8 = true;
_iteratorError8 = err;
} finally {
try {
if (!_iteratorNormalCompletion8 && _iterator8.return != null) {
_iterator8.return();
}
} finally {
if (_didIteratorError8) {
throw _iteratorError8;
}
}
}
pmf.normalize();
return pmf;
};
/**
* Evaluates the binomial pmf.
* @returns the probabily of k successes in n trials with probability p.
*/
exports.makeGaussianPdf = makeGaussianPdf;
var evalBinomialPmf = function evalBinomialPmf(k, n, p) {
return (0, _binomial.binomialPmf)(k, n, p);
};
/**
* Computes the Poisson PMF.
* @param {number} k number of events
* @param {number} lam parameter lambda in events per unit time
* @returns float probability
*/
exports.evalBinomialPmf = evalBinomialPmf;
var evalPoissonPmf = function evalPoissonPmf(k, lam) {
return (0, _poisson.poissonPmf)(k, lam);
};
exports.evalPoissonPmf = evalPoissonPmf;
var _default = {
odds: odds,
probability: probability,
probability2: probability2,
percentile: percentile,
credibleInterval: credibleInterval,
pmfProbLess: pmfProbLess,
pmfProbGreater: pmfProbGreater,
pmfProbEqual: pmfProbEqual,
randomSum: randomSum,
sampleSum: sampleSum,
evalGaussianPdf: evalGaussianPdf,
makeGaussianPdf: makeGaussianPdf,
evalBinomialPmf: evalBinomialPmf,
evalPoissonPmf: evalPoissonPmf
};
exports.default = _default;
//# sourceMappingURL=helpers.js.map