Skip to content

Commit feea856

Browse files
committed
fix delete script
1 parent dcd2596 commit feea856

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { parentPort } from "node:worker_threads"
2+
import { HighDensitySolver } from "lib/solvers/HighDensitySolver/HighDensitySolver"
3+
import { calculateNodeProbabilityOfFailure } from "lib/solvers/UnravelSolver/calculateCrossingProbabilityOfFailure.ts"
4+
import { NodeWithPortPoints } from "lib/types/high-density-types.ts"
5+
import { getIntraNodeCrossingsUsingCircle } from "lib/utils/getIntraNodeCrossingsUsingCircle"
6+
7+
type WorkerRequest = {
8+
taskId: number
9+
problemId: string
10+
problem: unknown
11+
}
12+
13+
type WorkerResponse =
14+
| {
15+
type: "result"
16+
taskId: number
17+
value: number
18+
solved: boolean
19+
solveDurationMs: number
20+
}
21+
| {
22+
type: "error"
23+
taskId: number
24+
error: string
25+
}
26+
27+
const unwrapProblem = (problem: unknown) => {
28+
// The dataset currently wraps the benchmark payload as { id, data }.
29+
if (typeof problem === "object" && problem !== null && "data" in problem) {
30+
return (problem as { data: unknown }).data
31+
}
32+
33+
return problem
34+
}
35+
36+
const computeProblemScore = (problem: unknown) => {
37+
// The worker keeps the benchmark math off the main thread.
38+
// The worker owns both the predictor and the real solve for one problem.
39+
const typedProblem = unwrapProblem(problem) as NodeWithPortPoints
40+
const stats = getIntraNodeCrossingsUsingCircle(typedProblem)
41+
42+
// Normalize optional fields so the scoring function always sees the same shape.
43+
// Keep the payload normalized to the same shape used by the old benchmark path.
44+
const predictedFailure = calculateNodeProbabilityOfFailure(
45+
{
46+
...typedProblem,
47+
layer: "",
48+
availableZ: typedProblem.availableZ ?? [],
49+
},
50+
stats.numSameLayerCrossings,
51+
stats.numEntryExitLayerChanges,
52+
stats.numTransitionPairCrossings,
53+
)
54+
55+
// The benchmark target must come from a real solve, not from cached result files.
56+
const solver = new HighDensitySolver({
57+
nodePortPoints: [typedProblem],
58+
})
59+
const solveStart = performance.now()
60+
solver.solve()
61+
const solveDurationMs = performance.now() - solveStart
62+
63+
// The target is binary: solved means 0 failure, unsolved means 1 failure.
64+
const actualFailure = solver.solved ? 0 : 1
65+
return {
66+
value: (predictedFailure - actualFailure) ** 2,
67+
solved: solver.solved,
68+
solveDurationMs,
69+
}
70+
}
71+
72+
if (!parentPort) {
73+
throw new Error("Benchmark worker must run inside a worker thread")
74+
}
75+
76+
const workerParentPort = parentPort
77+
78+
workerParentPort.on("message", (message: WorkerRequest) => {
79+
// A worker can process many tasks over its lifetime, one message at a time.
80+
// Each message is independent, so a failed problem should not poison the worker process.
81+
try {
82+
const result = computeProblemScore(message.problem)
83+
workerParentPort.postMessage({
84+
type: "result",
85+
taskId: message.taskId,
86+
value: result.value,
87+
solved: result.solved,
88+
solveDurationMs: result.solveDurationMs,
89+
} satisfies WorkerResponse)
90+
} catch (error) {
91+
// Report errors back to the parent so it can decide whether to continue or abort.
92+
const messageText = error instanceof Error ? error.message : String(error)
93+
workerParentPort.postMessage({
94+
type: "error",
95+
taskId: message.taskId,
96+
error: messageText,
97+
} satisfies WorkerResponse)
98+
}
99+
})

0 commit comments

Comments
 (0)