Source code for vbi.models.cpp.base

"""
Base class for VBI models providing a unified interface for parameter management.
"""
from abc import ABC, abstractmethod
from typing import Dict, List, Any


[docs] class BaseModel(ABC): """ Abstract base class for all VBI models. This class provides a unified interface for model parameter management, ensuring consistency across different model implementations. Attributes ---------- _par : dict Internal dictionary storing all model parameters. valid_params : list List of valid parameter names for this model. """
[docs] def __init__(self): """Initialize the base model.""" self._par = {} self.valid_params = []
[docs] @abstractmethod def get_default_parameters(self) -> Dict[str, Any]: """ Get the default parameters for the model. Returns ------- dict Dictionary containing default parameter values. """ pass
[docs] @abstractmethod def get_parameter_descriptions(self) -> Dict[str, str]: """ Get descriptions for all model parameters. Returns ------- dict Dictionary mapping parameter names to their descriptions. """ pass
[docs] def check_parameters(self, par: Dict[str, Any]) -> None: """ Validate that all provided parameters are valid for this model. Parameters ---------- par : dict Dictionary of parameters to validate. Raises ------ ValueError If any parameter name is not in the valid_params list. """ for key in par.keys(): if key not in self.valid_params: raise ValueError(f"Invalid parameter: {key}")
[docs] def get_parameters(self) -> Dict[str, Any]: """ Get all model parameters as a dictionary. Returns ------- dict Dictionary containing all current model parameters. Examples -------- >>> model = VEP_sde() >>> params = model.get_parameters() >>> print(params['G']) 1.0 """ return self._par.copy()
[docs] def set_parameters(self, par: Dict[str, Any]) -> None: """ Update model parameters. Parameters ---------- par : dict Dictionary of parameters to update. Only valid parameters will be updated. Raises ------ ValueError If any parameter name is invalid. Examples -------- >>> model = VEP_sde() >>> model.set_parameters({'G': 2.0, 'tau': 15.0}) """ self.check_parameters(par) self._par.update(par) # Update attributes for name, value in par.items(): setattr(self, name, value)
[docs] def get_parameter(self, name: str) -> Any: """ Get the value of a specific parameter. Parameters ---------- name : str Name of the parameter to retrieve. Returns ------- Any Value of the requested parameter. Raises ------ KeyError If parameter name does not exist. Examples -------- >>> model = VEP_sde() >>> g_value = model.get_parameter('G') >>> print(g_value) 1.0 """ if name not in self._par: raise KeyError(f"Parameter '{name}' not found in model.") return self._par[name]
[docs] def list_parameters(self) -> List[str]: """ Get a list of all valid parameter names for this model. Returns ------- list List of valid parameter names. Examples -------- >>> model = VEP_sde() >>> params = model.list_parameters() >>> print('G' in params) True """ return list(self.valid_params)
[docs] @abstractmethod def run(self, par: Dict[str, Any] = {}, **kwargs) -> Dict[str, Any]: """ Run the model simulation. Parameters ---------- par : dict, optional Dictionary of parameters to update before running. **kwargs Additional keyword arguments specific to the model. Returns ------- dict Dictionary containing simulation results (typically 't' for time and state variables). """ pass
def __call__(self) -> Dict[str, Any]: """ Return model parameters when instance is called. Returns ------- dict Dictionary of all model parameters. """ return self._par def _format_value(self, value): """Format a parameter value for display""" if hasattr(value, 'shape') and value is not None: # Array-like object try: shape_tuple = tuple(value.shape) if len(shape_tuple) == 0: # 0-d array (scalar stored as array) return f"{value}" else: return f"shape {shape_tuple}" except: return str(type(value).__name__) elif isinstance(value, (list, tuple)) and len(value) > 0: # List/tuple if len(value) <= 3: return f"{value}" else: return f"[{len(value)} items]" elif isinstance(value, dict): return f"dict({len(value)})" else: # Scalar or other type return f"{value}" def _format_parameters_table(self) -> str: """ Format model parameters as a table with names, descriptions, values, and types. Returns ------- str Formatted table string with 4 columns: - Parameter: parameter name - Description: what the parameter does - Value: current value or shape - Type: scalar | vector | matrix | string | bool | - """ param_info = self.get_parameter_descriptions() lines = [ "=" * 110, f"{self.__class__.__name__}", "=" * 110, "", "Model Parameters:", "-" * 110, f"{'Parameter':<15} | {'Description':<40} | {'Value/Shape':<30} | {'Type':<15}", "-" * 110, ] for name in sorted(self.valid_params): if name in self._par: # Get current value (may have been converted) try: current_value = getattr(self, name) except AttributeError: current_value = self._par[name] # Get description and type from param_info if isinstance(param_info.get(name), tuple): description, param_type = param_info[name] else: description = param_info.get(name, "No description") param_type = "-" # Format current value for display current_str = self._format_value(current_value) lines.append(f"{name:<15} | {description:<40} | {current_str:<30} | {param_type:<15}") lines.append("=" * 110) return "\n".join(lines) def __str__(self) -> str: """ Return string representation of the model with parameter table. Returns ------- str Formatted string with model information and parameters table. """ return self._format_parameters_table()