2022-04-12 05:41:36 +00:00
|
|
|
import * as _ from "lodash";
|
|
|
|
import {
|
|
|
|
genericDist,
|
|
|
|
samplingParams,
|
|
|
|
evaluate,
|
|
|
|
expressionValue,
|
|
|
|
errorValue,
|
|
|
|
distributionError,
|
|
|
|
toPointSet,
|
|
|
|
continuousShape,
|
|
|
|
discreteShape,
|
|
|
|
distributionErrorToString,
|
|
|
|
} from "../rescript/TypescriptInterface.gen";
|
|
|
|
export {
|
|
|
|
makeSampleSetDist,
|
|
|
|
errorValueToString,
|
|
|
|
distributionErrorToString,
|
|
|
|
} from "../rescript/TypescriptInterface.gen";
|
2022-04-08 19:55:04 +00:00
|
|
|
import {
|
2022-04-08 23:48:53 +00:00
|
|
|
Constructors_mean,
|
|
|
|
Constructors_sample,
|
|
|
|
Constructors_pdf,
|
|
|
|
Constructors_cdf,
|
|
|
|
Constructors_inv,
|
|
|
|
Constructors_normalize,
|
2022-04-15 17:58:00 +00:00
|
|
|
Constructors_isNormalized,
|
2022-04-08 23:48:53 +00:00
|
|
|
Constructors_toPointSet,
|
|
|
|
Constructors_toSampleSet,
|
|
|
|
Constructors_truncate,
|
|
|
|
Constructors_inspect,
|
|
|
|
Constructors_toString,
|
|
|
|
Constructors_toSparkline,
|
|
|
|
Constructors_algebraicAdd,
|
|
|
|
Constructors_algebraicMultiply,
|
|
|
|
Constructors_algebraicDivide,
|
|
|
|
Constructors_algebraicSubtract,
|
|
|
|
Constructors_algebraicLogarithm,
|
2022-04-09 16:37:26 +00:00
|
|
|
Constructors_algebraicPower,
|
2022-04-08 23:48:53 +00:00
|
|
|
Constructors_pointwiseAdd,
|
|
|
|
Constructors_pointwiseMultiply,
|
|
|
|
Constructors_pointwiseDivide,
|
|
|
|
Constructors_pointwiseSubtract,
|
|
|
|
Constructors_pointwiseLogarithm,
|
2022-04-09 16:37:26 +00:00
|
|
|
Constructors_pointwisePower,
|
2022-04-08 18:42:14 +00:00
|
|
|
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
|
2022-04-12 05:41:36 +00:00
|
|
|
export type { samplingParams, errorValue };
|
2022-04-08 18:42:14 +00:00
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
export let defaultSamplingInputs: samplingParams = {
|
2022-04-08 18:42:14 +00:00
|
|
|
sampleCount: 10000,
|
2022-04-12 05:41:36 +00:00
|
|
|
xyPointLength: 10000,
|
2022-04-08 18:42:14 +00:00
|
|
|
};
|
|
|
|
|
2022-04-11 06:16:29 +00:00
|
|
|
export type result<a, b> =
|
2022-04-08 23:48:53 +00:00
|
|
|
| {
|
|
|
|
tag: "Ok";
|
2022-04-11 00:48:45 +00:00
|
|
|
value: a;
|
2022-04-08 23:48:53 +00:00
|
|
|
}
|
|
|
|
| {
|
|
|
|
tag: "Error";
|
2022-04-11 00:48:45 +00:00
|
|
|
value: b;
|
2022-04-09 02:55:06 +00:00
|
|
|
};
|
|
|
|
|
2022-04-11 00:51:43 +00:00
|
|
|
export function resultMap<a, b, c>(
|
|
|
|
r: result<a, c>,
|
|
|
|
mapFn: (x: a) => b
|
|
|
|
): result<b, c> {
|
2022-04-08 23:48:53 +00:00
|
|
|
if (r.tag === "Ok") {
|
|
|
|
return { tag: "Ok", value: mapFn(r.value) };
|
|
|
|
} else {
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
function Ok<a, b>(x: a): result<a, b> {
|
|
|
|
return { tag: "Ok", value: x };
|
2022-04-11 06:16:29 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
type tagged<a, b> = { tag: a; value: b };
|
2022-04-11 03:16:31 +00:00
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
function tag<a, b>(x: a, y: b): tagged<a, b> {
|
|
|
|
return { tag: x, value: y };
|
2022-04-11 03:16:31 +00:00
|
|
|
}
|
|
|
|
|
2022-04-25 14:00:27 +00:00
|
|
|
export abstract class internalCode {
|
|
|
|
protected opaque!: any;
|
|
|
|
} /* simulate opaque types */
|
2022-04-25 07:20:27 +00:00
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
export type squiggleExpression =
|
|
|
|
| tagged<"symbol", string>
|
|
|
|
| tagged<"string", string>
|
2022-04-12 23:34:06 +00:00
|
|
|
| tagged<"call", string>
|
2022-04-25 07:20:27 +00:00
|
|
|
| tagged<"lambda", [string[], internalCode]>
|
2022-04-12 05:41:36 +00:00
|
|
|
| tagged<"array", squiggleExpression[]>
|
|
|
|
| tagged<"boolean", boolean>
|
|
|
|
| tagged<"distribution", Distribution>
|
|
|
|
| tagged<"number", number>
|
|
|
|
| tagged<"record", { [key: string]: squiggleExpression }>;
|
2022-04-11 03:16:31 +00:00
|
|
|
export function run(
|
|
|
|
squiggleString: string,
|
2022-04-21 22:09:06 +00:00
|
|
|
samplingInputs?: samplingParams
|
2022-04-11 03:16:31 +00:00
|
|
|
): result<squiggleExpression, errorValue> {
|
|
|
|
let si: samplingParams = samplingInputs
|
|
|
|
? samplingInputs
|
|
|
|
: defaultSamplingInputs;
|
2022-04-12 05:41:36 +00:00
|
|
|
let result: result<expressionValue, errorValue> = evaluate(squiggleString);
|
|
|
|
return resultMap(result, (x) => createTsExport(x, si));
|
2022-04-11 03:16:31 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
function createTsExport(
|
|
|
|
x: expressionValue,
|
|
|
|
sampEnv: samplingParams
|
|
|
|
): squiggleExpression {
|
2022-04-11 03:16:31 +00:00
|
|
|
switch (x.tag) {
|
|
|
|
case "EvArray":
|
2022-04-12 05:41:36 +00:00
|
|
|
return tag(
|
|
|
|
"array",
|
|
|
|
x.value.map((x) => createTsExport(x, sampEnv))
|
|
|
|
);
|
2022-04-11 03:16:31 +00:00
|
|
|
case "EvBool":
|
|
|
|
return tag("boolean", x.value);
|
2022-04-12 15:12:19 +00:00
|
|
|
case "EvCall":
|
|
|
|
return tag("call", x.value);
|
2022-04-25 07:20:27 +00:00
|
|
|
case "EvLambda":
|
|
|
|
return tag("lambda", x.value);
|
2022-04-11 03:16:31 +00:00
|
|
|
case "EvDistribution":
|
|
|
|
return tag("distribution", new Distribution(x.value, sampEnv));
|
|
|
|
case "EvNumber":
|
|
|
|
return tag("number", x.value);
|
|
|
|
case "EvRecord":
|
2022-04-12 05:41:36 +00:00
|
|
|
return tag(
|
|
|
|
"record",
|
|
|
|
_.mapValues(x.value, (x) => createTsExport(x, sampEnv))
|
|
|
|
);
|
|
|
|
case "EvString":
|
|
|
|
return tag("string", x.value);
|
|
|
|
case "EvSymbol":
|
|
|
|
return tag("symbol", x.value);
|
2022-04-11 03:16:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-11 00:51:43 +00:00
|
|
|
export function resultExn<a, c>(r: result<a, c>): a | c {
|
|
|
|
return r.value;
|
2022-04-10 01:56:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
export type point = { x: number; y: number };
|
2022-04-11 06:16:29 +00:00
|
|
|
|
|
|
|
export type shape = {
|
2022-04-12 05:41:36 +00:00
|
|
|
continuous: point[];
|
|
|
|
discrete: point[];
|
|
|
|
};
|
2022-04-11 06:16:29 +00:00
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
function shapePoints(x: continuousShape | discreteShape): point[] {
|
2022-04-11 06:16:29 +00:00
|
|
|
let xs = x.xyShape.xs;
|
|
|
|
let ys = x.xyShape.ys;
|
2022-04-12 05:41:36 +00:00
|
|
|
return _.zipWith(xs, ys, (x, y) => ({ x, y }));
|
2022-04-11 06:16:29 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 00:48:45 +00:00
|
|
|
export class Distribution {
|
2022-04-08 18:42:14 +00:00
|
|
|
t: genericDist;
|
2022-04-11 03:16:31 +00:00
|
|
|
env: samplingParams;
|
2022-04-08 18:42:14 +00:00
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
constructor(t: genericDist, env: samplingParams) {
|
2022-04-08 18:42:14 +00:00
|
|
|
this.t = t;
|
2022-04-08 23:48:53 +00:00
|
|
|
this.env = env;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
mapResultDist(
|
|
|
|
r: result<genericDist, distributionError>
|
|
|
|
): result<Distribution, distributionError> {
|
2022-04-11 00:48:45 +00:00
|
|
|
return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
|
2022-04-08 18:42:14 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
mean(): result<number, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return Constructors_mean({ env: this.env }, this.t);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
sample(): result<number, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return Constructors_sample({ env: this.env }, this.t);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
pdf(n: number): result<number, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return Constructors_pdf({ env: this.env }, this.t, n);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
cdf(n: number): result<number, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return Constructors_cdf({ env: this.env }, this.t, n);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
inv(n: number): result<number, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return Constructors_inv({ env: this.env }, this.t, n);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-15 17:58:00 +00:00
|
|
|
isNormalized(): result<boolean, distributionError> {
|
|
|
|
return Constructors_isNormalized({ env: this.env }, this.t);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
normalize(): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_normalize({ env: this.env }, this.t)
|
|
|
|
);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-15 22:00:31 +00:00
|
|
|
type() {
|
2022-04-13 23:37:59 +00:00
|
|
|
return this.t.tag;
|
|
|
|
}
|
|
|
|
|
2022-04-12 06:21:32 +00:00
|
|
|
pointSet(): result<shape, distributionError> {
|
2022-04-12 05:41:36 +00:00
|
|
|
let pointSet = toPointSet(
|
|
|
|
this.t,
|
|
|
|
{
|
|
|
|
xyPointLength: this.env.xyPointLength,
|
|
|
|
sampleCount: this.env.sampleCount,
|
|
|
|
},
|
|
|
|
undefined
|
|
|
|
);
|
|
|
|
if (pointSet.tag === "Ok") {
|
2022-04-11 06:16:29 +00:00
|
|
|
let distribution = pointSet.value;
|
2022-04-12 05:41:36 +00:00
|
|
|
if (distribution.tag === "Continuous") {
|
2022-04-11 06:16:29 +00:00
|
|
|
return Ok({
|
|
|
|
continuous: shapePoints(distribution.value),
|
2022-04-12 05:41:36 +00:00
|
|
|
discrete: [],
|
|
|
|
});
|
|
|
|
} else if (distribution.tag === "Discrete") {
|
2022-04-11 06:16:29 +00:00
|
|
|
return Ok({
|
|
|
|
discrete: shapePoints(distribution.value),
|
2022-04-12 05:41:36 +00:00
|
|
|
continuous: [],
|
|
|
|
});
|
|
|
|
} else {
|
2022-04-11 06:16:29 +00:00
|
|
|
return Ok({
|
|
|
|
discrete: shapePoints(distribution.value.discrete),
|
2022-04-12 05:41:36 +00:00
|
|
|
continuous: shapePoints(distribution.value.continuous),
|
|
|
|
});
|
2022-04-11 06:16:29 +00:00
|
|
|
}
|
2022-04-12 05:41:36 +00:00
|
|
|
} else {
|
|
|
|
return pointSet;
|
2022-04-11 06:16:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
toPointSet(): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_toPointSet({ env: this.env }, this.t)
|
|
|
|
);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
toSampleSet(n: number): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_toSampleSet({ env: this.env }, this.t, n)
|
|
|
|
);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
truncate(
|
|
|
|
left: number,
|
|
|
|
right: number
|
|
|
|
): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_truncate({ env: this.env }, this.t, left, right)
|
2022-04-08 19:55:04 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
inspect(): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 06:16:29 +00:00
|
|
|
toString(): string {
|
|
|
|
let result = Constructors_toString({ env: this.env }, this.t);
|
2022-04-12 05:41:36 +00:00
|
|
|
if (result.tag === "Ok") {
|
|
|
|
return result.value;
|
|
|
|
} else {
|
|
|
|
return distributionErrorToString(result.value);
|
2022-04-11 06:16:29 +00:00
|
|
|
}
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
toSparkline(n: number): result<string, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return Constructors_toSparkline({ env: this.env }, this.t, n);
|
2022-04-08 19:55:04 +00:00
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
algebraicAdd(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_algebraicAdd({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
algebraicMultiply(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
algebraicDivide(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_algebraicDivide({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
algebraicSubtract(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
algebraicLogarithm(
|
|
|
|
d2: Distribution
|
|
|
|
): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
algebraicPower(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
2022-04-09 16:37:26 +00:00
|
|
|
Constructors_algebraicPower({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
pointwiseAdd(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
pointwiseMultiply(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
pointwiseDivide(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
pointwiseSubtract(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-12 05:41:36 +00:00
|
|
|
pointwiseLogarithm(
|
|
|
|
d2: Distribution
|
|
|
|
): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
|
|
|
Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-11 03:16:31 +00:00
|
|
|
pointwisePower(d2: Distribution): result<Distribution, distributionError> {
|
2022-04-08 23:48:53 +00:00
|
|
|
return this.mapResultDist(
|
2022-04-09 16:37:26 +00:00
|
|
|
Constructors_pointwisePower({ env: this.env }, this.t, d2.t)
|
2022-04-08 18:42:14 +00:00
|
|
|
);
|
|
|
|
}
|
2022-03-01 07:43:35 +00:00
|
|
|
}
|