Source code for mmm_framework.mmm_extensions.builders_base

"""
Base classes and utilities for extension builders.

This module provides shared functionality for extension builders that
operate on extension-specific config classes (frozen dataclasses).

Note: The extension builders use different config classes than the base
builders (frozen dataclasses vs Pydantic models), so they cannot directly
inherit. This module provides common patterns and utilities.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, TypeVar, runtime_checkable

if TYPE_CHECKING:
    from typing import Self

T = TypeVar("T")


[docs] @runtime_checkable class ExtensionBuilderProtocol(Protocol[T]): """Protocol for extension configuration builders. All extension builders should implement a build() method that returns the final configuration object. """
[docs] def build(self) -> T: """Build and return the configuration object.""" ...
[docs] class AdstockBuilderMixin: """ Mixin providing common adstock configuration methods. This mixin provides shared convenience methods for configuring adstock parameters. It can be used by any builder that configures adstock. Attributes ---------- _l_max : int Maximum lag for adstock transformation. _prior_alpha : float Alpha parameter for Beta prior on decay rate. _prior_beta : float Beta parameter for Beta prior on decay rate. _normalize : bool Whether to normalize adstock weights. """ _l_max: int _prior_alpha: float _prior_beta: float _normalize: bool def _init_adstock_fields( self, l_max: int = 8, prior_alpha: float = 2.0, prior_beta: float = 2.0, normalize: bool = True, ) -> None: """Initialize adstock fields with defaults.""" self._l_max = l_max self._prior_alpha = prior_alpha self._prior_beta = prior_beta self._normalize = normalize
[docs] def with_max_lag(self, l_max: int) -> Self: """Set maximum lag length. Parameters ---------- l_max : int Maximum number of periods for carryover effects. Returns ------- Self Builder instance for method chaining. """ self._l_max = l_max return self
[docs] def with_slow_decay(self) -> Self: """Configure for slow decay (long memory). Sets Beta(3, 1) prior which favors higher decay rates, meaning effects persist longer. Returns ------- Self Builder instance for method chaining. """ self._prior_alpha = 3.0 self._prior_beta = 1.0 return self
[docs] def with_fast_decay(self) -> Self: """Configure for fast decay (short memory). Sets Beta(1, 3) prior which favors lower decay rates, meaning effects dissipate quickly. Returns ------- Self Builder instance for method chaining. """ self._prior_alpha = 1.0 self._prior_beta = 3.0 return self
[docs] def without_normalization(self) -> Self: """Disable weight normalization. Returns ------- Self Builder instance for method chaining. """ self._normalize = False return self
[docs] class SaturationBuilderMixin: """ Mixin providing common saturation configuration methods. This mixin provides shared convenience methods for configuring saturation parameters. It can be used by any builder that configures saturation. Attributes ---------- _lam_alpha : float Alpha parameter for lambda prior (logistic saturation). _lam_beta : float Beta parameter for lambda prior. _kappa_alpha : float Alpha parameter for kappa prior (Hill saturation). _kappa_beta : float Beta parameter for kappa prior. _slope_alpha : float Alpha parameter for slope prior (Hill saturation). _slope_beta : float Beta parameter for slope prior. """ _lam_alpha: float _lam_beta: float _kappa_alpha: float _kappa_beta: float _slope_alpha: float _slope_beta: float def _init_saturation_fields( self, lam_alpha: float = 3.0, lam_beta: float = 1.0, kappa_alpha: float = 2.0, kappa_beta: float = 2.0, slope_alpha: float = 3.0, slope_beta: float = 1.0, ) -> None: """Initialize saturation fields with defaults.""" self._lam_alpha = lam_alpha self._lam_beta = lam_beta self._kappa_alpha = kappa_alpha self._kappa_beta = kappa_beta self._slope_alpha = slope_alpha self._slope_beta = slope_beta
[docs] def with_strong_saturation(self) -> Self: """Configure for strong diminishing returns. Returns ------- Self Builder instance for method chaining. """ self._lam_alpha = 5.0 self._lam_beta = 1.0 return self
[docs] def with_weak_saturation(self) -> Self: """Configure for weak diminishing returns. Returns ------- Self Builder instance for method chaining. """ self._lam_alpha = 1.0 self._lam_beta = 2.0 return self
[docs] class EffectPriorMixin: """ Mixin for configuring effect prior parameters. This mixin provides shared methods for configuring effect priors (constraint type and scale). """ def _tight_prior(self, sigma: float) -> float: """Return tightened prior scale.""" return sigma * 0.5 def _wide_prior(self, sigma: float) -> float: """Return widened prior scale.""" return sigma * 2.0
__all__ = [ "ExtensionBuilderProtocol", "AdstockBuilderMixin", "SaturationBuilderMixin", "EffectPriorMixin", ]