/ concept-collection / fastandaccurate
Sign in
concept-collection / fastandaccurate
fastandaccurate / src / harness / resultSchema.ts
112 lines · 3.0 KBBlameHistoryRaw
1// The result-file format committed to the fastandaccurate-results repo.
2// One file holds one work-precision sweep: one problem instance, one
3// solver, one environment.
5import {
6 canonicalSpec,
7 canonicalSpecJson,
8 PROBLEM_ID,
9 PROBLEM_VERSION,
10 type Laplace2dInstance,
11} from "../problems/laplace2d/spec";
12import type { RunPoint } from "./runner";
14export const RESULT_FORMAT = "fastandaccurate-result";
15export const RESULT_FORMAT_VERSION = 1;
17export interface ResultEnvironment {
18 kind: "browser" | "node";
19 /** User agent string (browser) or node version (node). */
20 runtime: string;
21 numblVersion: string;
22 os?: string;
23 cpu?: string;
24 /** Free-text label a human recognizes ("office workstation"). */
25 machineLabel?: string;
26 /** Whether a visitor can rerun this result in the browser. */
27 browserReproducible: boolean;
30export interface ResultPoint {
31 n: number;
32 solveSeconds: number;
33 solveSecondsAll: number[];
34 coldSeconds: number;
35 relMax: number;
36 relL2: number;
39export interface ResultFile {
40 format: typeof RESULT_FORMAT;
41 formatVersion: typeof RESULT_FORMAT_VERSION;
42 problem: string;
43 problemVersion: number;
44 instance: string;
45 spec: Record<string, unknown>;
46 specHash: string;
47 solver: {
48 id: string;
49 version: string;
50 backend: "cpu" | "gpu";
51 /** "builtin" for solvers in the fastandaccurate repo; otherwise a
52 * URL or free-text pointer to the solver's source. */
53 source: string;
54 };
55 environment: ResultEnvironment;
56 protocol: {
57 warmupRuns: number;
58 timedRuns: number;
59 timer: string;
60 };
61 createdUtc: string;
62 points: ResultPoint[];
65/** SHA-256 hex digest, using WebCrypto (browser, worker, node >= 20). */
66export async function sha256Hex(text: string): Promise<string> {
67 const digest = await crypto.subtle.digest(
68 "SHA-256",
69 new TextEncoder().encode(text)
70 );
71 return Array.from(new Uint8Array(digest))
72 .map((b) => b.toString(16).padStart(2, "0"))
73 .join("");
76export function toResultPoint(p: RunPoint): ResultPoint {
77 return {
78 n: p.n,
79 solveSeconds: p.solveSeconds,
80 solveSecondsAll: p.solveSecondsAll,
81 coldSeconds: p.coldSeconds,
82 relMax: p.relMax,
83 relL2: p.relL2,
84 };
87export async function buildResultFile(opts: {
88 instance: Laplace2dInstance;
89 solver: { id: string; version: string; backend: "cpu" | "gpu"; source: string };
90 environment: ResultEnvironment;
91 repeats: number;
92 points: ResultPoint[];
93}): Promise<ResultFile> {
94 return {
95 format: RESULT_FORMAT,
96 formatVersion: RESULT_FORMAT_VERSION,
97 problem: PROBLEM_ID,
98 problemVersion: PROBLEM_VERSION,
99 instance: opts.instance.id,
100 spec: canonicalSpec(opts.instance) as unknown as Record<string, unknown>,
101 specHash: await sha256Hex(canonicalSpecJson(opts.instance)),
102 solver: opts.solver,
103 environment: opts.environment,
104 protocol: {
105 warmupRuns: 1,
106 timedRuns: opts.repeats,
107 timer: "numbl tic/toc",
108 },
109 createdUtc: new Date().toISOString(),
110 points: opts.points,
111 };
moveopenescclose