Source code for alts.core.evaluator

#Version 1.1.1 conform as of 01.04.2025
"""
| *alts.core.evaluator*
| :doc:`Built-In Implementations </modules/evaluator>`
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING

import os

if TYPE_CHECKING:
    from typing import Callable, Optional
    from alts.core.experiment import Experiment

from alts.core.configuration import Configurable, post_init



[docs] class Evaluator(Configurable): """ Evaluator() | **Description** | The Evaluator evaluates the results of an experiment. An evaluation can take any shape and may wrap any function of the experiment. """ experiment: Experiment = post_init()
[docs] def register(self, experiment: Experiment): """ register(self, experiment) -> None | **Description** | Registers a new experiment as the one to be evaluated. :param experiment: The experiment to be evaluated :type experiment: Experiment """ self.experiment = experiment
[docs] @dataclass class LogingEvaluator(Evaluator): """ LogingEvaluator(experiment) | **Description** | Logs the evaluation of the experiment into a ```./eval/log``` folder. :param experiment: The experiment to be evaluated :type experiment: Experiment """ folder: str = "log" root_path: str = "./eval" path = "./eval" @property def iteration(self): """ iteration(self) -> int | **Description** | Returns the current iteration of the experiment. :return: Current iteration of the experiment :rtype: int """ return self.experiment.iteration
[docs] def register(self, experiment: Experiment): """ register(self, experiment) -> None | **Description** | Registers the experiment to be evaluated and creates the appropiate logging folders. :param experiment: The experiment to be evaluated :type experiment: Experiment """ super().register(experiment) self.path = self.root_path if self.experiment.exp_path is not None: self.path = os.path.join(self.experiment.exp_path, self.path) if self.experiment.exp_name is not None: self.path = os.path.join(self.path, self.experiment.exp_name) self.path = os.path.join(self.path, self.folder) self.path = os.path.join(self.path, f'exp_{self.experiment.exp_nr}') os.makedirs(self.path, exist_ok=True)
import functools
[docs] class Evaluate(): """ Evaluate(func) | **Description** | Evaluate is a modifiable function decorator/wrapper . You may set a function that runs beforehand, afterwards, or receives the original function as an argument. | Call the currently wrapped function with Evaluate(). :param func: Function to be wrapped :type func: function """ def __init__(self, func): """ __init__(self, func) -> None | **Description** | Sets ```func``` as its original function and initiates the ```pre```, ```wrap```, and ```post``` functions to do nothing (i.e. calling ```Evaluate(*args, **kwargs)``` now would yield ```original_func(*args, **kwargs)```). :param func: Function to be wrapped :type func: function """ functools.update_wrapper(self, func) self._original_func = func self._pre_func: Optional[Callable] = None self._wrap_func: Optional[Callable] = None self._post_func: Optional[Callable] = None def __call__(self, *args, **kwargs): """ __call__(self, *args, **kwargs) | **Description** | Calls the wrapped function with the given arguments. | Running order: pre(*args, **kwargs), wrap(original_func, *args, **kwargs), post(*args, **kwargs) :return: The result of wrap(original_func, *args, **kwargs) :rtype: any """ if not self._pre_func is None: self._pre_func(*args, **kwargs) if not self._wrap_func is None: result = self._wrap_func(self._original_func, *args, **kwargs) else: result = self._original_func(*args, **kwargs) if not self._post_func is None: self._post_func(result) return result
[docs] def pre(self, func): """ pre(self, func) -> None | **Description** | Sets the function to run before the wrapped function. :param func: Function to run before the wrapped function :type func: function """ self._pre_func = func
[docs] def warp(self, func): """ wrap(self, func) -> None | **Description** | Sets the function to wrap the original function (takes the original function as an argument). :param func: Function to wrap the original function :type func: function """ self._warp_func = func
[docs] def post(self, func): """ pre(self, func) -> None | **Description** | Sets the function to run after the wrapped function. :param func: Function to run after the wrapped function :type func: function """ self._post_func = func