@almadar/evaluator 2.0.0 → 2.1.0
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.
|
@@ -49,6 +49,19 @@ interface EvaluationContext {
|
|
|
49
49
|
* Helps detect typos and missing entity fields early.
|
|
50
50
|
*/
|
|
51
51
|
strictBindings?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Set by prob/condition when a predicate fails during inference.
|
|
54
|
+
* Checked by prob/posterior and prob/infer to reject samples.
|
|
55
|
+
*/
|
|
56
|
+
_probRejected?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Seeded PRNG state for deterministic probabilistic sampling.
|
|
59
|
+
* Stored as a mutable object so child contexts share the same state.
|
|
60
|
+
* Set by prob/seed.
|
|
61
|
+
*/
|
|
62
|
+
_probSeed?: {
|
|
63
|
+
state: number;
|
|
64
|
+
};
|
|
52
65
|
/** Mutate entity fields */
|
|
53
66
|
mutateEntity?: (changes: Record<string, unknown>) => void;
|
|
54
67
|
/** Emit an event */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SExpr } from '@almadar/core';
|
|
2
2
|
export { CORE_BINDINGS, CoreBinding, Expression, ExpressionSchema, ParsedBinding, SExpr, SExprAtom, SExprSchema, collectBindings, getArgs, getOperator, isBinding, isSExpr, isSExprAtom, isSExprCall, isValidBinding, parseBinding, sexpr, walkSExpr } from '@almadar/core';
|
|
3
|
-
import { E as EvaluationContext } from './index-
|
|
4
|
-
export { c as createChildContext, a as createEffectContext, b as createMinimalContext, e as evalAbs, d as evalAdd, f as evalAnd, g as evalCallService, h as evalCeil, i as evalClamp, j as evalConcat, k as evalCount, l as evalDecrement, m as evalDespawn, n as evalDivide, o as evalDo, p as evalEmit, q as evalEmpty, r as evalEqual, s as evalFilter, t as evalFind, u as evalFirst, v as evalFloor, w as evalFn, x as evalGreaterThan, y as evalGreaterThanOrEqual, z as evalIf, A as evalIncludes, B as evalIncrement, C as evalLast, D as evalLessThan, F as evalLessThanOrEqual, G as evalLet, H as evalMap, I as evalMatches, J as evalMax, K as evalMin, L as evalModulo, M as evalMultiply, N as evalNavigate, O as evalNot, P as evalNotEqual, Q as evalNotify, R as evalNth, S as evalOr, T as evalPersist, U as evalRenderUI, V as evalRound, W as evalSet, X as evalSetDynamic, Y as evalSpawn, Z as evalSubtract, _ as evalSum, $ as evalWhen, a0 as resolveBinding } from './index-
|
|
3
|
+
import { E as EvaluationContext } from './index-DBM7Xkm3.js';
|
|
4
|
+
export { c as createChildContext, a as createEffectContext, b as createMinimalContext, e as evalAbs, d as evalAdd, f as evalAnd, g as evalCallService, h as evalCeil, i as evalClamp, j as evalConcat, k as evalCount, l as evalDecrement, m as evalDespawn, n as evalDivide, o as evalDo, p as evalEmit, q as evalEmpty, r as evalEqual, s as evalFilter, t as evalFind, u as evalFirst, v as evalFloor, w as evalFn, x as evalGreaterThan, y as evalGreaterThanOrEqual, z as evalIf, A as evalIncludes, B as evalIncrement, C as evalLast, D as evalLessThan, F as evalLessThanOrEqual, G as evalLet, H as evalMap, I as evalMatches, J as evalMax, K as evalMin, L as evalModulo, M as evalMultiply, N as evalNavigate, O as evalNot, P as evalNotEqual, Q as evalNotify, R as evalNth, S as evalOr, T as evalPersist, U as evalRenderUI, V as evalRound, W as evalSet, X as evalSetDynamic, Y as evalSpawn, Z as evalSubtract, _ as evalSum, $ as evalWhen, a0 as resolveBinding } from './index-DBM7Xkm3.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* S-Expression Evaluator
|
package/dist/index.js
CHANGED
|
@@ -2101,6 +2101,224 @@ async function evalAsyncSequence(args, evaluate2, ctx) {
|
|
|
2101
2101
|
return results;
|
|
2102
2102
|
}
|
|
2103
2103
|
|
|
2104
|
+
// std/prob.ts
|
|
2105
|
+
function mulberry32(seed) {
|
|
2106
|
+
let t = seed.state += 1831565813;
|
|
2107
|
+
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
2108
|
+
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
2109
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
2110
|
+
}
|
|
2111
|
+
function getRandom(ctx) {
|
|
2112
|
+
if (ctx._probSeed) {
|
|
2113
|
+
return mulberry32(ctx._probSeed);
|
|
2114
|
+
}
|
|
2115
|
+
return Math.random();
|
|
2116
|
+
}
|
|
2117
|
+
function gammaVariate(shape, ctx) {
|
|
2118
|
+
if (shape < 1) {
|
|
2119
|
+
const u = getRandom(ctx);
|
|
2120
|
+
return gammaVariate(shape + 1, ctx) * Math.pow(u, 1 / shape);
|
|
2121
|
+
}
|
|
2122
|
+
const d = shape - 1 / 3;
|
|
2123
|
+
const c = 1 / Math.sqrt(9 * d);
|
|
2124
|
+
for (; ; ) {
|
|
2125
|
+
let x;
|
|
2126
|
+
let v;
|
|
2127
|
+
do {
|
|
2128
|
+
x = gaussianStandard(ctx);
|
|
2129
|
+
v = 1 + c * x;
|
|
2130
|
+
} while (v <= 0);
|
|
2131
|
+
v = v * v * v;
|
|
2132
|
+
const u = getRandom(ctx);
|
|
2133
|
+
if (u < 1 - 0.0331 * (x * x) * (x * x)) {
|
|
2134
|
+
return d * v;
|
|
2135
|
+
}
|
|
2136
|
+
if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v))) {
|
|
2137
|
+
return d * v;
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
function gaussianStandard(ctx) {
|
|
2142
|
+
const u1 = getRandom(ctx);
|
|
2143
|
+
const u2 = getRandom(ctx);
|
|
2144
|
+
return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
|
2145
|
+
}
|
|
2146
|
+
function evalProbSeed(args, evaluate2, ctx) {
|
|
2147
|
+
const n = evaluate2(args[0], ctx);
|
|
2148
|
+
ctx._probSeed = { state: n | 0 };
|
|
2149
|
+
}
|
|
2150
|
+
function evalProbFlip(args, evaluate2, ctx) {
|
|
2151
|
+
const p = evaluate2(args[0], ctx);
|
|
2152
|
+
return getRandom(ctx) < p;
|
|
2153
|
+
}
|
|
2154
|
+
function evalProbGaussian(args, evaluate2, ctx) {
|
|
2155
|
+
const mu = evaluate2(args[0], ctx);
|
|
2156
|
+
const sigma = evaluate2(args[1], ctx);
|
|
2157
|
+
return mu + sigma * gaussianStandard(ctx);
|
|
2158
|
+
}
|
|
2159
|
+
function evalProbUniform(args, evaluate2, ctx) {
|
|
2160
|
+
const lo = evaluate2(args[0], ctx);
|
|
2161
|
+
const hi = evaluate2(args[1], ctx);
|
|
2162
|
+
return lo + getRandom(ctx) * (hi - lo);
|
|
2163
|
+
}
|
|
2164
|
+
function evalProbBeta(args, evaluate2, ctx) {
|
|
2165
|
+
const alpha = evaluate2(args[0], ctx);
|
|
2166
|
+
const beta = evaluate2(args[1], ctx);
|
|
2167
|
+
const x = gammaVariate(alpha, ctx);
|
|
2168
|
+
const y = gammaVariate(beta, ctx);
|
|
2169
|
+
return x / (x + y);
|
|
2170
|
+
}
|
|
2171
|
+
function evalProbCategorical(args, evaluate2, ctx) {
|
|
2172
|
+
const items = evaluate2(args[0], ctx);
|
|
2173
|
+
const weights = evaluate2(args[1], ctx);
|
|
2174
|
+
const totalWeight = weights.reduce((sum, w) => sum + w, 0);
|
|
2175
|
+
let r = getRandom(ctx) * totalWeight;
|
|
2176
|
+
for (let i = 0; i < items.length; i++) {
|
|
2177
|
+
r -= weights[i];
|
|
2178
|
+
if (r <= 0) return items[i];
|
|
2179
|
+
}
|
|
2180
|
+
return items[items.length - 1];
|
|
2181
|
+
}
|
|
2182
|
+
function evalProbPoisson(args, evaluate2, ctx) {
|
|
2183
|
+
const lambda = evaluate2(args[0], ctx);
|
|
2184
|
+
const limit = Math.exp(-lambda);
|
|
2185
|
+
let k = 0;
|
|
2186
|
+
let p = 1;
|
|
2187
|
+
do {
|
|
2188
|
+
k++;
|
|
2189
|
+
p *= getRandom(ctx);
|
|
2190
|
+
} while (p > limit);
|
|
2191
|
+
return k - 1;
|
|
2192
|
+
}
|
|
2193
|
+
function evalProbCondition(args, evaluate2, ctx) {
|
|
2194
|
+
const predicate = evaluate2(args[0], ctx);
|
|
2195
|
+
if (!predicate) {
|
|
2196
|
+
ctx._probRejected = true;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
function evalProbSample(args, evaluate2, ctx) {
|
|
2200
|
+
const n = evaluate2(args[0], ctx);
|
|
2201
|
+
const exprAst = args[1];
|
|
2202
|
+
const results = [];
|
|
2203
|
+
for (let i = 0; i < n; i++) {
|
|
2204
|
+
results.push(evaluate2(exprAst, ctx));
|
|
2205
|
+
}
|
|
2206
|
+
return results;
|
|
2207
|
+
}
|
|
2208
|
+
function evalProbPosterior(args, evaluate2, ctx) {
|
|
2209
|
+
const modelAst = args[0];
|
|
2210
|
+
const evidenceAst = args[1];
|
|
2211
|
+
const queryAst = args[2];
|
|
2212
|
+
const n = evaluate2(args[3], ctx);
|
|
2213
|
+
const results = [];
|
|
2214
|
+
for (let i = 0; i < n; i++) {
|
|
2215
|
+
const sampleEntity = { ...ctx.entity };
|
|
2216
|
+
const sampleCtx = {
|
|
2217
|
+
...ctx,
|
|
2218
|
+
entity: sampleEntity,
|
|
2219
|
+
_probRejected: false,
|
|
2220
|
+
mutateEntity: (changes) => {
|
|
2221
|
+
Object.assign(sampleEntity, changes);
|
|
2222
|
+
}
|
|
2223
|
+
};
|
|
2224
|
+
evaluate2(modelAst, sampleCtx);
|
|
2225
|
+
if (sampleCtx._probRejected) continue;
|
|
2226
|
+
const evidenceResult = evaluate2(evidenceAst, sampleCtx);
|
|
2227
|
+
if (!evidenceResult) continue;
|
|
2228
|
+
results.push(evaluate2(queryAst, sampleCtx));
|
|
2229
|
+
}
|
|
2230
|
+
return results;
|
|
2231
|
+
}
|
|
2232
|
+
function evalProbInfer(args, evaluate2, ctx) {
|
|
2233
|
+
const modelAst = args[0];
|
|
2234
|
+
const evidenceAst = args[1];
|
|
2235
|
+
const queryAst = args[2];
|
|
2236
|
+
const n = evaluate2(args[3], ctx);
|
|
2237
|
+
const accepted = [];
|
|
2238
|
+
for (let i = 0; i < n; i++) {
|
|
2239
|
+
const sampleEntity = { ...ctx.entity };
|
|
2240
|
+
const sampleCtx = {
|
|
2241
|
+
...ctx,
|
|
2242
|
+
entity: sampleEntity,
|
|
2243
|
+
_probRejected: false,
|
|
2244
|
+
mutateEntity: (changes) => {
|
|
2245
|
+
Object.assign(sampleEntity, changes);
|
|
2246
|
+
}
|
|
2247
|
+
};
|
|
2248
|
+
evaluate2(modelAst, sampleCtx);
|
|
2249
|
+
if (sampleCtx._probRejected) continue;
|
|
2250
|
+
const evidenceResult = evaluate2(evidenceAst, sampleCtx);
|
|
2251
|
+
if (!evidenceResult) continue;
|
|
2252
|
+
const queryVal = evaluate2(queryAst, sampleCtx);
|
|
2253
|
+
accepted.push(queryVal);
|
|
2254
|
+
}
|
|
2255
|
+
const count = accepted.length;
|
|
2256
|
+
if (count === 0) {
|
|
2257
|
+
return { mean: 0, variance: 0, samples: [], acceptRate: 0 };
|
|
2258
|
+
}
|
|
2259
|
+
const mean = accepted.reduce((s, v) => s + v, 0) / count;
|
|
2260
|
+
const variance = accepted.reduce((s, v) => s + (v - mean) ** 2, 0) / count;
|
|
2261
|
+
return {
|
|
2262
|
+
mean,
|
|
2263
|
+
variance,
|
|
2264
|
+
samples: accepted,
|
|
2265
|
+
acceptRate: count / n
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
function evalProbExpectedValue(args, evaluate2, ctx) {
|
|
2269
|
+
const samples = evaluate2(args[0], ctx);
|
|
2270
|
+
if (samples.length === 0) return 0;
|
|
2271
|
+
return samples.reduce((s, v) => s + v, 0) / samples.length;
|
|
2272
|
+
}
|
|
2273
|
+
function evalProbVariance(args, evaluate2, ctx) {
|
|
2274
|
+
const samples = evaluate2(args[0], ctx);
|
|
2275
|
+
if (samples.length === 0) return 0;
|
|
2276
|
+
const mean = samples.reduce((s, v) => s + v, 0) / samples.length;
|
|
2277
|
+
return samples.reduce((s, v) => s + (v - mean) ** 2, 0) / samples.length;
|
|
2278
|
+
}
|
|
2279
|
+
function evalProbHistogram(args, evaluate2, ctx) {
|
|
2280
|
+
const samples = evaluate2(args[0], ctx);
|
|
2281
|
+
const bins = evaluate2(args[1], ctx);
|
|
2282
|
+
if (samples.length === 0) {
|
|
2283
|
+
return { binEdges: [], counts: [] };
|
|
2284
|
+
}
|
|
2285
|
+
const min = Math.min(...samples);
|
|
2286
|
+
const max = Math.max(...samples);
|
|
2287
|
+
const binWidth = (max - min) / bins || 1;
|
|
2288
|
+
const binEdges = [];
|
|
2289
|
+
const counts = new Array(bins).fill(0);
|
|
2290
|
+
for (let i = 0; i <= bins; i++) {
|
|
2291
|
+
binEdges.push(min + i * binWidth);
|
|
2292
|
+
}
|
|
2293
|
+
for (const s of samples) {
|
|
2294
|
+
let idx = Math.floor((s - min) / binWidth);
|
|
2295
|
+
if (idx >= bins) idx = bins - 1;
|
|
2296
|
+
counts[idx]++;
|
|
2297
|
+
}
|
|
2298
|
+
return { binEdges, counts };
|
|
2299
|
+
}
|
|
2300
|
+
function evalProbPercentile(args, evaluate2, ctx) {
|
|
2301
|
+
const samples = evaluate2(args[0], ctx);
|
|
2302
|
+
const p = evaluate2(args[1], ctx);
|
|
2303
|
+
if (samples.length === 0) return 0;
|
|
2304
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
2305
|
+
const idx = p / 100 * (sorted.length - 1);
|
|
2306
|
+
const lo = Math.floor(idx);
|
|
2307
|
+
const hi = Math.ceil(idx);
|
|
2308
|
+
if (lo === hi) return sorted[lo];
|
|
2309
|
+
const frac = idx - lo;
|
|
2310
|
+
return sorted[lo] * (1 - frac) + sorted[hi] * frac;
|
|
2311
|
+
}
|
|
2312
|
+
function evalProbCredibleInterval(args, evaluate2, ctx) {
|
|
2313
|
+
const samples = evaluate2(args[0], ctx);
|
|
2314
|
+
const alpha = evaluate2(args[1], ctx);
|
|
2315
|
+
if (samples.length === 0) return [0, 0];
|
|
2316
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
2317
|
+
const loIdx = Math.floor(alpha / 2 * (sorted.length - 1));
|
|
2318
|
+
const hiIdx = Math.ceil((1 - alpha / 2) * (sorted.length - 1));
|
|
2319
|
+
return [sorted[loIdx], sorted[hiIdx]];
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2104
2322
|
// SExpressionEvaluator.ts
|
|
2105
2323
|
var jitCache = /* @__PURE__ */ new Map();
|
|
2106
2324
|
var MAX_JIT_CACHE_SIZE = 1e3;
|
|
@@ -2666,6 +2884,43 @@ var SExpressionEvaluator = class {
|
|
|
2666
2884
|
return evalAsyncAll(args, evaluate2, ctx);
|
|
2667
2885
|
case "async/sequence":
|
|
2668
2886
|
return evalAsyncSequence(args, evaluate2, ctx);
|
|
2887
|
+
// ===============================
|
|
2888
|
+
// Standard Library: prob/*
|
|
2889
|
+
// ===============================
|
|
2890
|
+
case "prob/seed":
|
|
2891
|
+
evalProbSeed(args, evaluate2, ctx);
|
|
2892
|
+
return void 0;
|
|
2893
|
+
case "prob/flip":
|
|
2894
|
+
return evalProbFlip(args, evaluate2, ctx);
|
|
2895
|
+
case "prob/gaussian":
|
|
2896
|
+
return evalProbGaussian(args, evaluate2, ctx);
|
|
2897
|
+
case "prob/uniform":
|
|
2898
|
+
return evalProbUniform(args, evaluate2, ctx);
|
|
2899
|
+
case "prob/beta":
|
|
2900
|
+
return evalProbBeta(args, evaluate2, ctx);
|
|
2901
|
+
case "prob/categorical":
|
|
2902
|
+
return evalProbCategorical(args, evaluate2, ctx);
|
|
2903
|
+
case "prob/poisson":
|
|
2904
|
+
return evalProbPoisson(args, evaluate2, ctx);
|
|
2905
|
+
case "prob/condition":
|
|
2906
|
+
evalProbCondition(args, evaluate2, ctx);
|
|
2907
|
+
return void 0;
|
|
2908
|
+
case "prob/sample":
|
|
2909
|
+
return evalProbSample(args, evaluate2, ctx);
|
|
2910
|
+
case "prob/posterior":
|
|
2911
|
+
return evalProbPosterior(args, evaluate2, ctx);
|
|
2912
|
+
case "prob/infer":
|
|
2913
|
+
return evalProbInfer(args, evaluate2, ctx);
|
|
2914
|
+
case "prob/expected-value":
|
|
2915
|
+
return evalProbExpectedValue(args, evaluate2, ctx);
|
|
2916
|
+
case "prob/variance":
|
|
2917
|
+
return evalProbVariance(args, evaluate2, ctx);
|
|
2918
|
+
case "prob/histogram":
|
|
2919
|
+
return evalProbHistogram(args, evaluate2, ctx);
|
|
2920
|
+
case "prob/percentile":
|
|
2921
|
+
return evalProbPercentile(args, evaluate2, ctx);
|
|
2922
|
+
case "prob/credible-interval":
|
|
2923
|
+
return evalProbCredibleInterval(args, evaluate2, ctx);
|
|
2669
2924
|
default:
|
|
2670
2925
|
console.warn(`Unknown operator: ${op}`);
|
|
2671
2926
|
return void 0;
|