grid2op-openenv / scripts /check_dataset_quality.py
Sidharth1743's picture
space snapshot
a754878
Raw
History Blame Contribute Delete
6.25 kB
from __future__ import annotations
import argparse
import json
from collections import Counter, defaultdict
from pathlib import Path
from typing import Any
def _selected_action_type(action: dict[str, Any]) -> str:
if action.get("do_nothing"):
return "do_nothing"
if action.get("redispatch"):
return "redispatch"
if action.get("line_set"):
statuses = [int(value) for value in action["line_set"].values()]
if statuses and statuses[0] == 1:
return "reconnect_line"
if statuses and statuses[0] == -1:
return "disconnect_line"
return "line_set"
return "empty"
def _selectable_simulations(simulations: list[dict[str, Any]]) -> list[dict[str, Any]]:
return [
simulation
for simulation in simulations
if not simulation.get("done") and not simulation.get("convergence_failed")
]
def _best_indices(simulations: list[dict[str, Any]]) -> dict[str, int | None]:
selectable = _selectable_simulations(simulations)
if not selectable:
return {
"best_reward": None,
"best_rho": None,
"best_safe_reward": None,
}
safe = [
simulation
for simulation in selectable
if not simulation.get("overloaded_line_ids")
]
best_reward = max(
selectable, key=lambda simulation: float(simulation["simulated_reward"])
)["candidate_index"]
best_rho = min(
selectable, key=lambda simulation: float(simulation["max_rho"])
)["candidate_index"]
best_safe_reward = max(
safe or selectable,
key=lambda simulation: float(simulation["simulated_reward"]),
)["candidate_index"]
return {
"best_reward": int(best_reward),
"best_rho": int(best_rho),
"best_safe_reward": int(best_safe_reward),
}
def check_dataset(path: Path) -> dict[str, Any]:
by_task: dict[str, dict[str, Any]] = defaultdict(
lambda: {
"rows": 0,
"no_selectable_simulations": 0,
"selected_not_best_reward": 0,
"selected_not_best_rho": 0,
"selected_not_best_safe_reward": 0,
"actions": Counter(),
"label_policies": Counter(),
"benchmark_tiers": Counter(),
}
)
global_counts: dict[str, Any] = {
"path": str(path),
"rows": 0,
"invalid_json_rows": 0,
"missing_metadata_rows": 0,
"missing_selected_action_rows": 0,
"missing_simulations_rows": 0,
}
row_issues: list[dict[str, Any]] = []
for line_no, line in enumerate(path.read_text().splitlines(), 1):
if not line.strip():
continue
try:
row = json.loads(line)
except json.JSONDecodeError as exc:
global_counts["invalid_json_rows"] += 1
row_issues.append(
{"line": line_no, "issue": "invalid_json", "error": str(exc)}
)
continue
global_counts["rows"] += 1
metadata = row.get("metadata")
if not isinstance(metadata, dict):
global_counts["missing_metadata_rows"] += 1
row_issues.append({"line": line_no, "issue": "missing_metadata"})
continue
task_id = str(metadata.get("task_id", "unknown"))
task_stats = by_task[task_id]
task_stats["rows"] += 1
task_stats["label_policies"][str(metadata.get("label_policy", "missing"))] += 1
task_stats["benchmark_tiers"][str(metadata.get("benchmark_tier", "missing"))] += 1
selected_action = metadata.get("selected_action")
if not isinstance(selected_action, dict):
global_counts["missing_selected_action_rows"] += 1
row_issues.append(
{"line": line_no, "task_id": task_id, "issue": "missing_selected_action"}
)
continue
task_stats["actions"][_selected_action_type(selected_action)] += 1
simulations = metadata.get("simulations")
if not isinstance(simulations, list) or not simulations:
global_counts["missing_simulations_rows"] += 1
row_issues.append(
{"line": line_no, "task_id": task_id, "issue": "missing_simulations"}
)
continue
selected_candidate = metadata.get("selected_candidate")
best = _best_indices(simulations)
if best["best_reward"] is None:
task_stats["no_selectable_simulations"] += 1
row_issues.append(
{"line": line_no, "task_id": task_id, "issue": "no_selectable_simulations"}
)
continue
if selected_candidate != best["best_reward"]:
task_stats["selected_not_best_reward"] += 1
if selected_candidate != best["best_rho"]:
task_stats["selected_not_best_rho"] += 1
if selected_candidate != best["best_safe_reward"]:
task_stats["selected_not_best_safe_reward"] += 1
task_output: dict[str, Any] = {}
for task_id, stats in sorted(by_task.items()):
task_output[task_id] = {
"rows": stats["rows"],
"no_selectable_simulations": stats["no_selectable_simulations"],
"selected_not_best_reward": stats["selected_not_best_reward"],
"selected_not_best_rho": stats["selected_not_best_rho"],
"selected_not_best_safe_reward": stats["selected_not_best_safe_reward"],
"actions": dict(sorted(stats["actions"].items())),
"label_policies": dict(sorted(stats["label_policies"].items())),
"benchmark_tiers": dict(sorted(stats["benchmark_tiers"].items())),
}
return {
"summary": global_counts,
"tasks": task_output,
"row_issues": row_issues[:100],
"row_issue_count": len(row_issues),
}
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description="Check Grid2Op teacher dataset JSONL quality."
)
parser.add_argument("path", type=Path)
return parser.parse_args()
def main() -> None:
args = parse_args()
print(json.dumps(check_dataset(args.path), indent=2, sort_keys=True))
if __name__ == "__main__":
main()