File size: 2,156 Bytes
5ccb4fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# Copyright (c) 2026 Simulacra Research Inc.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal

from .statistics import ChannelMetrics


EvalPath = Literal["ordinary", "contest", "large_n"]


@dataclass(frozen=True, slots=True)
class ContestCandidate:
    index: int
    route_log_probability: float
    energy: float
    standard_error: float
    walker_tail_std: float
    in_tie_set: bool

    def as_dict(self) -> dict[str, int | float | bool]:
        return {
            "index": self.index,
            "route_log_probability": self.route_log_probability,
            "energy": self.energy,
            "standard_error": self.standard_error,
            "walker_tail_std": self.walker_tail_std,
            "in_tie_set": self.in_tie_set,
        }


@dataclass(frozen=True, slots=True)
class ContestResult:
    winner: int
    reason: str
    candidates: tuple[ContestCandidate, ...]

    def as_dict(self) -> dict:
        return {
            "winner": self.winner,
            "reason": self.reason,
            "candidates": [candidate.as_dict() for candidate in self.candidates],
        }


@dataclass(frozen=True, slots=True)
class EvalMetric:
    step: int
    energy: float
    energy_std: float
    step_walltime: float
    walltime: float


@dataclass(frozen=True, slots=True)
class EvalResult:
    path: EvalPath
    route: tuple[int, ...]
    route_log_probability: float | None
    measurements: int
    walltime_seconds: float
    energy: ChannelMetrics
    channels: dict[str, ChannelMetrics]
    contest: ContestResult | None = None

    def as_dict(self) -> dict:
        result = {
            "measurements": self.measurements,
            "walltime_seconds": self.walltime_seconds,
            "energy": self.energy.mean,
            "energy_std": self.energy.local_energy_std,
            "channels": {name: metrics.mean for name, metrics in self.channels.items()},
        }
        if self.energy.lag1_autocorrelation is not None:
            result["energy_lag1_autocorrelation"] = self.energy.lag1_autocorrelation
        return result