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)