time-to-botec

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

Mixed.js (10120B)


      1 import * as XYShape from "../XYShape.js";
      2 import * as Continuous from "./Continuous.js";
      3 import * as Discrete from "./Discrete.js";
      4 import * as MixedPoint from "./MixedPoint.js";
      5 import * as Result from "../utility/result.js";
      6 import * as Common from "./Common.js";
      7 import { ContinuousShape } from "./Continuous.js";
      8 import { DiscreteShape } from "./Discrete.js";
      9 export class MixedShape {
     10     constructor(args) {
     11         this.continuous = args.continuous;
     12         this.discrete = args.discrete;
     13         this._integralSumCache = args.integralSumCache;
     14         this._integralCache = args.integralCache;
     15     }
     16     get integralCache() {
     17         return this._integralCache;
     18     }
     19     get integralSumCache() {
     20         return this._integralSumCache;
     21     }
     22     withAdjustedIntegralSum(integralSumCache) {
     23         return new MixedShape({
     24             continuous: this.continuous,
     25             discrete: this.discrete,
     26             integralSumCache,
     27             integralCache: this.integralCache,
     28         });
     29     }
     30     minX() {
     31         return Math.min(this.continuous.minX(), this.discrete.minX());
     32     }
     33     maxX() {
     34         return Math.max(this.continuous.maxX(), this.discrete.maxX());
     35     }
     36     isEmpty() {
     37         return this.continuous.isEmpty() && this.discrete.isEmpty();
     38     }
     39     toContinuous() {
     40         return this.continuous;
     41     }
     42     toDiscrete() {
     43         return this.discrete;
     44     }
     45     toMixed() {
     46         return this;
     47     }
     48     isEqual(other) {
     49         return (this.continuous.isEqual(other.continuous) &&
     50             this.discrete.isEqual(other.discrete));
     51     }
     52     truncate(leftCutoff, rightCutoff) {
     53         return new MixedShape({
     54             continuous: this.continuous.truncate(leftCutoff, rightCutoff),
     55             discrete: this.discrete.truncate(leftCutoff, rightCutoff),
     56         });
     57     }
     58     normalize() {
     59         if (this.isEmpty()) {
     60             return this;
     61         }
     62         if (this.continuous.isEmpty()) {
     63             return this.discrete.normalize().toMixed();
     64         }
     65         if (this.discrete.isEmpty()) {
     66             return this.continuous.normalize().toMixed();
     67         }
     68         const continuousIntegralSum = this.continuous.integralSum();
     69         const discreteIntegralSum = this.discrete.integralSum();
     70         const totalIntegralSum = continuousIntegralSum + discreteIntegralSum;
     71         const newContinuousSum = continuousIntegralSum / totalIntegralSum;
     72         const newDiscreteSum = discreteIntegralSum / totalIntegralSum;
     73         const normalizedContinuous = this.continuous
     74             .scaleBy(newContinuousSum / continuousIntegralSum)
     75             .withAdjustedIntegralSum(newContinuousSum);
     76         const normalizedDiscrete = this.discrete
     77             .scaleBy(newDiscreteSum / discreteIntegralSum)
     78             .withAdjustedIntegralSum(newDiscreteSum);
     79         return new MixedShape({
     80             continuous: normalizedContinuous,
     81             discrete: normalizedDiscrete,
     82             integralSumCache: 1,
     83         });
     84     }
     85     xToY(x) {
     86         const { continuous, discrete } = this.normalize();
     87         const c = continuous.xToY(x);
     88         const d = discrete.xToY(x);
     89         return MixedPoint.add(c, d);
     90     }
     91     toDiscreteProbabilityMassFraction() {
     92         const discreteIntegralSum = this.discrete.integralSum();
     93         const continuousIntegralSum = this.continuous.integralSum();
     94         const totalIntegralSum = discreteIntegralSum + continuousIntegralSum;
     95         return discreteIntegralSum / totalIntegralSum;
     96     }
     97     downsample(count) {
     98         const discreteIntegralSum = this.discrete.integralSum();
     99         const continuousIntegralSum = this.continuous.integralSum();
    100         const totalIntegralSum = discreteIntegralSum + continuousIntegralSum;
    101         const downsampledDiscrete = this.discrete.downsample(Math.floor((count * discreteIntegralSum) / totalIntegralSum));
    102         const downsampledContinuous = this.continuous.downsample(Math.floor((count * continuousIntegralSum) / totalIntegralSum));
    103         return new MixedShape({
    104             continuous: downsampledContinuous,
    105             discrete: downsampledDiscrete,
    106             integralSumCache: this.integralSumCache,
    107             integralCache: this.integralCache,
    108         });
    109     }
    110     integral() {
    111         if (!this._integralCache) {
    112             const continuousIntegral = this.continuous.integral();
    113             const discreteIntegral = Continuous.stepwiseToLinear(this.discrete.integral());
    114             this._integralCache = new ContinuousShape({
    115                 xyShape: XYShape.PointwiseCombination.addCombine(XYShape.XtoY.continuousInterpolator("Linear", "UseOutermostPoints"), continuousIntegral.xyShape, discreteIntegral.xyShape),
    116             });
    117         }
    118         return this._integralCache;
    119     }
    120     integralSum() {
    121         return (this._integralSumCache ??= this.integral().lastY());
    122     }
    123     integralXtoY(f) {
    124         return XYShape.XtoY.linear(this.integral().xyShape, f);
    125     }
    126     integralYtoX(f) {
    127         return XYShape.YtoX.linear(this.integral().xyShape, f);
    128     }
    129     mapY(fn, integralSumCacheFn, integralCacheFn) {
    130         const discrete = this.discrete.mapY(fn, integralSumCacheFn, integralCacheFn);
    131         const continuous = this.continuous.mapY(fn, integralSumCacheFn, integralCacheFn);
    132         return new MixedShape({
    133             discrete,
    134             continuous,
    135             integralSumCache: this.integralSumCache === undefined
    136                 ? undefined
    137                 : integralSumCacheFn?.(this.integralSumCache),
    138             integralCache: this.integralCache === undefined
    139                 ? undefined
    140                 : integralCacheFn?.(this.integralCache),
    141         });
    142     }
    143     mapYResult(fn, integralSumCacheFn, integralCacheFn) {
    144         const discreteResult = this.discrete.mapYResult(fn, integralSumCacheFn, integralCacheFn);
    145         const continuousResult = this.continuous.mapYResult(fn, integralSumCacheFn, integralCacheFn);
    146         if (!continuousResult.ok) {
    147             return continuousResult;
    148         }
    149         if (!discreteResult.ok) {
    150             return discreteResult;
    151         }
    152         const continuous = continuousResult.value;
    153         const discrete = discreteResult.value;
    154         return Result.Ok(new MixedShape({
    155             discrete,
    156             continuous,
    157             integralSumCache: this.integralSumCache === undefined
    158                 ? undefined
    159                 : integralSumCacheFn?.(this.integralSumCache),
    160             integralCache: this.integralCache === undefined
    161                 ? undefined
    162                 : integralCacheFn?.(this.integralCache),
    163         }));
    164     }
    165     mean() {
    166         const discreteMean = this.discrete.mean();
    167         const continuousMean = this.continuous.mean();
    168         return ((discreteMean * this.discrete.integralSum() +
    169             continuousMean * this.continuous.integralSum()) /
    170             this.integralSum());
    171     }
    172     variance() {
    173         const discreteIntegralSum = this.discrete.integralSum();
    174         const continuousIntegralSum = this.continuous.integralSum();
    175         const totalIntegralSum = discreteIntegralSum + continuousIntegralSum;
    176         const getMeanOfSquares = ({ discrete, continuous }) => {
    177             const discreteMean = discrete.shapeMap(XYShape.T.square).mean();
    178             const continuousMean = continuous.getMeanOfSquares();
    179             return ((discreteMean * discreteIntegralSum +
    180                 continuousMean * continuousIntegralSum) /
    181                 totalIntegralSum);
    182         };
    183         switch (discreteIntegralSum / totalIntegralSum) {
    184             case 1:
    185                 return this.discrete.variance();
    186             case 0:
    187                 return this.continuous.variance();
    188             default:
    189                 return XYShape.Analysis.getVarianceDangerously(this, (t) => t.mean(), (t) => getMeanOfSquares(t));
    190         }
    191     }
    192 }
    193 export const combineAlgebraically = (op, t1, t2) => {
    194     const ccConvResult = Continuous.combineAlgebraically(op, t1.continuous, t2.continuous);
    195     const dcConvResult = Continuous.combineAlgebraicallyWithDiscrete(op, t2.continuous, t1.discrete, "First");
    196     const cdConvResult = Continuous.combineAlgebraicallyWithDiscrete(op, t1.continuous, t2.discrete, "Second");
    197     const continuousConvResult = Continuous.sum([
    198         ccConvResult,
    199         dcConvResult,
    200         cdConvResult,
    201     ]);
    202     const discreteConvResult = Discrete.combineAlgebraically(op, t1.discrete, t2.discrete);
    203     const combinedIntegralSum = Common.combineIntegralSums((a, b) => a * b, t1.integralSumCache, t2.integralSumCache);
    204     return new MixedShape({
    205         discrete: discreteConvResult,
    206         continuous: continuousConvResult,
    207         integralSumCache: combinedIntegralSum,
    208         integralCache: undefined,
    209     });
    210 };
    211 export const combinePointwise = (t1, t2, fn, integralSumCachesFn = () => undefined, integralCachesFn = () => undefined) => {
    212     const reducedDiscrete = Discrete.combinePointwise(t1.toDiscrete(), t2.toDiscrete(), fn, integralSumCachesFn);
    213     const reducedContinuous = Continuous.combinePointwise(t1.toContinuous(), t2.toContinuous(), fn, undefined, integralSumCachesFn);
    214     const combinedIntegralSum = Common.combineIntegralSums(integralSumCachesFn, t1.integralSumCache, t2.integralSumCache);
    215     const combinedIntegral = Common.combineIntegrals(integralCachesFn, t1.integralCache, t2.integralCache);
    216     return Result.fmap(Result.merge(reducedContinuous, reducedDiscrete), ([continuous, discrete]) => new MixedShape({
    217         continuous,
    218         discrete,
    219         integralSumCache: combinedIntegralSum,
    220         integralCache: combinedIntegral,
    221     }));
    222 };
    223 export function buildMixedShape({ continuous, discrete, }) {
    224     continuous ??= new ContinuousShape({
    225         integralSumCache: 0,
    226         xyShape: { xs: [], ys: [] },
    227     });
    228     discrete ??= new DiscreteShape({
    229         integralSumCache: 0,
    230         xyShape: { xs: [], ys: [] },
    231     });
    232     const cLength = continuous.xyShape.xs.length;
    233     const dLength = discrete.xyShape.xs.length;
    234     if (cLength < 2 && dLength == 0) {
    235         return undefined;
    236     }
    237     else {
    238         return new MixedShape({ continuous, discrete });
    239     }
    240 }
    241 //# sourceMappingURL=Mixed.js.map