Skip to main content

PyMAB

PyMAB is a small Python library for reproducible multi-armed bandit experiments. It separates environments, policies, simulations, metrics, and plotting so experiments are easier to test, compare, and extend.

What changed in v1

  • Python 3.11+ and a clean typed API.
  • Explicit random seeds through numpy.random.Generator.
  • Environments own true arm values and reward sampling.
  • Policies only select actions and update from observed rewards.
  • Regret is computed from expected rewards, with realized rewards kept separate.
  • Plotting dependencies are optional via pymab[plot].
  • Pandas analysis helpers are optional via pymab[analysis].
  • Benchmarks can compare policies across repeated seeds with confidence intervals.

Install

pip install pymab

For local development:

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,plot]"
python -m unittest discover -v

With uv, use the Makefile targets used by CI:

make sync
make format
make lint
make security
make test

make format checks formatting. Use make format-fix to rewrite formatting locally.

The Makefile tries uv run ... first. If your local uv binary fails before it can run a tool, the targets fall back to executables installed in .venv; run make sync once to create/populate that environment.

Basic Example

import numpy as np

from pymab.environments import BanditEnvironment
from pymab.policies import EpsilonGreedyPolicy, UCBPolicy
from pymab.simulation import Experiment, ExperimentConfig

environment = BanditEnvironment(q_values=np.array([0.1, 0.4, 0.8]))
policies = [
    EpsilonGreedyPolicy(n_arms=3, epsilon=0.1),
    UCBPolicy(n_arms=3, c=2.0),
]

result = Experiment(
    environment=environment,
    policies=policies,
    config=ExperimentConfig(n_episodes=200, n_steps=500, seed=42),
).run()

print(result.average_reward_by_step[-1])
print(result.cumulative_regret[-1])

Compare Policies

import numpy as np

from pymab import compare
from pymab.environments import BanditEnvironment
from pymab.policies import RandomPolicy, ThompsonSamplingPolicy, UCBPolicy

benchmark = compare(
    [
        RandomPolicy(n_arms=3),
        UCBPolicy(n_arms=3),
        ThompsonSamplingPolicy(n_arms=3),
    ],
    environment=BanditEnvironment(q_values=np.array([0.1, 0.3, 0.8])),
    n_episodes=100,
    n_steps=500,
    seeds=(1, 2, 3, 4, 5),
)

print(benchmark.best_policy)
print(benchmark.summary())

Install pymab[analysis] to convert results into pandas DataFrames:

result_frame = benchmark.combined.to_pandas()
summary_frame = benchmark.to_pandas()

Persist reproducible result arrays with:

benchmark.combined.save_npz("results/benchmark.npz")

Non-Stationary Environments

import numpy as np

from pymab.environments import BanditEnvironment, GradualDrift

environment = BanditEnvironment(
    q_values=np.array([0.2, 0.5, 0.7]),
    dynamics=GradualDrift(change_rate=0.01),
)

Built-in dynamics:

  • StationaryDynamics
  • GradualDrift
  • AbruptShift
  • RandomArmSwap

Policies

Classic bandits:

  • GreedyPolicy
  • RandomPolicy
  • EpsilonGreedyPolicy
  • DecayingEpsilonGreedyPolicy
  • SoftmaxPolicy
  • GradientBanditPolicy
  • UCBPolicy
  • KLUCBPolicy
  • MOSSPolicy
  • SlidingWindowUCBPolicy
  • DiscountedUCBPolicy
  • CUSUMUCBPolicy
  • PageHinkleyUCBPolicy
  • BernoulliThompsonSamplingPolicy
  • GaussianThompsonSamplingPolicy
  • SlidingWindowBernoulliThompsonSamplingPolicy
  • DiscountedBernoulliThompsonSamplingPolicy
  • BernoulliBayesianUCBPolicy
  • GaussianBayesianUCBPolicy
  • EXP3Policy
  • SuccessiveEliminationPolicy
  • MedianEliminationPolicy

Contextual bandits:

  • LinearEpsilonGreedyPolicy
  • LinUCBPolicy
  • LinearThompsonSamplingPolicy
  • LogisticContextualBanditPolicy

Contextual Example

import numpy as np

from pymab.environments import LinearContextualEnvironment
from pymab.policies import LinUCBPolicy
from pymab.simulation import Experiment, ExperimentConfig


def context_provider(rng: np.random.Generator) -> np.ndarray:
    return np.array([[1.0, 0.0], [0.0, 1.0]])


environment = LinearContextualEnvironment(
    theta=np.array([[1.0, 0.0], [0.0, 1.0]]),
    context_provider=context_provider,
)

result = Experiment(
    environment=environment,
    policies=[LinUCBPolicy(n_arms=2, n_features=2)],
    config=ExperimentConfig(n_episodes=100, n_steps=200, seed=7),
).run()

Plotting

from pathlib import Path

from pymab.plotting import plot_average_reward, plot_cumulative_regret

plot_average_reward(result, output_path=Path("results/average_reward.html"))
plot_cumulative_regret(result, output_path=Path("results/regret.html"))

Install plotting extras first:

pip install "pymab[plot]"

Migration Notes

The old Game API remains as a deprecated compatibility wrapper. New code should use BanditEnvironment, ExperimentConfig, and Experiment directly. The old pymab.reward_distribution import path also remains available, but the new module is pymab.distributions.

Metadata

Release files for pymab 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pymab 1.0.0
File Size Uploaded Provenance Actions
pymab-1.0.0.tar.gz 37.6 kB With provenance Details for pymab-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pymab 1.0.0
File Interpreter ABI Platform Actions
pymab-1.0.0-py3-none-any.whl Python 3 none any Details for pymab-1.0.0-py3-none-any.whl

Total release size: 76.8 kB

Release files / pymab-1.0.0.tar.gz

Download URL pymab-1.0.0.tar.gz
Size 37.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e5065bafb6758044d6c1c4c9db14ee29935b7df4c079f016f61ed17530a59069
BLAKE2b-256 checksum
How to use checksums
bbb4e3133025fd92cc2b7fb6cd8e1a0236c73bebc847ce0565763f63887be46f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

Release files / pymab-1.0.0-py3-none-any.whl

Download URL pymab-1.0.0-py3-none-any.whl
Size 39.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a3589b83bd66d9f9dd774f24a925919890359f075c1169158b0fbe59d2d239d
BLAKE2b-256 checksum
How to use checksums
6fbba021571aec4b1e759cd3e82f2190919f1de8e31c57b10d5098a952b9d059
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

Security for pymab 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pymab-1.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page