from __future__ import annotations import os import time import random import re from dataclasses import dataclass from typing import Any, Dict, Iterable, Optional import numpy as np def now_ts() -> float: return time.time() def seed_everything(seed: int) -> None: random.seed(seed) np.random.seed(seed) os.environ["PYTHONHASHSEED"] = str(seed) def ensure_dir(path: str) -> None: os.makedirs(path, exist_ok=True) def clamp(x: float, lo: float, hi: float) -> float: return max(lo, min(hi, x)) def stable_hash(s: str) -> str: # Short stable tag for filenames/variants import hashlib return hashlib.sha1(s.encode("utf-8")).hexdigest()[:10] def sanitize_variant_prefix(name: str, max_len: int = 24) -> str: safe = re.sub(r"[^A-Za-z0-9_]+", "_", name).strip("_") if not safe: safe = "run" if max_len > 0 and len(safe) > max_len: safe = safe[:max_len] return safe @dataclass(frozen=True) class TrialKey: exp_name: str platform: str design: str variant: str fidelity: str