time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

Discrete.js (7342B)


      1 import * as Continuous from "./Continuous.js";
      2 import * as Result from "../utility/result.js";
      3 import * as MixedPoint from "./MixedPoint.js";
      4 import * as Common from "./Common.js";
      5 import { ContinuousShape } from "./Continuous.js";
      6 import * as XYShape from "../XYShape.js";
      7 import { convolutionOperationToFn, } from "./PointSet.js";
      8 import { epsilon_float } from "../magicNumbers.js";
      9 import { random_sample } from "../utility/math.js";
     10 import { MixedShape } from "./Mixed.js";
     11 export class DiscreteShape {
     12     constructor(args) {
     13         this.xyShape = args.xyShape;
     14         this._integralSumCache = args.integralSumCache;
     15         this._integralCache = args.integralCache;
     16     }
     17     get integralCache() {
     18         return this._integralCache;
     19     }
     20     get integralSumCache() {
     21         return this._integralSumCache;
     22     }
     23     withAdjustedIntegralSum(integralSumCache) {
     24         return new DiscreteShape({
     25             xyShape: this.xyShape,
     26             integralSumCache,
     27             integralCache: this.integralCache,
     28         });
     29     }
     30     shapeMap(fn) {
     31         return new DiscreteShape({
     32             xyShape: fn(this.xyShape),
     33             integralSumCache: this.integralSumCache,
     34             integralCache: this.integralCache,
     35         });
     36     }
     37     integral() {
     38         if (!this._integralCache) {
     39             if (XYShape.T.isEmpty(this.xyShape)) {
     40                 this._integralCache = emptyIntegral();
     41             }
     42             else {
     43                 const ts = this.xyShape;
     44                 const firstX = XYShape.T.minX(ts);
     45                 const prependedZeroPoint = {
     46                     xs: [firstX - epsilon_float],
     47                     ys: [0],
     48                 };
     49                 const integralShape = XYShape.T.accumulateYs(XYShape.T.concat(prependedZeroPoint, ts), (a, b) => a + b);
     50                 this._integralCache = Continuous.stepwiseToLinear(new ContinuousShape({
     51                     xyShape: integralShape,
     52                     interpolation: "Stepwise",
     53                 }));
     54             }
     55         }
     56         return this._integralCache;
     57     }
     58     integralSum() {
     59         return (this._integralSumCache ??= this.integral().lastY());
     60     }
     61     integralXtoY(f) {
     62         return XYShape.XtoY.linear(this.integral().xyShape, f);
     63     }
     64     integralYtoX(f) {
     65         return XYShape.YtoX.linear(this.integral().xyShape, f);
     66     }
     67     minX() {
     68         return XYShape.T.minX(this.xyShape);
     69     }
     70     maxX() {
     71         return XYShape.T.maxX(this.xyShape);
     72     }
     73     toDiscreteProbabilityMassFraction() {
     74         return 1;
     75     }
     76     isEqual(t) {
     77         return XYShape.T.isEqual(this.xyShape, t.xyShape);
     78     }
     79     mapY(fn, integralSumCacheFn, integralCacheFn) {
     80         return new DiscreteShape({
     81             xyShape: XYShape.T.mapY(this.xyShape, fn),
     82             integralSumCache: this.integralSumCache === undefined
     83                 ? undefined
     84                 : integralSumCacheFn?.(this.integralSumCache),
     85             integralCache: this.integralCache === undefined
     86                 ? undefined
     87                 : integralCacheFn?.(this.integralCache),
     88         });
     89     }
     90     mapYResult(fn, integralSumCacheFn, integralCacheFn) {
     91         const result = XYShape.T.mapYResult(this.xyShape, fn);
     92         if (!result.ok) {
     93             return result;
     94         }
     95         return Result.Ok(new DiscreteShape({
     96             xyShape: result.value,
     97             integralSumCache: this.integralSumCache === undefined
     98                 ? undefined
     99                 : integralSumCacheFn?.(this.integralSumCache),
    100             integralCache: this.integralCache === undefined
    101                 ? undefined
    102                 : integralCacheFn?.(this.integralCache),
    103         }));
    104     }
    105     isEmpty() {
    106         return this.xyShape.xs.length === 0;
    107     }
    108     toContinuous() {
    109         return undefined;
    110     }
    111     toDiscrete() {
    112         return this;
    113     }
    114     toMixed() {
    115         return new MixedShape({
    116             continuous: Continuous.empty(),
    117             discrete: this,
    118             integralSumCache: this.integralSumCache,
    119             integralCache: this.integralCache,
    120         });
    121     }
    122     scaleBy(scale) {
    123         return this.mapY((r) => r * scale, (sum) => sum * scale, (cache) => cache.scaleBy(scale));
    124     }
    125     normalize() {
    126         return this.scaleBy(1 / this.integralSum()).withAdjustedIntegralSum(1);
    127     }
    128     downsample(i) {
    129         const currentLength = XYShape.T.length(this.xyShape);
    130         if (i < currentLength && i >= 1 && currentLength > 1) {
    131             const sortedByY = XYShape.Zipped.sortByY(XYShape.T.zip(this.xyShape));
    132             const picked = [...sortedByY].reverse().slice(0, i);
    133             return new DiscreteShape({
    134                 xyShape: XYShape.T.fromZippedArray(XYShape.Zipped.sortByX(picked)),
    135             });
    136         }
    137         else {
    138             return this;
    139         }
    140     }
    141     truncate(leftCutoff, rightCutoff) {
    142         return new DiscreteShape({
    143             xyShape: XYShape.T.fromZippedArray(XYShape.Zipped.filterByX(XYShape.T.zip(this.xyShape), (x) => x >= (leftCutoff ?? -Infinity) && x <= (rightCutoff ?? Infinity))),
    144         });
    145     }
    146     xToY(f) {
    147         return MixedPoint.makeDiscrete(XYShape.XtoY.stepwiseIfAtX(this.xyShape, f) ?? 0);
    148     }
    149     mean() {
    150         const s = this.xyShape;
    151         return s.xs.reduce((acc, x, i) => acc + x * s.ys[i], 0);
    152     }
    153     variance() {
    154         return XYShape.Analysis.getVarianceDangerously(this, (t) => t.mean(), (t) => t.shapeMap(XYShape.T.square).mean());
    155     }
    156 }
    157 const emptyIntegral = () => new ContinuousShape({
    158     xyShape: { xs: [-Infinity], ys: [0] },
    159     interpolation: "Stepwise",
    160     integralSumCache: 0,
    161     integralCache: undefined,
    162 });
    163 export const empty = () => new DiscreteShape({
    164     xyShape: XYShape.T.empty,
    165     integralSumCache: 0,
    166     integralCache: emptyIntegral(),
    167 });
    168 export const isFloat = (t) => {
    169     if (t.xyShape.ys.length === 1 && t.xyShape.ys[0] === 1) {
    170         return true;
    171     }
    172     return false;
    173 };
    174 export const getShape = (t) => t.xyShape;
    175 export const combinePointwise = (t1, t2, fn, integralSumCachesFn = () => undefined) => {
    176     const combiner = XYShape.PointwiseCombination.combine;
    177     return Result.fmap(combiner(XYShape.XtoY.discreteInterpolator, fn, t1.xyShape, t2.xyShape), (x) => new DiscreteShape({ xyShape: x }));
    178 };
    179 export const combineAlgebraically = (op, t1, t2) => {
    180     const t1s = t1.xyShape;
    181     const t2s = t2.xyShape;
    182     const t1n = XYShape.T.length(t1s);
    183     const t2n = XYShape.T.length(t2s);
    184     const combinedIntegralSum = Common.combineIntegralSums((s1, s2) => s1 * s2, t1.integralSumCache, t2.integralSumCache);
    185     const fn = convolutionOperationToFn(op);
    186     const xToYMap = new Map();
    187     for (let i = 0; i <= t1n - 1; i++) {
    188         for (let j = 0; j <= t2n - 1; j++) {
    189             const x = fn(t1s.xs[i], t2s.xs[j]);
    190             const cv = xToYMap.get(x) ?? 0;
    191             const my = t1s.ys[i] * t2s.ys[j];
    192             xToYMap.set(x, cv + my);
    193         }
    194     }
    195     const rxys = XYShape.Zipped.sortByX([...xToYMap.entries()]);
    196     const combinedShape = XYShape.T.fromZippedArray(rxys);
    197     return new DiscreteShape({
    198         xyShape: combinedShape,
    199         integralSumCache: combinedIntegralSum,
    200     });
    201 };
    202 export const sampleN = (t, n) => {
    203     const normalized = t.normalize().xyShape;
    204     return random_sample(normalized.xs, { probs: normalized.ys, size: n });
    205 };
    206 //# sourceMappingURL=Discrete.js.map