Skip to content

simulation

Provides Simulation class for bandit simulations.

Simulation(bandit, agents=None, strategies=None, names=None, rng=None, seed=None)

Simulation of a multi-armed bandit problem.

A simulation consists of multiple trials of one or more bandit strategies run on a configured multi-armed bandit.

One of agents or strategies must be supplied. If agents is supplied, strategies and names are ignored. Otherwise, an agent is created for each strategy and given a name from names if available.

Parameters:

Name Type Description Default
bandit Bandit

A configured multi-armed bandit to simulate on.

required
agents Iterable[Agent] | None

A list of agents to simulate.

None
strategies Iterable[Strategy] | None

A list of strategies to simulate.

None
names Iterable[str] | None

A list of names for agents.

None
rng Generator | None

A random number generator.

None
seed int | None

A seed for random number generation if rng is not provided.

None

Raises:

Type Description
SimulationUsageError

If neither agents nor strategies are supplied.

Source code in mabby/simulation.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def __init__(
    self,
    bandit: Bandit,
    agents: Iterable[Agent] | None = None,
    strategies: Iterable[Strategy] | None = None,
    names: Iterable[str] | None = None,
    rng: Generator | None = None,
    seed: int | None = None,
):
    """Initializes a simulation.

    One of ``agents`` or ``strategies`` must be supplied. If ``agents`` is supplied,
    ``strategies`` and ``names`` are ignored. Otherwise, an ``agent`` is created for
    each ``strategy`` and given a name from ``names`` if available.

    Args:
        bandit: A configured multi-armed bandit to simulate on.
        agents: A list of agents to simulate.
        strategies: A list of strategies to simulate.
        names: A list of names for agents.
        rng: A random number generator.
        seed: A seed for random number generation if ``rng`` is not provided.

    Raises:
        SimulationUsageError: If neither ``agents`` nor ``strategies`` are supplied.
    """
    self.agents = self._create_agents(agents, strategies, names)
    if len(list(self.agents)) == 0:
        raise ValueError("no strategies or agents were supplied")
    self.bandit = bandit
    if len(self.bandit) == 0:
        raise ValueError("bandit cannot be empty")
    self._rng = rng if rng else np.random.default_rng(seed)

run(trials, steps, metrics=None)

Runs a simulation.

In a simulation run, each agent or strategy is run for the specified number of trials, and each trial is run for the given number of steps.

If metrics is not specified, all available metrics are tracked by default.

Parameters:

Name Type Description Default
trials int

The number of trials in the simulation.

required
steps int

The number of steps in a trial.

required
metrics Iterable[Metric] | None

A list of metrics to collect.

None

Returns:

Type Description
SimulationStats

A SimulationStats object with the results of the simulation.

Source code in mabby/simulation.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def run(
    self, trials: int, steps: int, metrics: Iterable[Metric] | None = None
) -> SimulationStats:
    """Runs a simulation.

    In a simulation run, each agent or strategy is run for the specified number of
    trials, and each trial is run for the given number of steps.

    If ``metrics`` is not specified, all available metrics are tracked by default.

    Args:
        trials: The number of trials in the simulation.
        steps: The number of steps in a trial.
        metrics: A list of metrics to collect.

    Returns:
        A ``SimulationStats`` object with the results of the simulation.
    """
    sim_stats = SimulationStats(simulation=self)
    for agent in self.agents:
        agent_stats = self._run_trials_for_agent(agent, trials, steps, metrics)
        sim_stats.add(agent_stats)
    return sim_stats