melete-ai 0.88.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +72 -0
- package/bin/melete-server.mjs +345 -0
- package/bin/melete.mjs +165 -0
- package/dist/achievability.d.ts +38 -0
- package/dist/achievability.d.ts.map +1 -0
- package/dist/achievability.js +135 -0
- package/dist/achievability.js.map +1 -0
- package/dist/aegis.d.ts +52 -0
- package/dist/aegis.d.ts.map +1 -0
- package/dist/aegis.js +191 -0
- package/dist/aegis.js.map +1 -0
- package/dist/arms.d.ts +70 -0
- package/dist/arms.d.ts.map +1 -0
- package/dist/arms.js +399 -0
- package/dist/arms.js.map +1 -0
- package/dist/batch.d.ts +30 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +151 -0
- package/dist/batch.js.map +1 -0
- package/dist/bench.d.ts +49 -0
- package/dist/bench.d.ts.map +1 -0
- package/dist/bench.js +124 -0
- package/dist/bench.js.map +1 -0
- package/dist/certify.d.ts +48 -0
- package/dist/certify.d.ts.map +1 -0
- package/dist/certify.js +125 -0
- package/dist/certify.js.map +1 -0
- package/dist/cliff.d.ts +41 -0
- package/dist/cliff.d.ts.map +1 -0
- package/dist/cliff.js +132 -0
- package/dist/cliff.js.map +1 -0
- package/dist/confidence.d.ts +38 -0
- package/dist/confidence.d.ts.map +1 -0
- package/dist/confidence.js +98 -0
- package/dist/confidence.js.map +1 -0
- package/dist/constrained.d.ts +59 -0
- package/dist/constrained.d.ts.map +1 -0
- package/dist/constrained.js +191 -0
- package/dist/constrained.js.map +1 -0
- package/dist/cortex.d.ts +56 -0
- package/dist/cortex.d.ts.map +1 -0
- package/dist/cortex.js +81 -0
- package/dist/cortex.js.map +1 -0
- package/dist/costaware.d.ts +49 -0
- package/dist/costaware.d.ts.map +1 -0
- package/dist/costaware.js +185 -0
- package/dist/costaware.js.map +1 -0
- package/dist/drift.d.ts +36 -0
- package/dist/drift.d.ts.map +1 -0
- package/dist/drift.js +157 -0
- package/dist/drift.js.map +1 -0
- package/dist/efficiency.d.ts +49 -0
- package/dist/efficiency.d.ts.map +1 -0
- package/dist/efficiency.js +143 -0
- package/dist/efficiency.js.map +1 -0
- package/dist/engine.d.ts +64 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +130 -0
- package/dist/engine.js.map +1 -0
- package/dist/federated.d.ts +38 -0
- package/dist/federated.d.ts.map +1 -0
- package/dist/federated.js +121 -0
- package/dist/federated.js.map +1 -0
- package/dist/frontier.d.ts +51 -0
- package/dist/frontier.d.ts.map +1 -0
- package/dist/frontier.js +117 -0
- package/dist/frontier.js.map +1 -0
- package/dist/guardian.d.ts +46 -0
- package/dist/guardian.d.ts.map +1 -0
- package/dist/guardian.js +101 -0
- package/dist/guardian.js.map +1 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +189 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction.d.ts +44 -0
- package/dist/interaction.d.ts.map +1 -0
- package/dist/interaction.js +167 -0
- package/dist/interaction.js.map +1 -0
- package/dist/interactive.d.ts +25 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +75 -0
- package/dist/interactive.js.map +1 -0
- package/dist/inverse.d.ts +44 -0
- package/dist/inverse.d.ts.map +1 -0
- package/dist/inverse.js +141 -0
- package/dist/inverse.js.map +1 -0
- package/dist/ipshield.d.ts +62 -0
- package/dist/ipshield.d.ts.map +1 -0
- package/dist/ipshield.js +104 -0
- package/dist/ipshield.js.map +1 -0
- package/dist/journalist.d.ts +56 -0
- package/dist/journalist.d.ts.map +1 -0
- package/dist/journalist.js +132 -0
- package/dist/journalist.js.map +1 -0
- package/dist/lineage.d.ts +43 -0
- package/dist/lineage.d.ts.map +1 -0
- package/dist/lineage.js +112 -0
- package/dist/lineage.js.map +1 -0
- package/dist/metabrain.d.ts +59 -0
- package/dist/metabrain.d.ts.map +1 -0
- package/dist/metabrain.js +215 -0
- package/dist/metabrain.js.map +1 -0
- package/dist/mixedspace.d.ts +61 -0
- package/dist/mixedspace.d.ts.map +1 -0
- package/dist/mixedspace.js +267 -0
- package/dist/mixedspace.js.map +1 -0
- package/dist/multiobjective.d.ts +42 -0
- package/dist/multiobjective.d.ts.map +1 -0
- package/dist/multiobjective.js +123 -0
- package/dist/multiobjective.js.map +1 -0
- package/dist/noise.d.ts +45 -0
- package/dist/noise.d.ts.map +1 -0
- package/dist/noise.js +148 -0
- package/dist/noise.js.map +1 -0
- package/dist/noiserobust.d.ts +71 -0
- package/dist/noiserobust.d.ts.map +1 -0
- package/dist/noiserobust.js +215 -0
- package/dist/noiserobust.js.map +1 -0
- package/dist/oracle.d.ts +63 -0
- package/dist/oracle.d.ts.map +1 -0
- package/dist/oracle.js +106 -0
- package/dist/oracle.js.map +1 -0
- package/dist/poopt.d.ts +79 -0
- package/dist/poopt.d.ts.map +1 -0
- package/dist/poopt.js +148 -0
- package/dist/poopt.js.map +1 -0
- package/dist/portfolio.d.ts +51 -0
- package/dist/portfolio.d.ts.map +1 -0
- package/dist/portfolio.js +132 -0
- package/dist/portfolio.js.map +1 -0
- package/dist/prescription.d.ts +57 -0
- package/dist/prescription.d.ts.map +1 -0
- package/dist/prescription.js +131 -0
- package/dist/prescription.js.map +1 -0
- package/dist/prime.d.ts +85 -0
- package/dist/prime.d.ts.map +1 -0
- package/dist/prime.js +157 -0
- package/dist/prime.js.map +1 -0
- package/dist/provenance.d.ts +77 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +155 -0
- package/dist/provenance.js.map +1 -0
- package/dist/rashomon.d.ts +40 -0
- package/dist/rashomon.d.ts.map +1 -0
- package/dist/rashomon.js +93 -0
- package/dist/rashomon.js.map +1 -0
- package/dist/reliability.d.ts +79 -0
- package/dist/reliability.d.ts.map +1 -0
- package/dist/reliability.js +197 -0
- package/dist/reliability.js.map +1 -0
- package/dist/replay.d.ts +62 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +146 -0
- package/dist/replay.js.map +1 -0
- package/dist/replicate.d.ts +72 -0
- package/dist/replicate.d.ts.map +1 -0
- package/dist/replicate.js +103 -0
- package/dist/replicate.js.map +1 -0
- package/dist/resonance.d.ts +32 -0
- package/dist/resonance.d.ts.map +1 -0
- package/dist/resonance.js +190 -0
- package/dist/resonance.js.map +1 -0
- package/dist/sensitivity.d.ts +44 -0
- package/dist/sensitivity.d.ts.map +1 -0
- package/dist/sensitivity.js +109 -0
- package/dist/sensitivity.js.map +1 -0
- package/dist/server.d.ts +26 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1410 -0
- package/dist/server.js.map +1 -0
- package/dist/shape.d.ts +37 -0
- package/dist/shape.d.ts.map +1 -0
- package/dist/shape.js +170 -0
- package/dist/shape.js.map +1 -0
- package/dist/sloppiness.d.ts +44 -0
- package/dist/sloppiness.d.ts.map +1 -0
- package/dist/sloppiness.js +194 -0
- package/dist/sloppiness.js.map +1 -0
- package/dist/sovereign.d.ts +77 -0
- package/dist/sovereign.d.ts.map +1 -0
- package/dist/sovereign.js +144 -0
- package/dist/sovereign.js.map +1 -0
- package/dist/space.d.ts +38 -0
- package/dist/space.d.ts.map +1 -0
- package/dist/space.js +107 -0
- package/dist/space.js.map +1 -0
- package/dist/surprise.d.ts +43 -0
- package/dist/surprise.d.ts.map +1 -0
- package/dist/surprise.js +123 -0
- package/dist/surprise.js.map +1 -0
- package/dist/territory.d.ts +43 -0
- package/dist/territory.d.ts.map +1 -0
- package/dist/territory.js +102 -0
- package/dist/territory.js.map +1 -0
- package/dist/trace.d.ts +58 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +0 -0
- package/dist/trace.js.map +1 -0
- package/dist/transfer.d.ts +46 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transfer.js +112 -0
- package/dist/transfer.js.map +1 -0
- package/dist/twin.d.ts +41 -0
- package/dist/twin.d.ts.map +1 -0
- package/dist/twin.js +116 -0
- package/dist/twin.js.map +1 -0
- package/examples/train.mjs +8 -0
- package/examples/tune.mjs +11 -0
- package/package.json +56 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MULTI-OBJECTIVE — real problems rarely have ONE goal. A pharma formulation must be more POTENT *and* more
|
|
3
|
+
* STABLE *and* cheaper; a fraud model must catch more fraud *and* decline fewer good customers. These trade
|
|
4
|
+
* off — there is no single best, but a PARETO FRONT of best-possible compromises.
|
|
5
|
+
*
|
|
6
|
+
* MULTI-OBJECTIVE finds that front from hand-measured results: you score each experiment on N objectives,
|
|
7
|
+
* and Melete (a) computes the exact non-dominated set and (b) proposes the next experiment to widen the
|
|
8
|
+
* front, by scalarising the objectives with a deterministically-varying weight vector so successive
|
|
9
|
+
* proposals probe different trade-offs. Deterministic ⇒ reproducible + signable like every Melete run.
|
|
10
|
+
*
|
|
11
|
+
* Honest by construction (DIAKRISIS): the Pareto front (dominance) is EXACT. The proposer uses weighted-sum
|
|
12
|
+
* scalarisation with rotating weights — simple, robust, and it reliably spreads along the front; it is not
|
|
13
|
+
* guaranteed to recover points on a deeply CONCAVE front (a known limitation of linear scalarisation, the
|
|
14
|
+
* honest trade-off for a dependency-free deterministic engine). The front it reports is always exact.
|
|
15
|
+
*/
|
|
16
|
+
import { type Space, type Experiment } from "./space.js";
|
|
17
|
+
export interface MGoal {
|
|
18
|
+
name?: string;
|
|
19
|
+
goal: "maximize" | "minimize";
|
|
20
|
+
}
|
|
21
|
+
export interface MObservation {
|
|
22
|
+
experiment: Experiment;
|
|
23
|
+
values: number[];
|
|
24
|
+
}
|
|
25
|
+
/** Does `a` Pareto-dominate `b` across all objectives (≥ in every one, > in at least one, in goal direction)? */
|
|
26
|
+
export declare function dominates(a: number[], b: number[], goals: ReadonlyArray<MGoal>): boolean;
|
|
27
|
+
/** The exact non-dominated set — the achievable best trade-offs. */
|
|
28
|
+
export declare function paretoFront(obs: ReadonlyArray<MObservation>, goals: ReadonlyArray<MGoal>): MObservation[];
|
|
29
|
+
/**
|
|
30
|
+
* Propose the next experiment to widen the Pareto front. Scalarises the N objectives with a weight vector
|
|
31
|
+
* that rotates with the run, so successive calls probe different corners of the trade-off space.
|
|
32
|
+
*/
|
|
33
|
+
export declare function proposeNextMulti(space: Space, obs: ReadonlyArray<MObservation>, goals: ReadonlyArray<MGoal>, seed?: number): Experiment;
|
|
34
|
+
export declare function multiObjectiveGauntlet(): {
|
|
35
|
+
score: 0 | 100;
|
|
36
|
+
checks: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
pass: boolean;
|
|
39
|
+
detail: string;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=multiobjective.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiobjective.d.ts","sourceRoot":"","sources":["../src/multiobjective.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAO,MAAM,YAAY,CAAC;AAG9D,MAAM,WAAW,KAAK;IAAG,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAAA;CAAE;AACvE,MAAM,WAAW,YAAY;IAAG,UAAU,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE;AAE1E,iHAAiH;AACjH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,OAAO,CASxF;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,YAAY,EAAE,CAGzG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,SAAI,GAAG,UAAU,CAiBlI;AAGD,wBAAgB,sBAAsB,IAAI;IAAE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CA4C3H"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MULTI-OBJECTIVE — real problems rarely have ONE goal. A pharma formulation must be more POTENT *and* more
|
|
3
|
+
* STABLE *and* cheaper; a fraud model must catch more fraud *and* decline fewer good customers. These trade
|
|
4
|
+
* off — there is no single best, but a PARETO FRONT of best-possible compromises.
|
|
5
|
+
*
|
|
6
|
+
* MULTI-OBJECTIVE finds that front from hand-measured results: you score each experiment on N objectives,
|
|
7
|
+
* and Melete (a) computes the exact non-dominated set and (b) proposes the next experiment to widen the
|
|
8
|
+
* front, by scalarising the objectives with a deterministically-varying weight vector so successive
|
|
9
|
+
* proposals probe different trade-offs. Deterministic ⇒ reproducible + signable like every Melete run.
|
|
10
|
+
*
|
|
11
|
+
* Honest by construction (DIAKRISIS): the Pareto front (dominance) is EXACT. The proposer uses weighted-sum
|
|
12
|
+
* scalarisation with rotating weights — simple, robust, and it reliably spreads along the front; it is not
|
|
13
|
+
* guaranteed to recover points on a deeply CONCAVE front (a known limitation of linear scalarisation, the
|
|
14
|
+
* honest trade-off for a dependency-free deterministic engine). The front it reports is always exact.
|
|
15
|
+
*/
|
|
16
|
+
import { lcg } from "./space.js";
|
|
17
|
+
import { proposeNext } from "./interactive.js";
|
|
18
|
+
/** Does `a` Pareto-dominate `b` across all objectives (≥ in every one, > in at least one, in goal direction)? */
|
|
19
|
+
export function dominates(a, b, goals) {
|
|
20
|
+
let strictly = false;
|
|
21
|
+
for (let i = 0; i < goals.length; i++) {
|
|
22
|
+
const dir = goals[i].goal === "minimize" ? -1 : 1;
|
|
23
|
+
const av = dir * a[i], bv = dir * b[i];
|
|
24
|
+
if (av < bv)
|
|
25
|
+
return false; // worse on some objective → cannot dominate
|
|
26
|
+
if (av > bv)
|
|
27
|
+
strictly = true; // strictly better on at least one
|
|
28
|
+
}
|
|
29
|
+
return strictly;
|
|
30
|
+
}
|
|
31
|
+
/** The exact non-dominated set — the achievable best trade-offs. */
|
|
32
|
+
export function paretoFront(obs, goals) {
|
|
33
|
+
const valid = (obs ?? []).filter((o) => o && Array.isArray(o.values) && o.values.length === goals.length && o.values.every((v) => Number.isFinite(v)));
|
|
34
|
+
return valid.filter((o, i) => !valid.some((p, j) => j !== i && dominates(p.values, o.values, goals)));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Propose the next experiment to widen the Pareto front. Scalarises the N objectives with a weight vector
|
|
38
|
+
* that rotates with the run, so successive calls probe different corners of the trade-off space.
|
|
39
|
+
*/
|
|
40
|
+
export function proposeNextMulti(space, obs, goals, seed = 1) {
|
|
41
|
+
const valid = (obs ?? []).filter((o) => o && o.experiment && Array.isArray(o.values) && o.values.length === goals.length && o.values.every((v) => Number.isFinite(v)));
|
|
42
|
+
const t = valid.length;
|
|
43
|
+
if (t === 0 || goals.length === 0)
|
|
44
|
+
return proposeNext(space, [], "maximize", seed);
|
|
45
|
+
// deterministic rotating weights (a different trade-off each step)
|
|
46
|
+
const rnd = lcg(((seed >>> 0) || 1) + t * 131 + 7);
|
|
47
|
+
const w = goals.map(() => rnd() + 1e-3);
|
|
48
|
+
const wsum = w.reduce((a, b) => a + b, 0) || 1;
|
|
49
|
+
for (let i = 0; i < w.length; i++)
|
|
50
|
+
w[i] /= wsum;
|
|
51
|
+
// per-objective range for fair normalisation across different scales
|
|
52
|
+
const mins = goals.map((_, i) => Math.min(...valid.map((o) => o.values[i])));
|
|
53
|
+
const maxs = goals.map((_, i) => Math.max(...valid.map((o) => o.values[i])));
|
|
54
|
+
const scalar = (vals) => {
|
|
55
|
+
let s = 0;
|
|
56
|
+
for (let i = 0; i < goals.length; i++) {
|
|
57
|
+
const dir = goals[i].goal === "minimize" ? -1 : 1;
|
|
58
|
+
const rng = (maxs[i] - mins[i]) || 1;
|
|
59
|
+
s += w[i] * dir * (vals[i] - mins[i]) / rng;
|
|
60
|
+
}
|
|
61
|
+
return s;
|
|
62
|
+
};
|
|
63
|
+
const sObs = valid.map((o) => ({ experiment: o.experiment, value: scalar(o.values) }));
|
|
64
|
+
return proposeNext(space, sObs, "maximize", seed + t);
|
|
65
|
+
}
|
|
66
|
+
// ── gauntlet ──────────────────────────────────────────────────────────────────
|
|
67
|
+
export function multiObjectiveGauntlet() {
|
|
68
|
+
const goals = [{ name: "f1", goal: "maximize" }, { name: "f2", goal: "maximize" }];
|
|
69
|
+
// a clean trade-off: f1 peaks at x=2, f2 peaks at x=8 → Pareto front is x ∈ [2,8]
|
|
70
|
+
const space = { dims: [{ name: "x", type: "real", min: 0, max: 10 }] };
|
|
71
|
+
const f = (x) => [-((x - 2) ** 2), -((x - 8) ** 2)];
|
|
72
|
+
// DOMINATES: [2,2] dominates [1,1] (both maximise); neither dominates on a trade-off
|
|
73
|
+
const dom = dominates([2, 2], [1, 1], goals) === true && dominates([2, 1], [1, 2], goals) === false && dominates([1, 1], [2, 2], goals) === false;
|
|
74
|
+
// PARETO-FRONT: dominated points excluded
|
|
75
|
+
const pts = [
|
|
76
|
+
{ experiment: { x: 0 }, values: [-4, -64] }, // dominated
|
|
77
|
+
{ experiment: { x: 2 }, values: [0, -36] }, // on front (best f1)
|
|
78
|
+
{ experiment: { x: 5 }, values: [-9, -9] }, // on front (balanced)
|
|
79
|
+
{ experiment: { x: 8 }, values: [-36, 0] }, // on front (best f2)
|
|
80
|
+
{ experiment: { x: 5.0 }, values: [-16, -16] }, // dominated by x=5
|
|
81
|
+
];
|
|
82
|
+
const front = paretoFront(pts, goals);
|
|
83
|
+
const frontOK = front.length === 3 && front.some((o) => o.experiment.x === 2) && front.some((o) => o.experiment.x === 8) && !front.some((o) => o.experiment.x === 0);
|
|
84
|
+
// PROPOSE: valid in-bounds
|
|
85
|
+
const next = proposeNextMulti(space, pts, goals, 3);
|
|
86
|
+
const proposeOK = typeof next.x === "number" && next.x >= 0 && next.x <= 10;
|
|
87
|
+
// SPREAD: a guided multi-objective loop discovers a SPREAD of trade-offs (not one point)
|
|
88
|
+
const obs = [];
|
|
89
|
+
for (let i = 0; i < 50; i++) {
|
|
90
|
+
const e = proposeNextMulti(space, obs, goals, 7);
|
|
91
|
+
const v = f(e.x ?? 0);
|
|
92
|
+
obs.push({ experiment: e, values: v });
|
|
93
|
+
}
|
|
94
|
+
const fr = paretoFront(obs, goals);
|
|
95
|
+
const xs = fr.map((o) => o.experiment.x ?? 0);
|
|
96
|
+
const spread = (Math.max(...xs) - Math.min(...xs)) > 3 && fr.length >= 3; // front spans much of [2,8]
|
|
97
|
+
// MIXED goals (one max, one min) works
|
|
98
|
+
const mixed = [{ goal: "maximize" }, { goal: "minimize" }];
|
|
99
|
+
const mdom = dominates([5, 1], [4, 2], mixed) === true; // higher f1 + lower f2 dominates
|
|
100
|
+
// DETERMINISTIC
|
|
101
|
+
const det = JSON.stringify(proposeNextMulti(space, pts, goals, 9)) === JSON.stringify(proposeNextMulti(space, pts, goals, 9));
|
|
102
|
+
// TOTAL
|
|
103
|
+
const total = (() => { try {
|
|
104
|
+
paretoFront(null, goals);
|
|
105
|
+
proposeNextMulti(space, null, goals);
|
|
106
|
+
dominates([], [], []);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
} })();
|
|
112
|
+
const checks = [
|
|
113
|
+
{ name: "DOMINANCE", pass: dom, detail: "Pareto-dominance is correct (strictly-better-in-one, not-worse-in-any); trade-offs do not dominate" },
|
|
114
|
+
{ name: "PARETO-FRONT-EXACT", pass: frontOK, detail: `the non-dominated set is exact (kept 3 front points, dropped the dominated ones)` },
|
|
115
|
+
{ name: "PROPOSE-VALID", pass: proposeOK, detail: "proposes a valid in-bounds next experiment" },
|
|
116
|
+
{ name: "SPREADS-THE-FRONT", pass: spread, detail: `a guided multi-objective loop discovers a spread of trade-offs (front size ${fr.length}, x-span ${(Math.max(...xs) - Math.min(...xs)).toFixed(1)})` },
|
|
117
|
+
{ name: "MIXED-MAX-MIN", pass: mdom, detail: "handles a mix of maximise + minimise objectives" },
|
|
118
|
+
{ name: "DETERMINISTIC", pass: det, detail: "same seed + history → same proposal" },
|
|
119
|
+
{ name: "TOTAL", pass: total, detail: "null / empty / mismatched inputs never throw" },
|
|
120
|
+
];
|
|
121
|
+
return { score: checks.every((c) => c.pass) ? 100 : 0, checks };
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=multiobjective.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiobjective.js","sourceRoot":"","sources":["../src/multiobjective.ts"],"names":[],"mappings":"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"}
|
package/dist/noise.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOISE — the replication advisor. Hand-measured scores are NOISY (a lab assay drifts, a taste test is
|
|
3
|
+
* subjective, a benchmark jitters). No simple optimizer tells you "that reading looks unreliable —
|
|
4
|
+
* re-measure it" or "your measurements are too noisy to trust this winner yet". NOISE does.
|
|
5
|
+
*
|
|
6
|
+
* It estimates the measurement noise σ from DISAGREEMENT between experiments that sit close together in
|
|
7
|
+
* the variable space: if two near-identical settings gave very different scores, that gap is noise (the
|
|
8
|
+
* response barely changed, so the difference is the meter wobbling). From σ it reports the signal-to-noise
|
|
9
|
+
* ratio, flags individual readings that deviate far from their neighbours (likely mis-measurements), and
|
|
10
|
+
* recommends whether to TRUST the result, RE-CHECK a flagged point, or REPLICATE measurements because the
|
|
11
|
+
* noise is drowning the signal.
|
|
12
|
+
*
|
|
13
|
+
* Honest by construction (DIAKRISIS): σ is estimated from near-neighbour pairs (it slightly over-counts any
|
|
14
|
+
* real local variation, so it is a conservative upper-ish bound); it needs enough close pairs and abstains
|
|
15
|
+
* to UNKNOWN otherwise. Decision support, not a guarantee — but the σ estimate is checkable: feed it data
|
|
16
|
+
* with a known injected noise and it recovers it (see the gauntlet).
|
|
17
|
+
*/
|
|
18
|
+
import { type Space, type Experiment } from "./space.js";
|
|
19
|
+
import { type Observation, type Goal } from "./engine.js";
|
|
20
|
+
export interface NoiseOutlier {
|
|
21
|
+
experiment: Experiment;
|
|
22
|
+
value: number;
|
|
23
|
+
deviation: number;
|
|
24
|
+
}
|
|
25
|
+
export interface NoiseReport {
|
|
26
|
+
n: number;
|
|
27
|
+
noiseSigma: number;
|
|
28
|
+
signalRange: number;
|
|
29
|
+
snr: number;
|
|
30
|
+
nearPairs: number;
|
|
31
|
+
outliers: NoiseOutlier[];
|
|
32
|
+
recommendation: "trust" | "recheck-flagged" | "replicate" | "unknown";
|
|
33
|
+
note: string;
|
|
34
|
+
}
|
|
35
|
+
/** Estimate measurement noise + flag unreliable readings from near-neighbour disagreement. */
|
|
36
|
+
export declare function analyzeNoise(obs: ReadonlyArray<Observation>, space: Space, _goal?: Goal, neighborFrac?: number): NoiseReport;
|
|
37
|
+
export declare function noiseGauntlet(): {
|
|
38
|
+
score: 0 | 100;
|
|
39
|
+
checks: Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
pass: boolean;
|
|
42
|
+
detail: string;
|
|
43
|
+
}>;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=noise.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noise.d.ts","sourceRoot":"","sources":["../src/noise.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAE1D,MAAM,WAAW,YAAY;IAAG,UAAU,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC1F,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,cAAc,EAAE,OAAO,GAAG,iBAAiB,GAAG,WAAW,GAAG,SAAS,CAAC;IACtE,IAAI,EAAE,MAAM,CAAC;CACd;AAOD,8FAA8F;AAC9F,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAE,IAAiB,EAAE,YAAY,SAAM,GAAG,WAAW,CAkDrI;AAKD,wBAAgB,aAAa,IAAI;IAAE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAiDlH"}
|
package/dist/noise.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
function norm(space, e) {
|
|
2
|
+
return space.dims.map((d) => { const lo = d.min ?? 0, hi = d.max ?? 1; const span = hi - lo || 1; return Math.max(0, Math.min(1, ((+e[d.name] || 0) - lo) / span)); });
|
|
3
|
+
}
|
|
4
|
+
const dist = (a, b) => { let s = 0; for (let i = 0; i < a.length; i++)
|
|
5
|
+
s += (a[i] - b[i]) ** 2; return Math.sqrt(s); };
|
|
6
|
+
/** Estimate measurement noise + flag unreliable readings from near-neighbour disagreement. */
|
|
7
|
+
export function analyzeNoise(obs, space, _goal = "maximize", neighborFrac = 0.1) {
|
|
8
|
+
const hist = (obs ?? []).filter((o) => o && o.experiment && Number.isFinite(o.value));
|
|
9
|
+
const n = hist.length;
|
|
10
|
+
if ((space?.dims?.length ?? 0) === 0 || n < 8) {
|
|
11
|
+
return { n, noiseSigma: 0, signalRange: 0, snr: 0, nearPairs: 0, outliers: [], recommendation: "unknown", note: `need ≈8+ measurements (have ${n})` };
|
|
12
|
+
}
|
|
13
|
+
const pts = hist.map((o) => norm(space, o.experiment));
|
|
14
|
+
const vals = hist.map((o) => o.value);
|
|
15
|
+
const vMin = Math.min(...vals), vMax = Math.max(...vals);
|
|
16
|
+
const signalRange = vMax - vMin;
|
|
17
|
+
// σ from the CLOSEST pairs: at small separation the response is ~flat, so the value gap is ~ noise.
|
|
18
|
+
// For two readings each with noise σ, Var(diff) = 2σ², so σ̂ = sqrt(mean(diff²)/2). Use the nearest pairs only.
|
|
19
|
+
const pairs = [];
|
|
20
|
+
for (let i = 0; i < n; i++)
|
|
21
|
+
for (let j = i + 1; j < n; j++) {
|
|
22
|
+
if (dist(pts[i], pts[j]) < neighborFrac)
|
|
23
|
+
pairs.push((vals[i] - vals[j]) ** 2);
|
|
24
|
+
}
|
|
25
|
+
// widen the radius if too few close pairs (sparse data)
|
|
26
|
+
let radius = neighborFrac;
|
|
27
|
+
while (pairs.length < 5 && radius < 0.6) {
|
|
28
|
+
radius += 0.1;
|
|
29
|
+
pairs.length = 0;
|
|
30
|
+
for (let i = 0; i < n; i++)
|
|
31
|
+
for (let j = i + 1; j < n; j++) {
|
|
32
|
+
if (dist(pts[i], pts[j]) < radius)
|
|
33
|
+
pairs.push((vals[i] - vals[j]) ** 2);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (pairs.length < 3) {
|
|
37
|
+
return { n, noiseSigma: 0, signalRange: +signalRange.toFixed(6), snr: 0, nearPairs: pairs.length, outliers: [], recommendation: "unknown", note: "samples too spread out to estimate noise — repeat a setting or sample closer together" };
|
|
38
|
+
}
|
|
39
|
+
// robust σ via the MEDIAN of squared near-pair gaps (one mis-measured reading can't poison it) with the
|
|
40
|
+
// χ²₁ median de-bias: E[median(diff²)] = 2σ²·0.45494, so σ̂ = sqrt(median / 0.90987).
|
|
41
|
+
const sorted = pairs.slice().sort((a, b) => a - b);
|
|
42
|
+
const m = sorted.length;
|
|
43
|
+
const median = m % 2 ? sorted[(m - 1) / 2] : (sorted[m / 2 - 1] + sorted[m / 2]) / 2;
|
|
44
|
+
const noiseSigma = Math.sqrt(median / 0.90987);
|
|
45
|
+
const snr = noiseSigma > 1e-12 ? signalRange / noiseSigma : Infinity;
|
|
46
|
+
// outliers: a reading far from the local mean of its CLOSE neighbours (tight radius keeps the trend out;
|
|
47
|
+
// 4σ threshold so ordinary noise is not mistaken for a mis-measurement)
|
|
48
|
+
const outliers = [];
|
|
49
|
+
if (noiseSigma > 1e-9) {
|
|
50
|
+
for (let i = 0; i < n; i++) {
|
|
51
|
+
const neigh = [];
|
|
52
|
+
for (let j = 0; j < n; j++) {
|
|
53
|
+
if (j === i)
|
|
54
|
+
continue;
|
|
55
|
+
if (dist(pts[i], pts[j]) < radius * 1.5)
|
|
56
|
+
neigh.push(vals[j]);
|
|
57
|
+
}
|
|
58
|
+
if (neigh.length >= 2) {
|
|
59
|
+
neigh.sort((a, b) => a - b);
|
|
60
|
+
const k = neigh.length;
|
|
61
|
+
const localMed = k % 2 ? neigh[(k - 1) / 2] : (neigh[k / 2 - 1] + neigh[k / 2]) / 2; // robust centre — a bad point can't drag it
|
|
62
|
+
const dev = Math.abs(vals[i] - localMed);
|
|
63
|
+
if (dev > 4 * noiseSigma)
|
|
64
|
+
outliers.push({ experiment: hist[i].experiment, value: vals[i], deviation: +dev.toFixed(4) });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
outliers.sort((a, b) => b.deviation - a.deviation); // worst first, so slice() keeps the real culprits
|
|
68
|
+
}
|
|
69
|
+
let recommendation;
|
|
70
|
+
let note;
|
|
71
|
+
if (noiseSigma > 0.15 * (signalRange || 1)) {
|
|
72
|
+
recommendation = "replicate";
|
|
73
|
+
note = `noise (σ≈${noiseSigma.toPrecision(3)}) is large vs the signal (SNR≈${snr.toFixed(1)}) — replicate measurements before trusting the winner`;
|
|
74
|
+
}
|
|
75
|
+
else if (outliers.length) {
|
|
76
|
+
recommendation = "recheck-flagged";
|
|
77
|
+
note = `${outliers.length} reading(s) look mis-measured (>3σ from neighbours) — re-check them`;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
recommendation = "trust";
|
|
81
|
+
note = `measurements look clean (σ≈${noiseSigma.toPrecision(3)}, SNR≈${snr.toFixed(1)})`;
|
|
82
|
+
}
|
|
83
|
+
return { n, noiseSigma: +noiseSigma.toFixed(6), signalRange: +signalRange.toFixed(6), snr: Number.isFinite(snr) ? +snr.toFixed(3) : 9999, nearPairs: pairs.length, outliers: outliers.slice(0, 5), recommendation, note };
|
|
84
|
+
}
|
|
85
|
+
// ── gauntlet ──────────────────────────────────────────────────────────────────
|
|
86
|
+
import { lcg } from "./space.js";
|
|
87
|
+
export function noiseGauntlet() {
|
|
88
|
+
const space = { dims: [{ name: "x", type: "real", min: 0, max: 10 }, { name: "y", type: "real", min: 0, max: 10 }] };
|
|
89
|
+
// deterministic Gaussian noise (Box–Muller) from the seeded RNG
|
|
90
|
+
const rnd = lcg(11);
|
|
91
|
+
const gauss = () => { const u1 = Math.max(1e-9, rnd()), u2 = rnd(); return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); };
|
|
92
|
+
// a nearly-flat response (so near-pair gaps are dominated by noise) + KNOWN noise σ = 0.30
|
|
93
|
+
const SIGMA = 0.30;
|
|
94
|
+
const flat = (e) => 5 + 0.05 * (e.x ?? 0); // very gentle slope
|
|
95
|
+
const noisy = [];
|
|
96
|
+
for (let i = 0; i < 120; i++) {
|
|
97
|
+
const e = { x: rnd() * 10, y: rnd() * 10 };
|
|
98
|
+
noisy.push({ experiment: e, value: flat(e) + SIGMA * gauss() });
|
|
99
|
+
}
|
|
100
|
+
const rN = analyzeNoise(noisy, space, "maximize");
|
|
101
|
+
// RECOVERS-NOISE: the estimate is within 2x of the injected σ (a real, falsifiable accuracy check)
|
|
102
|
+
const recovers = rN.noiseSigma > SIGMA * 0.5 && rN.noiseSigma < SIGMA * 2;
|
|
103
|
+
// a clean (noiseless) smooth response → σ̂ ≈ 0
|
|
104
|
+
const clean = [];
|
|
105
|
+
const rnd2 = lcg(3);
|
|
106
|
+
for (let i = 0; i < 120; i++) {
|
|
107
|
+
const e = { x: rnd2() * 10, y: rnd2() * 10 };
|
|
108
|
+
clean.push({ experiment: e, value: 5 + 0.05 * (e.x ?? 0) });
|
|
109
|
+
}
|
|
110
|
+
const rC = analyzeNoise(clean, space, "maximize");
|
|
111
|
+
const cleanLow = rC.noiseSigma < 0.05 && rC.recommendation === "trust";
|
|
112
|
+
// OUTLIER: inject one wildly-off reading into the clean set → it is flagged
|
|
113
|
+
const withOut = clean.slice();
|
|
114
|
+
withOut.push({ experiment: { x: 5, y: 5 }, value: 999 });
|
|
115
|
+
const rO = analyzeNoise(withOut, space, "maximize");
|
|
116
|
+
const flagsOutlier = rO.outliers.some((o) => o.value === 999);
|
|
117
|
+
// REPLICATE advice when noise is large vs signal (flat response + big noise)
|
|
118
|
+
const veryNoisy = [];
|
|
119
|
+
const rnd3 = lcg(5);
|
|
120
|
+
for (let i = 0; i < 120; i++) {
|
|
121
|
+
const e = { x: rnd3() * 10, y: rnd3() * 10 };
|
|
122
|
+
veryNoisy.push({ experiment: e, value: 5 + 1.5 * (Math.sqrt(-2 * Math.log(Math.max(1e-9, rnd3()))) * Math.cos(2 * Math.PI * rnd3())) });
|
|
123
|
+
}
|
|
124
|
+
const rV = analyzeNoise(veryNoisy, space, "maximize");
|
|
125
|
+
const advisesReplicate = rV.recommendation === "replicate";
|
|
126
|
+
const det = JSON.stringify(analyzeNoise(noisy, space, "maximize")) === JSON.stringify(analyzeNoise(noisy, space, "maximize"));
|
|
127
|
+
const thin = analyzeNoise(noisy.slice(0, 4), space, "maximize");
|
|
128
|
+
const abstains = thin.recommendation === "unknown";
|
|
129
|
+
const total = (() => { try {
|
|
130
|
+
analyzeNoise(null, space);
|
|
131
|
+
analyzeNoise([], space);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return false;
|
|
136
|
+
} })();
|
|
137
|
+
const checks = [
|
|
138
|
+
{ name: "RECOVERS-INJECTED-NOISE", pass: recovers, detail: `injected σ=${SIGMA}; estimated σ=${rN.noiseSigma} (within 2x = accurate)` },
|
|
139
|
+
{ name: "CLEAN-IS-LOW", pass: cleanLow, detail: `noiseless data → σ≈${rC.noiseSigma} and "trust"` },
|
|
140
|
+
{ name: "FLAGS-OUTLIER", pass: flagsOutlier, detail: "a 999 reading among clean data is flagged as mis-measured" },
|
|
141
|
+
{ name: "ADVISES-REPLICATE", pass: advisesReplicate, detail: `large noise vs signal → recommends replicate (got "${rV.recommendation}")` },
|
|
142
|
+
{ name: "DETERMINISTIC", pass: det, detail: "same data → same report" },
|
|
143
|
+
{ name: "ABSTAINS-WHEN-THIN", pass: abstains, detail: "too few measurements → UNKNOWN" },
|
|
144
|
+
{ name: "TOTAL", pass: total, detail: "null / empty never throws" },
|
|
145
|
+
];
|
|
146
|
+
return { score: checks.every((c) => c.pass) ? 100 : 0, checks };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=noise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noise.js","sourceRoot":"","sources":["../src/noise.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🛰 NOISE-ROBUST DISCOVERY — the engine that doesn't get fooled by luck.
|
|
3
|
+
*
|
|
4
|
+
* Every ordinary optimizer trusts the single highest reading it ever saw. In a deterministic lab that's fine.
|
|
5
|
+
* But run Melete as a 24/7 service on a real system — a satellite link in a solar storm, a database under a
|
|
6
|
+
* traffic spike, an assay with batch-to-batch drift — and the measurements are NOISY: the SAME setting can
|
|
7
|
+
* read 99% one second and 40% the next. A naive optimizer locks onto a setting that got one lucky high
|
|
8
|
+
* reading and then collapses in production. That is the single most expensive failure mode in real Bayesian
|
|
9
|
+
* optimization.
|
|
10
|
+
*
|
|
11
|
+
* NOISE-ROBUST fixes it the honest way:
|
|
12
|
+
* 1. REPLICATE — it re-measures each candidate several times to estimate not just the mean μ but the
|
|
13
|
+
* spread σ. Noise is HETEROSCEDASTIC (different in different regions), so σ is estimated PER POINT from
|
|
14
|
+
* that point's own replicates — never assumed global.
|
|
15
|
+
* 2. RACE (LUCB) — it spends extra measurements where it matters: tightening the confidence interval of the
|
|
16
|
+
* current leader and its closest challenger, so the winner is decided by evidence, not by a single fluke.
|
|
17
|
+
* 3. SELECT BY TRUST — the winner is the point with the highest LOWER confidence bound (μ − z·σ/√n): the
|
|
18
|
+
* value you can actually rely on. A lucky spike with huge σ has a low LCB and loses; a genuinely good,
|
|
19
|
+
* quiet setting wins. It also reports the "lucky max" (the naive answer) it rejected and a per-point risk
|
|
20
|
+
* band, so a human/dashboard can see the noise it filtered.
|
|
21
|
+
*
|
|
22
|
+
* Honest by construction (DIAKRISIS): σ is measured from real replicates, not modelled from a prior; the
|
|
23
|
+
* guarantee is statistical (it needs a few replicates per point) and the gauntlet proves it on a deliberately
|
|
24
|
+
* noisy landscape where a high-variance trap occasionally out-reads the true optimum — NOISE-ROBUST picks the
|
|
25
|
+
* trustworthy optimum ≥97.5% of seeds while a naive max-picker is fooled most of the time. Distinct from
|
|
26
|
+
* AEGIS (which is robust to INPUT wobble / landscape geometry); this is robust to OUTPUT measurement noise.
|
|
27
|
+
*/
|
|
28
|
+
import { type Space, type Experiment } from "./space.js";
|
|
29
|
+
import { type Observation, type Goal } from "./engine.js";
|
|
30
|
+
export interface RobustPoint {
|
|
31
|
+
experiment: Experiment;
|
|
32
|
+
mean: number;
|
|
33
|
+
std: number;
|
|
34
|
+
n: number;
|
|
35
|
+
lcb: number;
|
|
36
|
+
ucb: number;
|
|
37
|
+
}
|
|
38
|
+
export interface NoiseRobustResult {
|
|
39
|
+
best: Observation;
|
|
40
|
+
bestMean: number;
|
|
41
|
+
bestStd: number;
|
|
42
|
+
bestN: number;
|
|
43
|
+
bestLcb: number;
|
|
44
|
+
luckyMax: Observation;
|
|
45
|
+
rejectedLucky: boolean;
|
|
46
|
+
noiseFiltered: number;
|
|
47
|
+
points: RobustPoint[];
|
|
48
|
+
evaluations: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Noise-robust discovery on a stochastic oracle. `replicates` = initial measurements per candidate (≥3);
|
|
52
|
+
* `z` = confidence multiplier for the lower bound (higher = more conservative / trust-demanding).
|
|
53
|
+
*/
|
|
54
|
+
export declare function noiseRobustDiscover(opts: {
|
|
55
|
+
space: Space;
|
|
56
|
+
oracle: (e: Experiment) => number;
|
|
57
|
+
budget: number;
|
|
58
|
+
goal?: Goal;
|
|
59
|
+
seed?: number;
|
|
60
|
+
z?: number;
|
|
61
|
+
replicates?: number;
|
|
62
|
+
}): NoiseRobustResult;
|
|
63
|
+
export declare function noiseRobustGauntlet(): {
|
|
64
|
+
score: 0 | 100;
|
|
65
|
+
checks: Array<{
|
|
66
|
+
name: string;
|
|
67
|
+
pass: boolean;
|
|
68
|
+
detail: string;
|
|
69
|
+
}>;
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=noiserobust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noiserobust.d.ts","sourceRoot":"","sources":["../src/noiserobust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,UAAU,EAAO,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAM1D,MAAM,WAAW,WAAW;IAAG,UAAU,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;CAAE;AACxH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAClE,QAAQ,EAAE,WAAW,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAgE7L;AAOD,wBAAgB,mBAAmB,IAAI;IAAE,KAAK,EAAE,CAAC,GAAG,GAAG,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAuDxH"}
|