@chronon-sim/engine 0.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.
Files changed (151) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +19 -0
  3. package/dist/components/autoscaler.d.ts +47 -0
  4. package/dist/components/autoscaler.d.ts.map +1 -0
  5. package/dist/components/autoscaler.js +116 -0
  6. package/dist/components/autoscaler.js.map +1 -0
  7. package/dist/components/generator.d.ts +32 -0
  8. package/dist/components/generator.d.ts.map +1 -0
  9. package/dist/components/generator.js +124 -0
  10. package/dist/components/generator.js.map +1 -0
  11. package/dist/components/index.d.ts +14 -0
  12. package/dist/components/index.d.ts.map +1 -0
  13. package/dist/components/index.js +11 -0
  14. package/dist/components/index.js.map +1 -0
  15. package/dist/components/message-queue.d.ts +45 -0
  16. package/dist/components/message-queue.d.ts.map +1 -0
  17. package/dist/components/message-queue.js +152 -0
  18. package/dist/components/message-queue.js.map +1 -0
  19. package/dist/components/pullable.d.ts +24 -0
  20. package/dist/components/pullable.d.ts.map +1 -0
  21. package/dist/components/pullable.js +2 -0
  22. package/dist/components/pullable.js.map +1 -0
  23. package/dist/components/queue.d.ts +32 -0
  24. package/dist/components/queue.d.ts.map +1 -0
  25. package/dist/components/queue.js +88 -0
  26. package/dist/components/queue.js.map +1 -0
  27. package/dist/components/rate-limiter.d.ts +24 -0
  28. package/dist/components/rate-limiter.d.ts.map +1 -0
  29. package/dist/components/rate-limiter.js +77 -0
  30. package/dist/components/rate-limiter.js.map +1 -0
  31. package/dist/components/registry.d.ts +19 -0
  32. package/dist/components/registry.d.ts.map +1 -0
  33. package/dist/components/registry.js +43 -0
  34. package/dist/components/registry.js.map +1 -0
  35. package/dist/components/retry-policy.d.ts +41 -0
  36. package/dist/components/retry-policy.d.ts.map +1 -0
  37. package/dist/components/retry-policy.js +122 -0
  38. package/dist/components/retry-policy.js.map +1 -0
  39. package/dist/components/server.d.ts +26 -0
  40. package/dist/components/server.d.ts.map +1 -0
  41. package/dist/components/server.js +82 -0
  42. package/dist/components/server.js.map +1 -0
  43. package/dist/components/sink.d.ts +12 -0
  44. package/dist/components/sink.d.ts.map +1 -0
  45. package/dist/components/sink.js +35 -0
  46. package/dist/components/sink.js.map +1 -0
  47. package/dist/components/worker-pool.d.ts +68 -0
  48. package/dist/components/worker-pool.d.ts.map +1 -0
  49. package/dist/components/worker-pool.js +224 -0
  50. package/dist/components/worker-pool.js.map +1 -0
  51. package/dist/format/definition.d.ts +72 -0
  52. package/dist/format/definition.d.ts.map +1 -0
  53. package/dist/format/definition.js +17 -0
  54. package/dist/format/definition.js.map +1 -0
  55. package/dist/format/index.d.ts +5 -0
  56. package/dist/format/index.d.ts.map +1 -0
  57. package/dist/format/index.js +3 -0
  58. package/dist/format/index.js.map +1 -0
  59. package/dist/format/loader.d.ts +19 -0
  60. package/dist/format/loader.d.ts.map +1 -0
  61. package/dist/format/loader.js +275 -0
  62. package/dist/format/loader.js.map +1 -0
  63. package/dist/index.d.ts +9 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +9 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/kernel/heap.d.ts +14 -0
  68. package/dist/kernel/heap.d.ts.map +1 -0
  69. package/dist/kernel/heap.js +55 -0
  70. package/dist/kernel/heap.js.map +1 -0
  71. package/dist/kernel/index.d.ts +3 -0
  72. package/dist/kernel/index.d.ts.map +1 -0
  73. package/dist/kernel/index.js +2 -0
  74. package/dist/kernel/index.js.map +1 -0
  75. package/dist/kernel/kernel.d.ts +104 -0
  76. package/dist/kernel/kernel.d.ts.map +1 -0
  77. package/dist/kernel/kernel.js +236 -0
  78. package/dist/kernel/kernel.js.map +1 -0
  79. package/dist/model/entity.d.ts +78 -0
  80. package/dist/model/entity.d.ts.map +1 -0
  81. package/dist/model/entity.js +108 -0
  82. package/dist/model/entity.js.map +1 -0
  83. package/dist/model/fifo.d.ts +9 -0
  84. package/dist/model/fifo.d.ts.map +1 -0
  85. package/dist/model/fifo.js +24 -0
  86. package/dist/model/fifo.js.map +1 -0
  87. package/dist/model/index.d.ts +4 -0
  88. package/dist/model/index.d.ts.map +1 -0
  89. package/dist/model/index.js +3 -0
  90. package/dist/model/index.js.map +1 -0
  91. package/dist/rng/distributions.d.ts +98 -0
  92. package/dist/rng/distributions.d.ts.map +1 -0
  93. package/dist/rng/distributions.js +224 -0
  94. package/dist/rng/distributions.js.map +1 -0
  95. package/dist/rng/index.d.ts +4 -0
  96. package/dist/rng/index.d.ts.map +1 -0
  97. package/dist/rng/index.js +3 -0
  98. package/dist/rng/index.js.map +1 -0
  99. package/dist/rng/rng.d.ts +26 -0
  100. package/dist/rng/rng.d.ts.map +1 -0
  101. package/dist/rng/rng.js +101 -0
  102. package/dist/rng/rng.js.map +1 -0
  103. package/dist/run/assertions.d.ts +9 -0
  104. package/dist/run/assertions.d.ts.map +1 -0
  105. package/dist/run/assertions.js +57 -0
  106. package/dist/run/assertions.js.map +1 -0
  107. package/dist/run/index.d.ts +6 -0
  108. package/dist/run/index.d.ts.map +1 -0
  109. package/dist/run/index.js +4 -0
  110. package/dist/run/index.js.map +1 -0
  111. package/dist/run/results.d.ts +72 -0
  112. package/dist/run/results.d.ts.map +1 -0
  113. package/dist/run/results.js +2 -0
  114. package/dist/run/results.js.map +1 -0
  115. package/dist/run/run.d.ts +29 -0
  116. package/dist/run/run.d.ts.map +1 -0
  117. package/dist/run/run.js +80 -0
  118. package/dist/run/run.js.map +1 -0
  119. package/dist/run/simulation.d.ts +34 -0
  120. package/dist/run/simulation.d.ts.map +1 -0
  121. package/dist/run/simulation.js +104 -0
  122. package/dist/run/simulation.js.map +1 -0
  123. package/dist/schema/index.d.ts +5 -0
  124. package/dist/schema/index.d.ts.map +1 -0
  125. package/dist/schema/index.js +3 -0
  126. package/dist/schema/index.js.map +1 -0
  127. package/dist/schema/types.d.ts +83 -0
  128. package/dist/schema/types.d.ts.map +1 -0
  129. package/dist/schema/types.js +19 -0
  130. package/dist/schema/types.js.map +1 -0
  131. package/dist/schema/validate.d.ts +19 -0
  132. package/dist/schema/validate.d.ts.map +1 -0
  133. package/dist/schema/validate.js +120 -0
  134. package/dist/schema/validate.js.map +1 -0
  135. package/dist/stats/index.d.ts +6 -0
  136. package/dist/stats/index.d.ts.map +1 -0
  137. package/dist/stats/index.js +4 -0
  138. package/dist/stats/index.js.map +1 -0
  139. package/dist/stats/percentile.d.ts +38 -0
  140. package/dist/stats/percentile.d.ts.map +1 -0
  141. package/dist/stats/percentile.js +62 -0
  142. package/dist/stats/percentile.js.map +1 -0
  143. package/dist/stats/summary.d.ts +20 -0
  144. package/dist/stats/summary.d.ts.map +1 -0
  145. package/dist/stats/summary.js +38 -0
  146. package/dist/stats/summary.js.map +1 -0
  147. package/dist/stats/time-weighted.d.ts +31 -0
  148. package/dist/stats/time-weighted.d.ts.map +1 -0
  149. package/dist/stats/time-weighted.js +69 -0
  150. package/dist/stats/time-weighted.js.map +1 -0
  151. package/package.json +41 -0
@@ -0,0 +1,98 @@
1
+ import type { Rng } from "./rng.js";
2
+ /** Anything that can produce a number on demand: constants and random distributions alike. */
3
+ export interface SampleProvider {
4
+ nextSample(): number;
5
+ }
6
+ /** JSON-serialisable description of a distribution. Mirrors the JSON model format. */
7
+ export type DistributionSpec = {
8
+ dist: "constant";
9
+ value: number;
10
+ } | {
11
+ dist: "uniform";
12
+ min: number;
13
+ max: number;
14
+ } | {
15
+ dist: "exponential";
16
+ mean: number;
17
+ } | {
18
+ dist: "normal";
19
+ mean: number;
20
+ stdDev: number;
21
+ } | {
22
+ dist: "triangular";
23
+ min: number;
24
+ mode: number;
25
+ max: number;
26
+ } | {
27
+ dist: "lognormal";
28
+ mean: number;
29
+ stdDev: number;
30
+ };
31
+ /** A plain number (constant) or a distribution description. */
32
+ export type SamplerSpec = number | DistributionSpec;
33
+ /** Names of the supported distributions. */
34
+ export declare const DISTRIBUTION_NAMES: readonly ["constant", "uniform", "exponential", "normal", "triangular", "lognormal"];
35
+ /** Required numeric parameters of each distribution. */
36
+ export declare const DISTRIBUTION_PARAMS: Record<(typeof DISTRIBUTION_NAMES)[number], readonly string[]>;
37
+ /** Always returns the same value. */
38
+ export declare class ConstantSampler implements SampleProvider {
39
+ readonly value: number;
40
+ constructor(value: number);
41
+ nextSample(): number;
42
+ }
43
+ /** Uniform on [min, max). */
44
+ export declare class UniformSampler implements SampleProvider {
45
+ private readonly rng;
46
+ private readonly min;
47
+ private readonly max;
48
+ constructor(rng: Rng, min: number, max: number);
49
+ nextSample(): number;
50
+ }
51
+ /** Exponential with the given mean (rate = 1 / mean). */
52
+ export declare class ExponentialSampler implements SampleProvider {
53
+ private readonly rng;
54
+ private readonly mean;
55
+ constructor(rng: Rng, mean: number);
56
+ nextSample(): number;
57
+ }
58
+ /** Normal (Gaussian) via the Box–Muller transform. Can return negative values. */
59
+ export declare class NormalSampler implements SampleProvider {
60
+ private readonly rng;
61
+ private readonly mean;
62
+ private readonly stdDev;
63
+ private spare;
64
+ constructor(rng: Rng, mean: number, stdDev: number);
65
+ /** A standard-normal variate. */
66
+ nextStandard(): number;
67
+ nextSample(): number;
68
+ }
69
+ /** Triangular on [min, max] with the given mode. */
70
+ export declare class TriangularSampler implements SampleProvider {
71
+ private readonly rng;
72
+ private readonly min;
73
+ private readonly mode;
74
+ private readonly max;
75
+ constructor(rng: Rng, min: number, mode: number, max: number);
76
+ nextSample(): number;
77
+ }
78
+ /**
79
+ * Lognormal parameterised by the mean and standard deviation of the lognormal variable itself
80
+ * (not of its logarithm), which is how service times are usually described.
81
+ */
82
+ export declare class LognormalSampler implements SampleProvider {
83
+ private readonly normal;
84
+ private readonly mu;
85
+ private readonly sigma;
86
+ constructor(rng: Rng, mean: number, stdDev: number);
87
+ nextSample(): number;
88
+ }
89
+ /**
90
+ * Validate a raw (untrusted, e.g. parsed JSON) sampler spec.
91
+ * @returns human-readable problems; empty when the spec is valid
92
+ */
93
+ export declare function validateSamplerSpec(spec: unknown): string[];
94
+ /** Theoretical mean of a validated spec (used for documentation and sanity tests). */
95
+ export declare function samplerMean(spec: SamplerSpec): number;
96
+ /** Build a {@link SampleProvider} from a validated spec, drawing from `rng`. */
97
+ export declare function createSampler(spec: SamplerSpec, rng: Rng): SampleProvider;
98
+ //# sourceMappingURL=distributions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distributions.d.ts","sourceRoot":"","sources":["../../src/rng/distributions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ /** Names of the supported distributions. */
2
+ export const DISTRIBUTION_NAMES = [
3
+ "constant",
4
+ "uniform",
5
+ "exponential",
6
+ "normal",
7
+ "triangular",
8
+ "lognormal",
9
+ ];
10
+ /** Required numeric parameters of each distribution. */
11
+ export const DISTRIBUTION_PARAMS = {
12
+ constant: ["value"],
13
+ uniform: ["min", "max"],
14
+ exponential: ["mean"],
15
+ normal: ["mean", "stdDev"],
16
+ triangular: ["min", "mode", "max"],
17
+ lognormal: ["mean", "stdDev"],
18
+ };
19
+ /** Always returns the same value. */
20
+ export class ConstantSampler {
21
+ value;
22
+ constructor(value) {
23
+ this.value = value;
24
+ }
25
+ nextSample() {
26
+ return this.value;
27
+ }
28
+ }
29
+ /** Uniform on [min, max). */
30
+ export class UniformSampler {
31
+ rng;
32
+ min;
33
+ max;
34
+ constructor(rng, min, max) {
35
+ this.rng = rng;
36
+ this.min = min;
37
+ this.max = max;
38
+ }
39
+ nextSample() {
40
+ return this.min + (this.max - this.min) * this.rng.nextFloat();
41
+ }
42
+ }
43
+ /** Exponential with the given mean (rate = 1 / mean). */
44
+ export class ExponentialSampler {
45
+ rng;
46
+ mean;
47
+ constructor(rng, mean) {
48
+ this.rng = rng;
49
+ this.mean = mean;
50
+ }
51
+ nextSample() {
52
+ return -this.mean * Math.log(this.rng.nextFloatOpen());
53
+ }
54
+ }
55
+ /** Normal (Gaussian) via the Box–Muller transform. Can return negative values. */
56
+ export class NormalSampler {
57
+ rng;
58
+ mean;
59
+ stdDev;
60
+ spare = null;
61
+ constructor(rng, mean, stdDev) {
62
+ this.rng = rng;
63
+ this.mean = mean;
64
+ this.stdDev = stdDev;
65
+ }
66
+ /** A standard-normal variate. */
67
+ nextStandard() {
68
+ if (this.spare !== null) {
69
+ const z = this.spare;
70
+ this.spare = null;
71
+ return z;
72
+ }
73
+ const r = Math.sqrt(-2 * Math.log(this.rng.nextFloatOpen()));
74
+ const theta = 2 * Math.PI * this.rng.nextFloat();
75
+ this.spare = r * Math.sin(theta);
76
+ return r * Math.cos(theta);
77
+ }
78
+ nextSample() {
79
+ return this.mean + this.stdDev * this.nextStandard();
80
+ }
81
+ }
82
+ /** Triangular on [min, max] with the given mode. */
83
+ export class TriangularSampler {
84
+ rng;
85
+ min;
86
+ mode;
87
+ max;
88
+ constructor(rng, min, mode, max) {
89
+ this.rng = rng;
90
+ this.min = min;
91
+ this.mode = mode;
92
+ this.max = max;
93
+ }
94
+ nextSample() {
95
+ const { min, mode, max } = this;
96
+ if (max === min)
97
+ return min;
98
+ const u = this.rng.nextFloat();
99
+ const fc = (mode - min) / (max - min);
100
+ return u < fc
101
+ ? min + Math.sqrt(u * (max - min) * (mode - min))
102
+ : max - Math.sqrt((1 - u) * (max - min) * (max - mode));
103
+ }
104
+ }
105
+ /**
106
+ * Lognormal parameterised by the mean and standard deviation of the lognormal variable itself
107
+ * (not of its logarithm), which is how service times are usually described.
108
+ */
109
+ export class LognormalSampler {
110
+ normal;
111
+ mu;
112
+ sigma;
113
+ constructor(rng, mean, stdDev) {
114
+ // sigma^2 = ln(1 + (stdDev/mean)^2). log1p keeps precision when the ratio is tiny. When the squared ratio
115
+ // overflows (a subnormal mean, or an enormous stdDev) 1 + ratio^2 is just ratio^2, so use 2 ln(stdDev/mean)
116
+ // computed from the two logs; the direct formula would give ln(Infinity) - Infinity = NaN.
117
+ const ratioSquared = (stdDev / mean) ** 2;
118
+ const sigmaSquared = Number.isFinite(ratioSquared) ? Math.log1p(ratioSquared) : 2 * (Math.log(stdDev) - Math.log(mean));
119
+ this.sigma = Math.sqrt(sigmaSquared);
120
+ this.mu = Math.log(mean) - 0.5 * sigmaSquared;
121
+ this.normal = new NormalSampler(rng, 0, 1);
122
+ }
123
+ nextSample() {
124
+ return Math.exp(this.mu + this.sigma * this.normal.nextStandard());
125
+ }
126
+ }
127
+ function isRecord(v) {
128
+ return typeof v === "object" && v !== null && !Array.isArray(v);
129
+ }
130
+ function finite(v) {
131
+ return typeof v === "number" && Number.isFinite(v);
132
+ }
133
+ /**
134
+ * Validate a raw (untrusted, e.g. parsed JSON) sampler spec.
135
+ * @returns human-readable problems; empty when the spec is valid
136
+ */
137
+ export function validateSamplerSpec(spec) {
138
+ if (finite(spec))
139
+ return [];
140
+ if (!isRecord(spec)) {
141
+ return ["expected a number or a distribution object such as {\"dist\": \"exponential\", \"mean\": 1}"];
142
+ }
143
+ const name = spec["dist"];
144
+ if (typeof name !== "string" || !DISTRIBUTION_NAMES.includes(name)) {
145
+ return [`"dist" must be one of ${DISTRIBUTION_NAMES.join(", ")}`];
146
+ }
147
+ const params = DISTRIBUTION_PARAMS[name];
148
+ const problems = [];
149
+ for (const key of params) {
150
+ if (!finite(spec[key]))
151
+ problems.push(`${name}: "${key}" must be a finite number`);
152
+ }
153
+ for (const key of Object.keys(spec)) {
154
+ if (key !== "dist" && !params.includes(key))
155
+ problems.push(`${name}: unknown parameter "${key}"`);
156
+ }
157
+ if (problems.length > 0)
158
+ return problems;
159
+ const p = spec;
160
+ const get = (k) => p[k];
161
+ switch (name) {
162
+ case "uniform":
163
+ if (get("min") > get("max"))
164
+ problems.push("uniform: min must be <= max");
165
+ break;
166
+ case "exponential":
167
+ if (!(get("mean") > 0))
168
+ problems.push("exponential: mean must be > 0");
169
+ break;
170
+ case "normal":
171
+ if (get("stdDev") < 0)
172
+ problems.push("normal: stdDev must be >= 0");
173
+ break;
174
+ case "triangular":
175
+ if (!(get("min") <= get("mode") && get("mode") <= get("max"))) {
176
+ problems.push("triangular: requires min <= mode <= max");
177
+ }
178
+ break;
179
+ case "lognormal":
180
+ if (!(get("mean") > 0))
181
+ problems.push("lognormal: mean must be > 0");
182
+ if (get("stdDev") < 0)
183
+ problems.push("lognormal: stdDev must be >= 0");
184
+ break;
185
+ }
186
+ return problems;
187
+ }
188
+ /** Theoretical mean of a validated spec (used for documentation and sanity tests). */
189
+ export function samplerMean(spec) {
190
+ if (typeof spec === "number")
191
+ return spec;
192
+ switch (spec.dist) {
193
+ case "constant":
194
+ return spec.value;
195
+ case "uniform":
196
+ return (spec.min + spec.max) / 2;
197
+ case "exponential":
198
+ case "normal":
199
+ case "lognormal":
200
+ return spec.mean;
201
+ case "triangular":
202
+ return (spec.min + spec.mode + spec.max) / 3;
203
+ }
204
+ }
205
+ /** Build a {@link SampleProvider} from a validated spec, drawing from `rng`. */
206
+ export function createSampler(spec, rng) {
207
+ if (typeof spec === "number")
208
+ return new ConstantSampler(spec);
209
+ switch (spec.dist) {
210
+ case "constant":
211
+ return new ConstantSampler(spec.value);
212
+ case "uniform":
213
+ return new UniformSampler(rng, spec.min, spec.max);
214
+ case "exponential":
215
+ return new ExponentialSampler(rng, spec.mean);
216
+ case "normal":
217
+ return new NormalSampler(rng, spec.mean, spec.stdDev);
218
+ case "triangular":
219
+ return new TriangularSampler(rng, spec.min, spec.mode, spec.max);
220
+ case "lognormal":
221
+ return new LognormalSampler(rng, spec.mean, spec.stdDev);
222
+ }
223
+ }
224
+ //# sourceMappingURL=distributions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distributions.js","sourceRoot":"","sources":["../../src/rng/distributions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { Rng, deriveSeed } from "./rng.js";
2
+ export { ConstantSampler, UniformSampler, ExponentialSampler, NormalSampler, TriangularSampler, LognormalSampler, createSampler, validateSamplerSpec, samplerMean, DISTRIBUTION_NAMES, DISTRIBUTION_PARAMS, } from "./distributions.js";
3
+ export type { SampleProvider, DistributionSpec, SamplerSpec } from "./distributions.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rng/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Rng, deriveSeed } from "./rng.js";
2
+ export { ConstantSampler, UniformSampler, ExponentialSampler, NormalSampler, TriangularSampler, LognormalSampler, createSampler, validateSamplerSpec, samplerMean, DISTRIBUTION_NAMES, DISTRIBUTION_PARAMS, } from "./distributions.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rng/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EACL,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Derive a child seed from a base seed and an index (e.g. replication number).
3
+ * The result is a non-negative integer below 2^53.
4
+ */
5
+ export declare function deriveSeed(baseSeed: number, index: number): number;
6
+ /**
7
+ * Seeded pseudo-random number generator (xoshiro128**, 128-bit state).
8
+ *
9
+ * A generator is identified by `(seed, streamId)`: the same pair always yields the same sequence,
10
+ * and different stream ids yield statistically independent sequences. Give every component its
11
+ * own stream so that changing one component never shifts another component's random numbers.
12
+ */
13
+ export declare class Rng {
14
+ private s0;
15
+ private s1;
16
+ private s2;
17
+ private s3;
18
+ constructor(seed: number, streamId?: string | number);
19
+ /** Next uniformly distributed unsigned 32-bit integer. */
20
+ nextUint32(): number;
21
+ /** Next uniform float in [0, 1) with 53 bits of resolution. */
22
+ nextFloat(): number;
23
+ /** Next uniform float in (0, 1] — safe as an argument to Math.log. */
24
+ nextFloatOpen(): number;
25
+ }
26
+ //# sourceMappingURL=rng.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rng.d.ts","sourceRoot":"","sources":["../../src/rng/rng.ts"],"names":[],"mappings":"AA6BA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlE;AAeD;;;;;;GAMG;AACH,qBAAa,GAAG;IACd,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,EAAE,CAAS;gBAEP,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,GAAG,MAAU;IAYvD,0DAA0D;IAC1D,UAAU,IAAI,MAAM;IAcpB,+DAA+D;IAC/D,SAAS,IAAI,MAAM;IAMnB,sEAAsE;IACtE,aAAa,IAAI,MAAM;CAGxB"}
@@ -0,0 +1,101 @@
1
+ /** murmur3 32-bit finalizer: a strong integer mixer. */
2
+ function fmix32(h) {
3
+ h ^= h >>> 16;
4
+ h = Math.imul(h, 0x85ebca6b);
5
+ h ^= h >>> 13;
6
+ h = Math.imul(h, 0xc2b2ae35);
7
+ h ^= h >>> 16;
8
+ return h >>> 0;
9
+ }
10
+ /** Two independent 32-bit string hashes (FNV-1a and a multiplicative variant) = a 64-bit stream hash. */
11
+ function hashString(s) {
12
+ let a = 0x811c9dc5;
13
+ let b = 0x9747b28c;
14
+ for (let i = 0; i < s.length; i++) {
15
+ const c = s.charCodeAt(i);
16
+ a = Math.imul(a ^ c, 0x01000193);
17
+ b = Math.imul(b + c + 1, 0x5bd1e995);
18
+ b ^= b >>> 15;
19
+ }
20
+ return [fmix32(a), fmix32(b ^ s.length)];
21
+ }
22
+ function splitSeed(seed) {
23
+ if (!Number.isFinite(seed))
24
+ throw new RangeError(`seed must be a finite number, got ${seed}`);
25
+ const s = Math.abs(Math.trunc(seed));
26
+ return [s >>> 0, Math.floor(s / 4294967296) >>> 0];
27
+ }
28
+ /**
29
+ * Derive a child seed from a base seed and an index (e.g. replication number).
30
+ * The result is a non-negative integer below 2^53.
31
+ */
32
+ export function deriveSeed(baseSeed, index) {
33
+ const [lo, hi] = splitSeed(baseSeed);
34
+ const [ilo, ihi] = splitSeed(index);
35
+ const a = fmix32(lo ^ fmix32(ilo + 0x9e3779b9));
36
+ const b = fmix32(hi ^ fmix32(ihi + 0x7f4a7c15) ^ a);
37
+ const c = fmix32(a + b + 0x165667b1);
38
+ return (c & 0x1fffff) * 4294967296 + fmix32(a ^ (b + 0x27d4eb2f));
39
+ }
40
+ function splitmix32(seed) {
41
+ let a = seed | 0;
42
+ return () => {
43
+ a = (a + 0x9e3779b9) | 0;
44
+ let t = a ^ (a >>> 16);
45
+ t = Math.imul(t, 0x21f0aaad);
46
+ t ^= t >>> 15;
47
+ t = Math.imul(t, 0x735a2d97);
48
+ t ^= t >>> 15;
49
+ return t >>> 0;
50
+ };
51
+ }
52
+ /**
53
+ * Seeded pseudo-random number generator (xoshiro128**, 128-bit state).
54
+ *
55
+ * A generator is identified by `(seed, streamId)`: the same pair always yields the same sequence,
56
+ * and different stream ids yield statistically independent sequences. Give every component its
57
+ * own stream so that changing one component never shifts another component's random numbers.
58
+ */
59
+ export class Rng {
60
+ s0;
61
+ s1;
62
+ s2;
63
+ s3;
64
+ constructor(seed, streamId = 0) {
65
+ const [lo, hi] = splitSeed(seed);
66
+ const [h1, h2] = hashString(String(streamId));
67
+ const g1 = splitmix32(fmix32(lo ^ fmix32(h1)));
68
+ const g2 = splitmix32(fmix32(hi + 0x632be5ab) ^ fmix32(h2 + 0x1b873593) ^ g1());
69
+ this.s0 = g1();
70
+ this.s1 = g1();
71
+ this.s2 = g2();
72
+ this.s3 = g2();
73
+ if ((this.s0 | this.s1 | this.s2 | this.s3) === 0)
74
+ this.s0 = 1;
75
+ }
76
+ /** Next uniformly distributed unsigned 32-bit integer. */
77
+ nextUint32() {
78
+ const { s1 } = this;
79
+ const x = Math.imul(s1, 5);
80
+ const result = Math.imul((x << 7) | (x >>> 25), 9) >>> 0;
81
+ const t = s1 << 9;
82
+ this.s2 ^= this.s0;
83
+ this.s3 ^= s1;
84
+ this.s1 ^= this.s2;
85
+ this.s0 ^= this.s3;
86
+ this.s2 ^= t;
87
+ this.s3 = (this.s3 << 11) | (this.s3 >>> 21);
88
+ return result;
89
+ }
90
+ /** Next uniform float in [0, 1) with 53 bits of resolution. */
91
+ nextFloat() {
92
+ const a = this.nextUint32() >>> 5; // 27 bits
93
+ const b = this.nextUint32() >>> 6; // 26 bits
94
+ return (a * 67108864 + b) / 9007199254740992;
95
+ }
96
+ /** Next uniform float in (0, 1] — safe as an argument to Math.log. */
97
+ nextFloatOpen() {
98
+ return 1 - this.nextFloat();
99
+ }
100
+ }
101
+ //# sourceMappingURL=rng.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rng.js","sourceRoot":"","sources":["../../src/rng/rng.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { AssertionDefinition } from "../format/index.js";
2
+ import type { AssertionResult, RunResults } from "./results.js";
3
+ /**
4
+ * Check assertions against run results. An assertion on an undefined value (an unknown output, no
5
+ * observations, or a confidence interval with a single replication) fails, because a gate that
6
+ * silently passes when its data is missing is worse than no gate.
7
+ */
8
+ export declare function evaluateAssertions(results: RunResults, assertions: readonly AssertionDefinition[]): AssertionResult[];
9
+ //# sourceMappingURL=assertions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../../src/run/assertions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAyChE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,mBAAmB,EAAE,GAAG,eAAe,EAAE,CAYrH"}
@@ -0,0 +1,57 @@
1
+ function compare(actual, op, value) {
2
+ switch (op) {
3
+ case "<":
4
+ return actual < value;
5
+ case "<=":
6
+ return actual <= value;
7
+ case ">":
8
+ return actual > value;
9
+ case ">=":
10
+ return actual >= value;
11
+ case "==":
12
+ return actual === value;
13
+ }
14
+ }
15
+ function fmt(v) {
16
+ return Number.isInteger(v) ? String(v) : String(Number(v.toPrecision(5)));
17
+ }
18
+ /** The number an assertion compares, or null when it is undefined for these results. */
19
+ function pick(results, a) {
20
+ const summary = results.outputs.find((o) => o.id === a.output);
21
+ if (summary === undefined)
22
+ return null;
23
+ switch (a.statistic ?? "mean") {
24
+ case "mean":
25
+ return summary.mean;
26
+ case "ci95Low":
27
+ return summary.ci95?.low ?? null;
28
+ case "ci95High":
29
+ return summary.ci95?.high ?? null;
30
+ case "min":
31
+ case "max": {
32
+ const values = results.replications.map((r) => r.outputs[a.output]).filter((v) => typeof v === "number");
33
+ if (values.length === 0)
34
+ return null;
35
+ return a.statistic === "min" ? Math.min(...values) : Math.max(...values);
36
+ }
37
+ }
38
+ }
39
+ /**
40
+ * Check assertions against run results. An assertion on an undefined value (an unknown output, no
41
+ * observations, or a confidence interval with a single replication) fails, because a gate that
42
+ * silently passes when its data is missing is worse than no gate.
43
+ */
44
+ export function evaluateAssertions(results, assertions) {
45
+ return assertions.map((assertion) => {
46
+ const stat = assertion.statistic ?? "mean";
47
+ const label = assertion.name ? `${assertion.name}: ` : "";
48
+ const actual = pick(results, assertion);
49
+ const subject = `${assertion.output} (${stat})`;
50
+ if (actual === null) {
51
+ return { assertion, actual: null, passed: false, message: `${label}${subject} is undefined, cannot check ${assertion.op} ${fmt(assertion.value)}` };
52
+ }
53
+ const passed = compare(actual, assertion.op, assertion.value);
54
+ return { assertion, actual, passed, message: `${label}${subject} = ${fmt(actual)} ${passed ? assertion.op : `violates ${assertion.op}`} ${fmt(assertion.value)}` };
55
+ });
56
+ }
57
+ //# sourceMappingURL=assertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../../src/run/assertions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { runModel, defaultTimeSeries, replicationSeed } from "./run.js";
2
+ export type { RunOptions } from "./run.js";
3
+ export { evaluateAssertions } from "./assertions.js";
4
+ export { Simulation } from "./simulation.js";
5
+ export type { RunResults, RunSettingsUsed, ReplicationResult, OutputSummary, TimeSeriesResult, TimeSeriesReplication, AssertionResult, } from "./results.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACxE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACV,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,GAChB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { runModel, defaultTimeSeries, replicationSeed } from "./run.js";
2
+ export { evaluateAssertions } from "./assertions.js";
3
+ export { Simulation } from "./simulation.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAExE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}