Source code for alts.core.experiment_runner
#Version 1.1.1 conform as of 15.12.2024
"""
| *alts.core.experiment_runner*
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from multiprocessing import Pool
import os
from alts.core.evaluator import Evaluator
from alts.core.experiment import Experiment
if TYPE_CHECKING:
from typing import Tuple, Union, Iterable, List
from alts.core.blueprint import Blueprint
[docs]
class ExperimentRunner():
"""
ExperimentRunner(blueprints)
| **Description**
| Runs experiments as described by blueprints.
:param blueprints: Blueprints describing experiments to run
:type blueprints: Iterable[Blueprint]
"""
def __init__(self, blueprints: Iterable[Blueprint]) -> None:
"""
__init__(self, blueprints) -> None
| **Description**
| Saves ``blueprints`` locally and initializes empty lists.
:param blueprints: The blueprints for the experiments
:type blueprints: Iterable[Blueprint]
"""
self.evaluators: List[Evaluator] = []
self.blueprints = blueprints
[docs]
def run_experiment(self, blueprint: Blueprint):
"""
run_experiment(blueprint) -> None
| **Description**
| Runs the experiment based on ``blueprint`` on a single core.
:param blueprint: The blueprint for the experiment
:type blueprint: Blueprint
"""
self.evaluators = []
for evaluator in blueprint.evaluators:
self.evaluators.append(evaluator())
for exp_nr in range(blueprint.repeat):
experiment = Experiment(blueprint, exp_nr)
self.register_evaluators(experiment)
print("Running:", experiment.exp_name, exp_nr)
experiment.run()
[docs]
def run_repetition(self, exp_config: Tuple[Blueprint, int]):
"""
run_repetition(self, exp_config) -> None
| **Description**
| Runs the configured experiment once with the given ``exp_nr``,
ignoring the configured amount of repetitions.
:param exp_config: A blueprint and a given experiment number
:type exp_config: Tuple[Blueprint, int]
"""
blueprint, exp_nr = exp_config
evaluators: List[Evaluator] = []
for evaluator in blueprint.evaluators:
evaluators.append(evaluator())
experiment = Experiment(blueprint, exp_nr)
for evaluator in evaluators:
evaluator.register(experiment)
print("Running:", experiment.exp_name, exp_nr)
experiment.run()
[docs]
def run_experiment_parallel(self, blueprint: Blueprint, nr_processes: int = int(os.cpu_count() / 2)): # type: ignore
"""
run_experiment_parallel(self, blueprint, nr_processes) -> None
| **Description**
| Runs a single experiment on multiple cores.
:param blueprint: The blueprint for the experiment
:type blueprint: Blueprint
:param nr_processes: How many processes to run in parallel (default= 1/2 CPU count)
:type nr_processes: int
"""
exp_configs = []
for exp_nr in range(blueprint.repeat):
exp_configs.append((blueprint,exp_nr))
with Pool(nr_processes) as p:
p.map(self.run_repetition, exp_configs)
[docs]
def run_experiments(self, blueprints: Union[Iterable[Blueprint], None] = None):
"""
run_experiments(self, blueprints) -> None
| **Description**
| Runs multiple experiments on asingle core.
:param blueprints: Blueprints for experiments (default= None)
:type blueprints: Iterable[Blueprint]
"""
if blueprints is None: blueprints = self.blueprints
for blueprint in blueprints:
self.run_experiment(blueprint)
[docs]
def run_experiments_parallel(self, blueprints: Union[Iterable[Blueprint], None] = None, nr_processes: int = int(os.cpu_count() / 2), parallel_sub_exp=True): # type: ignore
"""
run_experiments_parallel(self, blueprint, nr_processes) -> None
| **Description**
| Runs a multiple experiments. Runs either each experiment on multiple cores
or one experiment per core.
:param blueprint: The blueprints for the experiments (default= None)
:type blueprint: Iterbale[Blueprint]
:param nr_processes: How many processes to run in parallel (default= 1/2 CPU count)
:type nr_processes: int
:param parallel_sub_exp: Whether to run a single experiment in parallel (or multiple experiments in parallel) (default= True)
:type parallel_sub_exp: bool
"""
if blueprints is None: blueprints = self.blueprints
if parallel_sub_exp:
for blueprint in blueprints:
self.run_experiment_parallel(blueprint)
else:
with Pool(nr_processes) as p:
p.map(self.run_experiment, blueprints)
[docs]
def register_evaluators(self, experiment):
"""
register_evaluators(self,experiment) -> None
| **Description**
| Registers the experiment in all own evaluators.
:param experiment: Experiment to be registered
:type experiment: Experiment
"""
for evaluator in self.evaluators:
evaluator.register(experiment)