Source code for smartcer.forecasts.perfect

"""
Perfect forecast: the true future values of the scenario data.
"""

import numpy as np

from smartcer.core.community import Community
from smartcer.forecasts.base import FORECAST_QUANTITIES, check_steps, community_totals


[docs] class PerfectForecast: """ Forecast provider that returns the true generation and load of every node and the community totals of the nodes without a battery (`community_totals`). Generation is zero for a consumer and load is zero for a producer, as in the node data. Attributes: n_steps: Number of steps of the community period. """ def __init__(self, community: Community) -> None: """ Read the series of every node. Args: community: The community whose data are forecast. """ self.n_steps = community.n_steps series = {f'{node.node_id}/{quantity}': getattr(node, f'{quantity}_kwh') for node in community.nodes for quantity in FORECAST_QUANTITIES} series.update(community_totals(community)) self._keys = tuple(series) # one row per key, so that a forecast is a single copy self._data = np.vstack(list(series.values())) def __repr__(self) -> str: return f'PerfectForecast({len(self._keys)} series, {self.n_steps} steps)'
[docs] def reset(self, rng: np.random.Generator) -> None: """ Start an episode; a perfect forecast is deterministic and ignores the generator. Args: rng: The environment's random generator. """
[docs] def get(self, t: int, horizon: int) -> dict[str, np.ndarray]: """ True values of the steps t, ..., t + horizon - 1. Args: t: First forecast step. horizon: Number of steps H, ≥ 1. Returns: dict[str, np.ndarray]: `'<node_id>/generation'` and `'<node_id>/load'` of every node and the community totals → copies of the H values (kWh per step). Raises: ValueError: If the horizon is not positive or the steps leave the period. """ check_steps(t, horizon, self.n_steps) return dict(zip(self._keys, self._data[:, t:t + horizon].copy()))