@yipe/dice 0.1.4 → 0.1.6
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/dist/index.cjs +129 -129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +129 -129
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ var __defProp = Object.defineProperty;
|
|
|
4
4
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
5
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
6
|
|
|
7
|
-
// src/lru-cache.ts
|
|
7
|
+
// src/common/lru-cache.ts
|
|
8
8
|
var LRUCache = class {
|
|
9
9
|
constructor(maxSize = 1e3) {
|
|
10
10
|
this.maxSize = maxSize;
|
|
@@ -46,10 +46,10 @@ var LRUCache = class {
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
// src/types.ts
|
|
49
|
+
// src/common/types.ts
|
|
50
50
|
var EPS = 1e-12;
|
|
51
51
|
|
|
52
|
-
// src/query.ts
|
|
52
|
+
// src/pmf/query.ts
|
|
53
53
|
var _DiceQuery = class _DiceQuery {
|
|
54
54
|
constructor(singles, combined, eps = EPS) {
|
|
55
55
|
__publicField(this, "singles");
|
|
@@ -1911,7 +1911,7 @@ var _PMF = class _PMF {
|
|
|
1911
1911
|
* optionally guarantees at least `minBins` survivors by adding top-K.
|
|
1912
1912
|
* Returns a new, non-normalized PMF.
|
|
1913
1913
|
*/
|
|
1914
|
-
|
|
1914
|
+
prune(epsRel, minBins = 0) {
|
|
1915
1915
|
const size = this.map.size;
|
|
1916
1916
|
if (size === 0) return this;
|
|
1917
1917
|
let peak = 0;
|
|
@@ -1923,7 +1923,7 @@ var _PMF = class _PMF {
|
|
|
1923
1923
|
if (dmg > maxDamage) maxDamage = dmg;
|
|
1924
1924
|
}
|
|
1925
1925
|
if (peak === 0)
|
|
1926
|
-
return new _PMF(new Map(this.map),
|
|
1926
|
+
return new _PMF(new Map(this.map), epsRel, false, this.identifier);
|
|
1927
1927
|
const thresh = epsRel * peak;
|
|
1928
1928
|
const entries = [...this.map.entries()];
|
|
1929
1929
|
const survivorsByDmg = /* @__PURE__ */ new Map();
|
|
@@ -1964,7 +1964,7 @@ var _PMF = class _PMF {
|
|
|
1964
1964
|
}
|
|
1965
1965
|
prunedMap.set(dmg, { p: bin.p, count: newCount, attr: newAttr });
|
|
1966
1966
|
}
|
|
1967
|
-
return new _PMF(prunedMap,
|
|
1967
|
+
return new _PMF(prunedMap, epsRel, false, `prune(${this.identifier})`);
|
|
1968
1968
|
}
|
|
1969
1969
|
/** NEW - REVIEW IF THESE ARE USEFUL OR DUPLCIATIVE? */
|
|
1970
1970
|
/** Probability mass at exactly x. */
|
|
@@ -2188,128 +2188,7 @@ var _PMF = class _PMF {
|
|
|
2188
2188
|
__publicField(_PMF, "__anonIdCounter", 1);
|
|
2189
2189
|
var PMF = _PMF;
|
|
2190
2190
|
|
|
2191
|
-
// src/
|
|
2192
|
-
var Mixture = class _Mixture {
|
|
2193
|
-
constructor(eps = EPS) {
|
|
2194
|
-
__publicField(this, "totals", /* @__PURE__ */ new Map());
|
|
2195
|
-
// raw mass per outcome (pre-normalization)
|
|
2196
|
-
__publicField(this, "labelMass", /* @__PURE__ */ new Map());
|
|
2197
|
-
// raw mass per outcome per label
|
|
2198
|
-
__publicField(this, "eps");
|
|
2199
|
-
this.eps = Number.isFinite(eps) ? eps : EPS;
|
|
2200
|
-
}
|
|
2201
|
-
/** Remove all accumulated state. */
|
|
2202
|
-
clear() {
|
|
2203
|
-
this.totals.clear();
|
|
2204
|
-
this.labelMass.clear();
|
|
2205
|
-
return this;
|
|
2206
|
-
}
|
|
2207
|
-
/** Number of distinct outcome values currently accumulated. */
|
|
2208
|
-
size() {
|
|
2209
|
-
return this.totals.size;
|
|
2210
|
-
}
|
|
2211
|
-
/** Whether a label was ever added. */
|
|
2212
|
-
hasLabel(label) {
|
|
2213
|
-
for (const bag of this.labelMass.values()) if (bag[label]) return true;
|
|
2214
|
-
return false;
|
|
2215
|
-
}
|
|
2216
|
-
/**
|
|
2217
|
-
* Add a labeled component with a mixture weight.
|
|
2218
|
-
* Weight can be any positive finite number. Very small contributions are pruned by eps.
|
|
2219
|
-
*/
|
|
2220
|
-
add(label, pmf, weight = 1) {
|
|
2221
|
-
if (!Number.isFinite(weight) || weight <= 0) return this;
|
|
2222
|
-
for (const [v, binOrNumber] of pmf) {
|
|
2223
|
-
const isNumber = typeof binOrNumber === "number";
|
|
2224
|
-
const p = isNumber ? binOrNumber : binOrNumber?.p ?? 0;
|
|
2225
|
-
if (p <= 0) continue;
|
|
2226
|
-
const add = weight * p;
|
|
2227
|
-
if (!Number.isFinite(add) || Math.abs(add) < this.eps) continue;
|
|
2228
|
-
this.totals.set(v, (this.totals.get(v) ?? 0) + add);
|
|
2229
|
-
const bag = this.labelMass.get(v) ?? {};
|
|
2230
|
-
bag[label] = (bag[label] ?? 0) + add;
|
|
2231
|
-
this.labelMass.set(v, bag);
|
|
2232
|
-
}
|
|
2233
|
-
return this;
|
|
2234
|
-
}
|
|
2235
|
-
buildPMF(eps = EPS) {
|
|
2236
|
-
let grand = 0;
|
|
2237
|
-
let c = 0;
|
|
2238
|
-
for (const m of this.totals.values()) {
|
|
2239
|
-
const y = m - c;
|
|
2240
|
-
const t = grand + y;
|
|
2241
|
-
c = t - grand - y;
|
|
2242
|
-
grand = t;
|
|
2243
|
-
}
|
|
2244
|
-
if (!(grand > 0)) throw new Error("Mixture: zero total mass");
|
|
2245
|
-
const internal = /* @__PURE__ */ new Map();
|
|
2246
|
-
for (const [v, m] of this.totals) {
|
|
2247
|
-
if (m <= 0 || Math.abs(m) < this.eps) continue;
|
|
2248
|
-
const count = this.labelMass.get(v) ?? {};
|
|
2249
|
-
internal.set(v, { p: m / grand, count });
|
|
2250
|
-
}
|
|
2251
|
-
return new PMF(internal, eps);
|
|
2252
|
-
}
|
|
2253
|
-
/**
|
|
2254
|
-
* Produce normalized *per-label* PMFs (labels independent).
|
|
2255
|
-
* These are unlabeled PMFs built from the raw mass of that label alone.
|
|
2256
|
-
*/
|
|
2257
|
-
byOutcome() {
|
|
2258
|
-
const labels = /* @__PURE__ */ new Set();
|
|
2259
|
-
for (const bag of this.labelMass.values()) {
|
|
2260
|
-
for (const k of Object.keys(bag)) labels.add(k);
|
|
2261
|
-
}
|
|
2262
|
-
const out = {};
|
|
2263
|
-
for (const label of labels) {
|
|
2264
|
-
const m = /* @__PURE__ */ new Map();
|
|
2265
|
-
for (const [v, bag] of this.labelMass) {
|
|
2266
|
-
const w = bag[label];
|
|
2267
|
-
if (w && Math.abs(w) >= this.eps) m.set(v, w);
|
|
2268
|
-
}
|
|
2269
|
-
if (m.size > 0) out[label] = PMF.fromMap(m, this.eps);
|
|
2270
|
-
}
|
|
2271
|
-
return out;
|
|
2272
|
-
}
|
|
2273
|
-
/**
|
|
2274
|
-
* Mixture weights per label, normalized to sum to 1 over labels that appeared.
|
|
2275
|
-
* Uses raw mass before per-outcome normalization.
|
|
2276
|
-
*/
|
|
2277
|
-
weights() {
|
|
2278
|
-
const res = {};
|
|
2279
|
-
for (const [, bag] of this.labelMass) {
|
|
2280
|
-
for (const [lab, w] of Object.entries(bag)) {
|
|
2281
|
-
if (!Number.isFinite(w) || w <= 0) continue;
|
|
2282
|
-
res[lab] = (res[lab] ?? 0) + w;
|
|
2283
|
-
}
|
|
2284
|
-
}
|
|
2285
|
-
let total = 0;
|
|
2286
|
-
let c = 0;
|
|
2287
|
-
for (const v of Object.values(res)) {
|
|
2288
|
-
const y = v - c;
|
|
2289
|
-
const t = total + y;
|
|
2290
|
-
c = t - total - y;
|
|
2291
|
-
total = t;
|
|
2292
|
-
}
|
|
2293
|
-
if (total > 0) {
|
|
2294
|
-
for (const k in res) res[k] = res[k] / total;
|
|
2295
|
-
}
|
|
2296
|
-
return res;
|
|
2297
|
-
}
|
|
2298
|
-
toJSON() {
|
|
2299
|
-
return {
|
|
2300
|
-
totals: Array.from(this.totals.entries()).sort((a, b) => a[0] - b[0]),
|
|
2301
|
-
labels: Array.from(this.labelMass.entries()).sort((a, b) => a[0] - b[0]),
|
|
2302
|
-
eps: this.eps
|
|
2303
|
-
};
|
|
2304
|
-
}
|
|
2305
|
-
static mix(items, eps = EPS) {
|
|
2306
|
-
const mix = new _Mixture(eps);
|
|
2307
|
-
for (const [lab, pmf, w] of items) mix.add(lab, pmf, w);
|
|
2308
|
-
return mix.buildPMF();
|
|
2309
|
-
}
|
|
2310
|
-
};
|
|
2311
|
-
|
|
2312
|
-
// src/dice.ts
|
|
2191
|
+
// src/parser/dice.ts
|
|
2313
2192
|
var Dice = class _Dice {
|
|
2314
2193
|
constructor(x = 0) {
|
|
2315
2194
|
__publicField(this, "faces", {});
|
|
@@ -2724,7 +2603,7 @@ var Dice = class _Dice {
|
|
|
2724
2603
|
}
|
|
2725
2604
|
};
|
|
2726
2605
|
|
|
2727
|
-
// src/parser.ts
|
|
2606
|
+
// src/parser/parser.ts
|
|
2728
2607
|
var parseCache = new LRUCache(1e3);
|
|
2729
2608
|
var cachingEnabled = true;
|
|
2730
2609
|
function setCachingEnabled(enabled) {
|
|
@@ -3136,6 +3015,127 @@ function parseOperation(s) {
|
|
|
3136
3015
|
return;
|
|
3137
3016
|
}
|
|
3138
3017
|
|
|
3018
|
+
// src/pmf/mixture.ts
|
|
3019
|
+
var Mixture = class _Mixture {
|
|
3020
|
+
constructor(eps = EPS) {
|
|
3021
|
+
__publicField(this, "totals", /* @__PURE__ */ new Map());
|
|
3022
|
+
// raw mass per outcome (pre-normalization)
|
|
3023
|
+
__publicField(this, "labelMass", /* @__PURE__ */ new Map());
|
|
3024
|
+
// raw mass per outcome per label
|
|
3025
|
+
__publicField(this, "eps");
|
|
3026
|
+
this.eps = Number.isFinite(eps) ? eps : EPS;
|
|
3027
|
+
}
|
|
3028
|
+
/** Remove all accumulated state. */
|
|
3029
|
+
clear() {
|
|
3030
|
+
this.totals.clear();
|
|
3031
|
+
this.labelMass.clear();
|
|
3032
|
+
return this;
|
|
3033
|
+
}
|
|
3034
|
+
/** Number of distinct outcome values currently accumulated. */
|
|
3035
|
+
size() {
|
|
3036
|
+
return this.totals.size;
|
|
3037
|
+
}
|
|
3038
|
+
/** Whether a label was ever added. */
|
|
3039
|
+
hasLabel(label) {
|
|
3040
|
+
for (const bag of this.labelMass.values()) if (bag[label]) return true;
|
|
3041
|
+
return false;
|
|
3042
|
+
}
|
|
3043
|
+
/**
|
|
3044
|
+
* Add a labeled component with a mixture weight.
|
|
3045
|
+
* Weight can be any positive finite number. Very small contributions are pruned by eps.
|
|
3046
|
+
*/
|
|
3047
|
+
add(label, pmf, weight = 1) {
|
|
3048
|
+
if (!Number.isFinite(weight) || weight <= 0) return this;
|
|
3049
|
+
for (const [v, binOrNumber] of pmf) {
|
|
3050
|
+
const isNumber = typeof binOrNumber === "number";
|
|
3051
|
+
const p = isNumber ? binOrNumber : binOrNumber?.p ?? 0;
|
|
3052
|
+
if (p <= 0) continue;
|
|
3053
|
+
const add = weight * p;
|
|
3054
|
+
if (!Number.isFinite(add) || Math.abs(add) < this.eps) continue;
|
|
3055
|
+
this.totals.set(v, (this.totals.get(v) ?? 0) + add);
|
|
3056
|
+
const bag = this.labelMass.get(v) ?? {};
|
|
3057
|
+
bag[label] = (bag[label] ?? 0) + add;
|
|
3058
|
+
this.labelMass.set(v, bag);
|
|
3059
|
+
}
|
|
3060
|
+
return this;
|
|
3061
|
+
}
|
|
3062
|
+
buildPMF(eps = EPS) {
|
|
3063
|
+
let grand = 0;
|
|
3064
|
+
let c = 0;
|
|
3065
|
+
for (const m of this.totals.values()) {
|
|
3066
|
+
const y = m - c;
|
|
3067
|
+
const t = grand + y;
|
|
3068
|
+
c = t - grand - y;
|
|
3069
|
+
grand = t;
|
|
3070
|
+
}
|
|
3071
|
+
if (!(grand > 0)) throw new Error("Mixture: zero total mass");
|
|
3072
|
+
const internal = /* @__PURE__ */ new Map();
|
|
3073
|
+
for (const [v, m] of this.totals) {
|
|
3074
|
+
if (m <= 0 || Math.abs(m) < this.eps) continue;
|
|
3075
|
+
const count = this.labelMass.get(v) ?? {};
|
|
3076
|
+
internal.set(v, { p: m / grand, count });
|
|
3077
|
+
}
|
|
3078
|
+
return new PMF(internal, eps);
|
|
3079
|
+
}
|
|
3080
|
+
/**
|
|
3081
|
+
* Produce normalized *per-label* PMFs (labels independent).
|
|
3082
|
+
* These are unlabeled PMFs built from the raw mass of that label alone.
|
|
3083
|
+
*/
|
|
3084
|
+
byOutcome() {
|
|
3085
|
+
const labels = /* @__PURE__ */ new Set();
|
|
3086
|
+
for (const bag of this.labelMass.values()) {
|
|
3087
|
+
for (const k of Object.keys(bag)) labels.add(k);
|
|
3088
|
+
}
|
|
3089
|
+
const out = {};
|
|
3090
|
+
for (const label of labels) {
|
|
3091
|
+
const m = /* @__PURE__ */ new Map();
|
|
3092
|
+
for (const [v, bag] of this.labelMass) {
|
|
3093
|
+
const w = bag[label];
|
|
3094
|
+
if (w && Math.abs(w) >= this.eps) m.set(v, w);
|
|
3095
|
+
}
|
|
3096
|
+
if (m.size > 0) out[label] = PMF.fromMap(m, this.eps);
|
|
3097
|
+
}
|
|
3098
|
+
return out;
|
|
3099
|
+
}
|
|
3100
|
+
/**
|
|
3101
|
+
* Mixture weights per label, normalized to sum to 1 over labels that appeared.
|
|
3102
|
+
* Uses raw mass before per-outcome normalization.
|
|
3103
|
+
*/
|
|
3104
|
+
weights() {
|
|
3105
|
+
const res = {};
|
|
3106
|
+
for (const [, bag] of this.labelMass) {
|
|
3107
|
+
for (const [lab, w] of Object.entries(bag)) {
|
|
3108
|
+
if (!Number.isFinite(w) || w <= 0) continue;
|
|
3109
|
+
res[lab] = (res[lab] ?? 0) + w;
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
let total = 0;
|
|
3113
|
+
let c = 0;
|
|
3114
|
+
for (const v of Object.values(res)) {
|
|
3115
|
+
const y = v - c;
|
|
3116
|
+
const t = total + y;
|
|
3117
|
+
c = t - total - y;
|
|
3118
|
+
total = t;
|
|
3119
|
+
}
|
|
3120
|
+
if (total > 0) {
|
|
3121
|
+
for (const k in res) res[k] = res[k] / total;
|
|
3122
|
+
}
|
|
3123
|
+
return res;
|
|
3124
|
+
}
|
|
3125
|
+
toJSON() {
|
|
3126
|
+
return {
|
|
3127
|
+
totals: Array.from(this.totals.entries()).sort((a, b) => a[0] - b[0]),
|
|
3128
|
+
labels: Array.from(this.labelMass.entries()).sort((a, b) => a[0] - b[0]),
|
|
3129
|
+
eps: this.eps
|
|
3130
|
+
};
|
|
3131
|
+
}
|
|
3132
|
+
static mix(items, eps = EPS) {
|
|
3133
|
+
const mix = new _Mixture(eps);
|
|
3134
|
+
for (const [lab, pmf, w] of items) mix.add(lab, pmf, w);
|
|
3135
|
+
return mix.buildPMF();
|
|
3136
|
+
}
|
|
3137
|
+
};
|
|
3138
|
+
|
|
3139
3139
|
exports.DiceQuery = DiceQuery;
|
|
3140
3140
|
exports.EPS = EPS;
|
|
3141
3141
|
exports.LRUCache = LRUCache;
|