npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

probility

v1.1.3

Published

Probility is an evolving library that aims to provide an easy-to-understand interface for creating probability distributions and generating data from those distributions.

Downloads

36

Readme

Probility

Probility is an evolving library that aims to provide an easy-to-understand interface for creating probability distributions and generating data from those distributions.

Probility provides both a class to interface with data collections and a set of functions to generate practical tests of outcomes and theoretical enumerations of expected outcomes for complex probability rules.

To see the current power of Probility, please check out the Examples Folder and run the sample code in Node. Example output is provided in the Markdown files, but running the code and looking at how the examples are constructed should give a much clearer picture of how everything works behind the scenes.

Why Probility?

My game-designer coworker trying to work out various combinations of die rolls using an Excel table initially inspired this project. I hope that, as it works now, Probility provides an easy way to interface with, describe, and explore probabilistic collections of data. In the future, I hope to make it even more robust by allowing developers to store and manipulate different states of a single Probility instance.

Usage

Probility can be installed from npm with the following command:

npm install probility

API Reference

class Probility(array, [options])

The main class for Probility collections. It takes an array and an optional options object during initialization.

It can be assigned directly:

const Probility = require('Probility')
const d6 = new Probility([1, 2, 3, 4, 5, 6])
d6.choose() // returns a random number from the array

Or as a parent class:


class SixSidedDie extends Probility {
    constructor() {
        super([1, 2, 3, 4, 5, 6])
    }

    roll() {
        return this.choose()
    }

...
}

Or as a dependency for an entirely new class.


class SixSidedDie {
    constructor(faces = [1, 2, 3, 4, 5, 6]) {
        this.prob = new Probility(faces) // Access all the Probility methods in the prob property
    }

    roll() {
        return this.prob.choose()
    }

...
}

In addition to passing an array with discrete objects, an alternative syntax exists to describe the ratios of the included choices:

class Urn extends Probility {
    constructor(stateDescription, options) {
        super(stateDescription, options)
    }

    pick() {
        return this.choose()
    }
}

// creating a new instance with an array describing the state:

const quarterUrn = new Urn([{"25%": "red ball"}, {"25%": "green ball"},
    {"1/4": "purple ball"},
    {"remainder": "black ball"}], {parseArray: true, total: 400})

// parseArray must be true. If not, we'd have a collection of four objects
// with equal probability to be chosen. Setting total to 400 here means that
// the pool will consist of 100 of each type of ball. Without setting the total,
// the pool would consist of one type of each ball.

array:

The array can either be a collection of discrete choices (like the sixSidedDie example), or a description of the probability state using ratios, percents, or the remainder identifier (like in the urn example) or whole numbers. Right now, whole numbers cannot be mixed with ratios or percents and cannot also have a remainder object in the same array. To describe the state in the second way, the parseArray option must be true when calling the constructor.

Probility will handle most types of objects as choices, including functions:

const loudCoin = new Probility([(str) => str.toUpperCase(), (str) => str.toLowerCase()]);
loudCoin.choose()("Hello") // HELLO
loudCoin.choose()("Hello") // hello

options:

Currently, there are three accepted options: parseArray: boolean, usePool: boolean and total: number. Setting parseArray to true will cause the Probility constructor to interpret the array as an array of objects describing the amount of a given choice. It is false by default, which will cause the constructor to read the array as a collection of discrete objects with equal probabilities.

usePool : false will skip the pool initialization and cause the chooseFomPool() method to return an error. Because of the different implementations of chooseWithSample() and chooseFromPool(), the best option will be based on each use case: In general, usePool: true is a better option for collections with many evenly -distributed choices, e.g. representing a deck of playing cards. usePool: false is a better option for collections with fewer and non-evenly-distributed choices, e.g. an urn with a two colors of balls with a constantly-changing ratio between them. The choose() method will detect which of the two choose implementations to use based on this option.

total can be set to a number representing the total number of options in a state description array (i.e., a parsed array). It will not override the totals if whole numbers are used; it is useful when describing a collection with ratios and percents that will later need choices added or removed. A high total will correlate to a large pool, so space concerns may factor into it's usefulness for your use case.

Probility.frequencyTest(callback, n)

Static. Calls the callback n times and returns a new Map of the results mapped to the number of times the result occurred out of n. The values of the Map are Rational Numbers, an included class:

const Probility = require('probility')

const d6 = new SixSidedDie();

Probility.frequencyTest(() => d6.roll(), 6000)

//  Map(6) {
//    6 => RationalNumber { numerator: 1019, denominator: 6000 },
//    1 => RationalNumber { numerator: 1012, denominator: 6000 },
//    5 => RationalNumber { numerator: 1040, denominator: 6000 },
//    3 => RationalNumber { numerator: 952, denominator: 6000 },
//    2 => RationalNumber { numerator: 1020, denominator: 6000 },
//    4 => RationalNumber { numerator: 957, denominator: 6000 }
// }

Probility.frequencyTest(() => {
    return d6.roll() % 2 === 0 ? "Even" : "Odd"
}, 6000)

// Map(2) {
//     'Odd' => RationalNumber { numerator: 2986, denominator: 6000 },
//     'Even' => RationalNumber { numerator: 3014, denominator: 6000 }
// }

Probility.frequencyEnumeration(array)

Static. Returns a mapping of all possible outcomes to their actual probability. It is meant to be used with Probility's . enumerate() method.

const
    Probility = require("Probility");

Probility.frequencyEnumeration(() => {
    return d6.enumerate((roll1) => {
        return d6.enumerate((roll2) => roll1 + roll2)
    })
});

// Map(11) {
//   2 => RationalNumber { numerator: 1, denominator: 36 },
//   3 => RationalNumber { numerator: 2, denominator: 36 },
//   4 => RationalNumber { numerator: 3, denominator: 36 },
//   5 => RationalNumber { numerator: 4, denominator: 36 },
//   6 => RationalNumber { numerator: 5, denominator: 36 },
//   7 => RationalNumber { numerator: 6, denominator: 36 },
//   8 => RationalNumber { numerator: 5, denominator: 36 },
//   9 => RationalNumber { numerator: 4, denominator: 36 },
//   10 => RationalNumber { numerator: 3, denominator: 36 },
//   11 => RationalNumber { numerator: 2, denominator: 36 },
//   12 => RationalNumber { numerator: 1, denominator: 36 }
// }

Probility.frequencyEnumeration(() => {
    return d6.enumerate((roll1) => {
        return d6.enumerate((roll2) => (roll1 + roll2) % 2 === 0 ? "Even" : "Odd")
    })
});

// Map(2) {
//     'Even' => RationalNumber { numerator: 18, denominator: 36 },
//     'Odd' => RationalNumber { numerator: 18, denominator: 36 }
// }

instance.numUniqueChoices

Returns the number of unique choices in a Probility instance.

const d6 = new Probility([1, 2, 3, 4, 5, 6]);
d6.numUniqueChoices // 6

instance.possibleChoices

Returns an array of the unique choices in a Probility instances.

const weightedD6 = new Probility([1, 2, 3, 4, 5, 6, 6, 6, 6, 6])
weightedD6.possibleChoices // [1,2,3,4,5,6]

instance.numTotalChoices

Returns the number of total choices.

const weightedD6 = new Probility([1, 2, 3, 4, 5, 6, 6, 6, 6, 6])
weightedD6.numTotalChoices // 10

instance.choose()

Returns a choice based on the probabilities of the choices in the collection. Will call chooseFromPool() or chooseFromSample() based on how the instance was created.

const weightedD6 = new Probility([1, 2, 3, 4, 5, 6, 6, 6, 6, 6])
const coin = new Probility([{"1/2": "heads"}, {"1/2": "tails"}], {parseArray: true, usePool: false});

coin.choose() // 'heads' -- calls chooseFromSample()
weightedD6.choose() // 6 -- calls chooseFromPool()

instance.initPool()

Initializes an instance's pool. Mostly used internally, but can be used to force a pool when an instance was not created with one.

const coin = new Probility([{"1/2": "heads"}, {"1/2": "tails"}], {parseArray: true, usePool: false});
coin.chooseFromPool(); // throws an error
coin.initPool();
coin.chooseFromPool() // "heads"

instance.add(choice, num)

Returns the Probility instance. Adds a number num of choice to the possible choices and reinitializes the pool, if using one.

const d6 = new Probility([1, 2, 3, 4, 5, 6])
d6.add(7, 1);
d6.possibleChoices // [1,2,3,4,5,6,7]

instance.addOne(choice)

Shorthand for instance.add(choice, 1).

instance.remove(predicateCallback, num)

Returns the Probility instance. iterates over the array and removes up to num choices that return true from predicateCallback(choice).

const smallDeck = new Probility(["1H", "6D", "JS", "KS"]);

// Removing a specific choice:

smallDeck.remove(card => card === "JS", 1);
smallDeck.possibleChoices // ["1H", "6D", "KS"]

// Removing non-specific items:

const slipsOfPaper = new Probility([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
slipsOfPaper.remove(paper => paper % 2 === 0, 3)
slipsOfPaper.possibleChoices // [1,3,5,7,8,9,10,11,12]

instance.listAllProbabilities()

Returns a Map of the probabilities of the unique choices.

const slipsOfPaper = new Probility([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
slipsOfPaper.listAllProbabilities()
// Map(12) {
//   1 => '1 / 12',
//   2 => '1 / 12',
//   3 => '1 / 12',
//   4 => '1 / 12',
//   5 => '1 / 12',
//   6 => '1 / 12',
//   7 => '1 / 12',
//   8 => '1 / 12',
//   9 => '1 / 12',
//   10 => '1 / 12',
//   11 => '1 / 12',
//   12 => '1 / 12'
}

instance.singleChoiceProbability(choice)

Returns a RationalNumber representing the probability of the given choice from the instance.

const weightedDie = new Probility([1, 2, 3, 4, 4, 4, 5, 6])
weightedDie.singleChoiceProbability(4).toString() // "3 / 8"

instance.probabilityOf(predicateCallback)

Returns a RationalNumber representing the probability that a choice will return true from predicateCallback (choice). In other words, the number of choices that return true over the total number of choices.

const slipsOfPaper = new Probility([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
slipsOfPaper.probabilityOf(paper => paper % 2 === 0).simplify().toString() // "1 / 2"

instance.getRandomChoice()

Returns a random choice from the collection of unique choices in the collection. With this method, all unique choices have an equal probability of being chosen.

const slipsOfPaper = new Probility([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
slipsOfPaper.getRandomChoice() // 10

instance.getRandomNumberFromTotal()

Returns a random number between 0 and the total number of all choices in a collection (exclusive).

const bigUrn = new Probility([{"50%": "White Ball"}, {"50%": "Black Ball"}], {parseArray; true, total: 4000})
bigUrn.getRandomNumberFromTotal() // 3320

instance.getRandomNumberFromUnique()

Returns a random number between 0 and the number of unique choices in a collection (exclusive).

const bigUrn = new Probility([{"50%": "White Ball"}, {"50%": "Black Ball"}], {parseArray; true, total: 4000})
bigUrn.getRandomNumberFromUnique() // 1

instance.enumerate(callback)

Returns an array of values returned from calling the callback with each value. Under the hood, this uses Array. flatMap, so they can be easily chained. (Though of course, enumerating can become resource-hungry quickly; it's essentially permuting all possible choices with each call to this method.)

const d6 = new Probility([1, 2, 3, 4, 5, 6]);
d6.enumerate(roll => {
    return roll
})
// [1,2,3,4,5,6]

d6.enumerate(roll1 => {
    return d6.enumerate(roll2 => {
        return roll1 + roll2
    })
})
//[2,  3,  4, 5, 6,  7,  3,  4, 5, 6,  7,  8, 4, 5,  6,  7,  8,  9,
// 5,  6,  7, 8, 9, 10,  6,  7, 8, 9, 10, 11, 7, 8,  9, 10, 11, 12 ]