# hots/core/interfaces.py
"""HOTS core interfaces: plugin base classes."""
from abc import ABC, abstractmethod
from typing import Any
import pandas as pd
[docs]
class ClusteringPlugin(ABC):
"""Interface for clustering plugins."""
[docs]
@abstractmethod
def fit(self, df: pd.DataFrame) -> pd.Series:
"""Perform clustering and return labels."""
pass
[docs]
class OptimizationPlugin(ABC):
"""Interface for optimization backends (Pyomo, OR-Tools, ...)."""
[docs]
@abstractmethod
def build(self, *, u_mat=None, w_mat=None, v_mat=None, dv_mat=None):
"""Create and return a model handle (e.g., a Pyomo model wrapper)."""
pass
[docs]
@abstractmethod
def solve(self, *, solver=None):
"""Solve the problem using current data."""
pass
[docs]
class ConnectorPlugin(ABC):
"""Interface for connector plugins."""
[docs]
@abstractmethod
def apply_moves(self, moves: Any) -> None:
"""Apply relocation moves to the target environment."""
pass
[docs]
class ProblemPlugin(ABC):
"""Interface for domain‑specific problem plugins (placement, allocation, etc.)."""
[docs]
@abstractmethod
def adjust(self, solution: Any, **kwargs) -> Any:
"""
Given an optimization solution (and any auxiliary data),
return an adjusted solution.
"""
pass
[docs]
@abstractmethod
def initial(
self,
labels: pd.Series,
df_indiv: pd.DataFrame,
df_host: pd.DataFrame,
) -> list[dict[str, Any]]:
"""
Produce the initial problem solution if needed.
:param labels: cluster labels from initial clustering
:param df_indiv: individual‐level data
:param df_host: host‐level data
:return: list of move dicts to apply
"""
pass