@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 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
- pruneRelative(epsRel, minBins = 0) {
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), this.epsilon, false, this.identifier);
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, this.epsilon, false, `prune(${this.identifier})`);
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/mixture.ts
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;