Source code for evolib.utils.history_logger

# SPDX-License-Identifier: MIT
from typing import Any, Dict, List

import pandas as pd


[docs] class HistoryLogger: """ A flexible logger for recording per-generation statistics during evolutionary runs. Automatically handles dynamic columns to support polymorphic ParaBase.get_history(). """ def __init__(self, columns: list[str] | None = None): """ Args: columns (list[str] | None): Optional initial list of expected columns. Will be extended automatically if needed. """ self.columns = columns if columns is not None else [] self.history = pd.DataFrame(columns=self.columns)
[docs] def log(self, data: dict) -> None: """ Logs a new row of generation data, automatically adding new columns if needed. Args: data (dict): Dictionary of values to log for the current generation. """ new_keys = [k for k in data if k not in self.history.columns] if new_keys: for key in new_keys: self.history[key] = pd.NA self.columns.append(key) row = pd.Series(data) self.history.loc[len(self.history)] = row
[docs] def to_dataframe(self) -> pd.DataFrame: """Returns the full history as a pandas DataFrame.""" df = self.history.copy() for col in df.columns: try: df[col] = pd.to_numeric(df[col]) except (ValueError, TypeError): pass # leave non-numeric columns untouched return df
[docs] def to_dicts(self) -> List[Dict[str, Any]]: """Returns the full history as a list of dictionaries.""" return self.to_dataframe().to_dict(orient="records")
[docs] def save_csv(self, path: str) -> None: """ Saves the current history to a CSV file. Args: path (str): File path to save the history. """ self.history.to_csv(path, index=False)
[docs] def reset(self) -> None: """Clears the entire logged history.""" self.history = pd.DataFrame(columns=self.columns)