File size: 3,992 Bytes
8a02303 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | """
Karnataka Grid Scenarios
========================
Generates difficulty variants of the Karnataka 15-bus grid.
Same topology (KPTCL transmission map), different operating conditions.
Scenarios vary:
- Renewable penetration (solar/wind max_p)
- Load magnitude (base_p multiplier)
- Line capacity (tighter or relaxed limits)
- Battery capacity
"""
import copy
from typing import Dict
from src.tasks import generate_karnataka_task
__all__ = ['generate_karnataka_scenario', 'KARNATAKA_SCENARIOS']
# Difficulty profiles: multipliers applied to the base Karnataka grid
_DIFFICULTY_PROFILES = {
"easy": {
"description": "Low renewables, light load, relaxed lines",
"renewable_multiplier": 0.3, # Solar/wind max_p scaled down
"load_multiplier": 0.6, # Loads are lighter
"line_capacity_multiplier": 1.5, # Lines can carry more
"battery_capacity_multiplier": 1.5, # More storage headroom
"max_steps": 50,
},
"medium": {
"description": "Moderate renewables, normal load, standard lines",
"renewable_multiplier": 0.7,
"load_multiplier": 1.0,
"line_capacity_multiplier": 1.0,
"battery_capacity_multiplier": 1.0,
"max_steps": 50,
},
"hard": {
"description": "High renewables, peak demand, tight lines",
"renewable_multiplier": 1.3, # More volatile supply
"load_multiplier": 1.4, # Peak demand
"line_capacity_multiplier": 0.75, # Congested corridors
"battery_capacity_multiplier": 0.7, # Less storage
"max_steps": 50,
},
}
def generate_karnataka_scenario(difficulty: str, seed: int = 808) -> Dict:
"""Generate a Karnataka grid scenario at a given difficulty level.
The base topology (15 buses, 18 lines, 4 zones) is identical across
all difficulties. Only the operating conditions change:
- Renewable generation capacity (solar/wind max_p)
- Load demand (base_p on load buses)
- Transmission line capacity
- Battery storage capacity
This enables curriculum learning on a consistent grid structure.
"""
if difficulty not in _DIFFICULTY_PROFILES:
raise ValueError(
f"Unknown difficulty '{difficulty}'. "
f"Available: {list(_DIFFICULTY_PROFILES.keys())}"
)
profile = _DIFFICULTY_PROFILES[difficulty]
base = generate_karnataka_task(seed=seed)
# Apply multipliers to buses
for bus in base["buses"]:
bus_type = bus["type"]
if bus_type in ("solar", "wind"):
bus["max_p"] = round(bus["max_p"] * profile["renewable_multiplier"], 1)
elif bus_type == "load":
bus["base_p"] = round(bus["base_p"] * profile["load_multiplier"], 1)
elif bus_type == "battery":
bus["max_p"] = round(bus["max_p"] * profile["battery_capacity_multiplier"], 1)
bus["capacity"] = round(bus["capacity"] * profile["battery_capacity_multiplier"], 1)
bus["init_soc"] = round(bus["capacity"] * 0.5, 1)
elif bus_type == "slack":
# Scale slack to cover the adjusted load
total_load = sum(
b["base_p"] * (profile["load_multiplier"] if b["type"] == "load" else 1.0)
for b in base["buses"] if b["type"] == "load"
)
bus["max_p"] = max(200, round(total_load * 0.8, 1))
bus["min_p"] = -bus["max_p"]
# Apply line capacity multiplier
for line in base["lines"]:
line["capacity"] = round(line["capacity"] * profile["line_capacity_multiplier"], 1)
# Update metadata
base["id"] = f"karnataka_{difficulty}"
base["difficulty"] = f"karnataka_{difficulty}"
base["max_steps"] = profile["max_steps"]
base["scenario_description"] = profile["description"]
return base
# Pre-built scenario configs
KARNATAKA_SCENARIOS = {
f"karnataka_{diff}": generate_karnataka_scenario(diff)
for diff in _DIFFICULTY_PROFILES
}
|