grid / smartgrid_mas /tasks.py
Not-OmKar's picture
Big update
427a79e
from dataclasses import dataclass
from typing import Dict
@dataclass
class TaskConfig:
task_id: str
description: str
max_steps: int
initial_demand_mwh: float
initial_renewable_mwh: float
peaker_capacity_mwh: float
ev_storage_mwh: float
ev_storage_capacity_mwh: float
base_price_usd_per_mwh: float
demand_trend_mwh: float
renewable_trend_mwh: float
demand_volatility: float
renewable_volatility: float
shock_step: int
shock_renewable_drop: float
reserve_margin_ratio: float
reserve_commitment_threshold_ratio: float
peaker_ramp_limit_mwh: float
peaker_activation_delay_steps: int
ev_ramp_limit_mwh: float
peaker_startup_cost_usd: float
peaker_emission_factor_tco2_per_mwh: float
carbon_price_usd_per_tco2: float
load_forecast_sigma: float
renewable_forecast_sigma: float
contingency_type: str
contingency_step: int
contingency_derate_pct: float
hint: str
enable_reserve_logic: bool = True
enable_ramp_limits: bool = True
enable_startup_emissions: bool = True
TASKS: Dict[str, TaskConfig] = {
"default": TaskConfig(
task_id="default",
description=(
"Hybrid multi-agent smart-grid market simulation. Agents submit strategic bids, "
"market clears, and LDU enforces physical feasibility with correction logs."
),
max_steps=24,
initial_demand_mwh=120.0,
initial_renewable_mwh=70.0,
peaker_capacity_mwh=85.0,
ev_storage_mwh=25.0,
ev_storage_capacity_mwh=60.0,
base_price_usd_per_mwh=45.0,
demand_trend_mwh=1.2,
renewable_trend_mwh=-0.6,
demand_volatility=4.0,
renewable_volatility=6.0,
shock_step=16,
shock_renewable_drop=22.0,
reserve_margin_ratio=0.12,
reserve_commitment_threshold_ratio=1.0,
peaker_ramp_limit_mwh=14.0,
peaker_activation_delay_steps=0,
ev_ramp_limit_mwh=9.0,
peaker_startup_cost_usd=180.0,
peaker_emission_factor_tco2_per_mwh=0.45,
carbon_price_usd_per_tco2=50.0,
load_forecast_sigma=4.0,
renewable_forecast_sigma=6.0,
contingency_type="none",
contingency_step=-1,
contingency_derate_pct=0.0,
hint=(
"Coordinate bids with expected dispatch feasibility. Market-optimal bids that violate "
"physical constraints are corrected by LDU and reduce reward."
),
),
"long_horizon": TaskConfig(
task_id="long_horizon",
description=(
"Extended 48-step planning regime with recurring scarcity windows and delayed consequences. "
"This task emphasizes long-horizon stability and storage foresight."
),
max_steps=48,
initial_demand_mwh=135.0,
initial_renewable_mwh=78.0,
peaker_capacity_mwh=90.0,
ev_storage_mwh=32.0,
ev_storage_capacity_mwh=75.0,
base_price_usd_per_mwh=48.0,
demand_trend_mwh=1.5,
renewable_trend_mwh=-0.8,
demand_volatility=5.0,
renewable_volatility=7.0,
shock_step=28,
shock_renewable_drop=26.0,
reserve_margin_ratio=0.14,
reserve_commitment_threshold_ratio=1.0,
peaker_ramp_limit_mwh=12.0,
peaker_activation_delay_steps=1,
ev_ramp_limit_mwh=8.0,
peaker_startup_cost_usd=210.0,
peaker_emission_factor_tco2_per_mwh=0.45,
carbon_price_usd_per_tco2=60.0,
load_forecast_sigma=5.5,
renewable_forecast_sigma=7.0,
contingency_type="transmission_derate",
contingency_step=30,
contingency_derate_pct=0.18,
hint=(
"Favor smooth dispatch and avoid repeated infeasible corrections. Battery misuse early in the "
"episode causes compounding penalties later."
),
),
"stress_shock": TaskConfig(
task_id="stress_shock",
description=(
"Shock-heavy reliability scenario. Market remains strategic, but severe renewable drop and high "
"demand volatility test emergency balancing behavior."
),
max_steps=30,
initial_demand_mwh=150.0,
initial_renewable_mwh=85.0,
peaker_capacity_mwh=96.0,
ev_storage_mwh=24.0,
ev_storage_capacity_mwh=70.0,
base_price_usd_per_mwh=55.0,
demand_trend_mwh=2.0,
renewable_trend_mwh=-1.0,
demand_volatility=7.5,
renewable_volatility=9.0,
shock_step=12,
shock_renewable_drop=35.0,
reserve_margin_ratio=0.16,
reserve_commitment_threshold_ratio=1.05,
peaker_ramp_limit_mwh=10.0,
peaker_activation_delay_steps=1,
ev_ramp_limit_mwh=7.0,
peaker_startup_cost_usd=260.0,
peaker_emission_factor_tco2_per_mwh=0.47,
carbon_price_usd_per_tco2=70.0,
load_forecast_sigma=8.0,
renewable_forecast_sigma=10.0,
contingency_type="peaker_trip",
contingency_step=13,
contingency_derate_pct=0.55,
hint=(
"Expect early shock and repeated scarcity. Policies must adapt quickly while keeping LDU corrections low."
),
),
"normal": TaskConfig(
task_id="normal",
description="Normal operations benchmark with mild variability and no forced shock.",
max_steps=24,
initial_demand_mwh=118.0,
initial_renewable_mwh=74.0,
peaker_capacity_mwh=86.0,
ev_storage_mwh=28.0,
ev_storage_capacity_mwh=62.0,
base_price_usd_per_mwh=44.0,
demand_trend_mwh=1.0,
renewable_trend_mwh=-0.4,
demand_volatility=3.0,
renewable_volatility=4.5,
shock_step=-1,
shock_renewable_drop=0.0,
reserve_margin_ratio=0.12,
reserve_commitment_threshold_ratio=1.0,
peaker_ramp_limit_mwh=15.0,
peaker_activation_delay_steps=0,
ev_ramp_limit_mwh=9.0,
peaker_startup_cost_usd=170.0,
peaker_emission_factor_tco2_per_mwh=0.44,
carbon_price_usd_per_tco2=45.0,
load_forecast_sigma=3.5,
renewable_forecast_sigma=5.0,
contingency_type="none",
contingency_step=-1,
contingency_derate_pct=0.0,
hint="Normal benchmark mode: prioritize efficient, low-correction dispatch.",
),
"outage": TaskConfig(
task_id="outage",
description="Outage benchmark with N-1 generator-or-feeder contingency and delayed thermal recovery.",
max_steps=30,
initial_demand_mwh=142.0,
initial_renewable_mwh=82.0,
peaker_capacity_mwh=95.0,
ev_storage_mwh=26.0,
ev_storage_capacity_mwh=68.0,
base_price_usd_per_mwh=53.0,
demand_trend_mwh=1.8,
renewable_trend_mwh=-0.9,
demand_volatility=6.0,
renewable_volatility=8.0,
shock_step=-1,
shock_renewable_drop=0.0,
reserve_margin_ratio=0.16,
reserve_commitment_threshold_ratio=1.08,
peaker_ramp_limit_mwh=9.0,
peaker_activation_delay_steps=1,
ev_ramp_limit_mwh=7.0,
peaker_startup_cost_usd=255.0,
peaker_emission_factor_tco2_per_mwh=0.47,
carbon_price_usd_per_tco2=70.0,
load_forecast_sigma=7.5,
renewable_forecast_sigma=9.0,
contingency_type="n_minus_one",
contingency_step=10,
contingency_derate_pct=0.6,
hint="Outage mode: N-1 resilience, reserve, and startup realism dominate.",
),
"renewable_collapse": TaskConfig(
task_id="renewable_collapse",
description="Renewable collapse benchmark with severe forecast error and large drop event.",
max_steps=30,
initial_demand_mwh=146.0,
initial_renewable_mwh=88.0,
peaker_capacity_mwh=96.0,
ev_storage_mwh=24.0,
ev_storage_capacity_mwh=70.0,
base_price_usd_per_mwh=56.0,
demand_trend_mwh=1.9,
renewable_trend_mwh=-1.2,
demand_volatility=7.0,
renewable_volatility=10.0,
shock_step=8,
shock_renewable_drop=48.0,
reserve_margin_ratio=0.18,
reserve_commitment_threshold_ratio=1.1,
peaker_ramp_limit_mwh=9.0,
peaker_activation_delay_steps=1,
ev_ramp_limit_mwh=6.5,
peaker_startup_cost_usd=270.0,
peaker_emission_factor_tco2_per_mwh=0.48,
carbon_price_usd_per_tco2=75.0,
load_forecast_sigma=9.0,
renewable_forecast_sigma=12.0,
contingency_type="transmission_derate",
contingency_step=12,
contingency_derate_pct=0.22,
hint="Renewable collapse mode: recover from severe uncertainty and scarcity.",
),
}
def get_task(task_id: str) -> TaskConfig:
if task_id not in TASKS:
raise ValueError(f"Unknown task_id '{task_id}'. Available: {list(TASKS.keys())}")
return TASKS[task_id]
def list_tasks() -> list[str]:
return list(TASKS.keys())