Source code for smartcer.gym.rewards.config
"""
Registry of the reward types and factory of the reward calculators.
Adapted from storage-node-environment (`storage_node_env/gym/rewards/config.py`): the factory reads
the registry instead of an if/elif chain; the registry is read-only.
"""
from collections.abc import Sequence
from dataclasses import dataclass
from types import MappingProxyType
from smartcer.gym.rewards.base import RewardCalculator
from smartcer.gym.rewards.calculators import EnergyReward, ProfitReward, WelfareReward
[docs]
@dataclass(frozen=True, slots=True)
class RewardConfig:
"""
Entry of the reward registry.
Attributes:
name: Reward type name.
description: Objective of the reward.
calculator: Calculator class.
"""
name: str
description: str
calculator: type[RewardCalculator]
REWARD_REGISTRY = MappingProxyType({
config.name: config for config in (
RewardConfig('welfare', 'social welfare W_t minus σ K_t (default)', WelfareReward),
RewardConfig('profit', 'net profit per node; collective variant plus the incentive',
ProfitReward),
RewardConfig('energy', '0.6.2 legacy: minus the squared imported energy',
EnergyReward),
)
})
REWARD_TYPES = tuple(REWARD_REGISTRY)
[docs]
def make_reward(reward_type: str, storage_node_ids: Sequence[str],
penalty_coefficient: float = 10.0, per_node: bool = False) -> RewardCalculator:
"""
Create the calculator of a registered reward type.
Args:
reward_type: Name in `REWARD_REGISTRY`.
storage_node_ids: Identifiers of the battery nodes.
penalty_coefficient: σ, ≥ 0.
per_node: Use the per-node variant.
Returns:
RewardCalculator: The calculator.
Raises:
ValueError: For an unknown type, an invalid σ or an unsupported per-node variant.
"""
if reward_type not in REWARD_REGISTRY:
raise ValueError(f'unknown reward {reward_type!r}; available: {REWARD_TYPES}')
calculator = REWARD_REGISTRY[reward_type].calculator
return calculator(storage_node_ids, penalty_coefficient=penalty_coefficient,
per_node=per_node)