import * as _ from 'lodash'
import type {
exportEnv,
exportDistribution,
} from "../rescript/ProgramEvaluator.gen";
export type { exportEnv, exportDistribution };
import { genericDist, samplingParams, evaluate, expressionValue, errorValue, distributionError, toPointSet, continuousShape, discreteShape, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
export { makeSampleSetDist, errorValueToString, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
import {
Constructors_mean,
Constructors_sample,
Constructors_pdf,
Constructors_cdf,
Constructors_inv,
Constructors_normalize,
Constructors_toPointSet,
Constructors_toSampleSet,
Constructors_truncate,
Constructors_inspect,
Constructors_toString,
Constructors_toSparkline,
Constructors_algebraicAdd,
Constructors_algebraicMultiply,
Constructors_algebraicDivide,
Constructors_algebraicSubtract,
Constructors_algebraicLogarithm,
Constructors_algebraicPower,
Constructors_pointwiseAdd,
Constructors_pointwiseMultiply,
Constructors_pointwiseDivide,
Constructors_pointwiseSubtract,
Constructors_pointwiseLogarithm,
Constructors_pointwisePower,
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
export type {samplingParams, errorValue}
export let defaultSamplingInputs: samplingParams = {
sampleCount: 10000,
xyPointLength: 10000
};
export type result =
| {
tag: "Ok";
value: a;
}
| {
tag: "Error";
value: b;
};
export function resultMap(
r: result,
mapFn: (x: a) => b
): result {
if (r.tag === "Ok") {
return { tag: "Ok", value: mapFn(r.value) };
} else {
return r;
}
}
function Ok(x: a): result {
return {"tag": "Ok", value: x}
}
type tagged = {tag: a, value: b}
function tag(x: a, y: b) : tagged{
return { tag: x, value: y}
}
export type squiggleExpression = tagged<"symbol", string> | tagged<"string", string> | tagged<"array", squiggleExpression[]> | tagged<"boolean", boolean> | tagged<"distribution", Distribution> | tagged<"number", number> | tagged<"record", {[key: string]: squiggleExpression }>
export function run(
squiggleString: string,
samplingInputs?: samplingParams,
_environment?: exportEnv
): result {
let si: samplingParams = samplingInputs
? samplingInputs
: defaultSamplingInputs;
let result : result = evaluate(squiggleString);
return resultMap(result, x => createTsExport(x, si));
}
function createTsExport(x: expressionValue, sampEnv: samplingParams): squiggleExpression {
switch (x.tag) {
case "EvArray":
return tag("array", x.value.map(x => createTsExport(x, sampEnv)));
case "EvBool":
return tag("boolean", x.value);
case "EvDistribution":
return tag("distribution", new Distribution(x.value, sampEnv));
case "EvNumber":
return tag("number", x.value);
case "EvRecord":
return tag("record", _.mapValues(x.value, x => createTsExport(x, sampEnv)))
}
}
export function resultExn(r: result): a | c {
return r.value;
}
export type point = { x: number, y: number}
export type shape = {
continuous: point[]
discrete: point[]
}
function shapePoints(x : continuousShape | discreteShape): point[]{
let xs = x.xyShape.xs;
let ys = x.xyShape.ys;
return _.zipWith(xs, ys, (x, y) => ({x, y}))
}
export class Distribution {
t: genericDist;
env: samplingParams;
constructor(t: genericDist, env: samplingParams) {
this.t = t;
this.env = env;
return this;
}
mapResultDist(r: result): result {
return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
}
mean(): result {
return Constructors_mean({ env: this.env }, this.t);
}
sample(): result {
return Constructors_sample({ env: this.env }, this.t);
}
pdf(n: number): result {
return Constructors_pdf({ env: this.env }, this.t, n);
}
cdf(n: number): result {
return Constructors_cdf({ env: this.env }, this.t, n);
}
inv(n: number): result {
return Constructors_inv({ env: this.env }, this.t, n);
}
normalize(): result {
return this.mapResultDist(
Constructors_normalize({ env: this.env }, this.t)
);
}
shape() : result {
let pointSet = toPointSet(this.t, {xyPointLength: this.env.xyPointLength, sampleCount: this.env.sampleCount}, null);
if(pointSet.tag === "Ok"){
let distribution = pointSet.value;
if(distribution.tag === "Continuous"){
return Ok({
continuous: shapePoints(distribution.value),
discrete: []
})
}
else if(distribution.tag === "Discrete"){
return Ok({
discrete: shapePoints(distribution.value),
continuous: []
})
}
else if(distribution.tag === "Mixed"){
return Ok({
discrete: shapePoints(distribution.value.discrete),
continuous: shapePoints(distribution.value.continuous)
})
}
}
else {
return pointSet
}
}
toPointSet(): result {
return this.mapResultDist(
Constructors_toPointSet({ env: this.env }, this.t)
);
}
toSampleSet(n: number): result {
return this.mapResultDist(
Constructors_toSampleSet({ env: this.env }, this.t, n)
);
}
truncate(left: number, right: number): result {
return this.mapResultDist(
Constructors_truncate({ env: this.env }, this.t, left, right)
);
}
inspect(): result {
return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
}
toString(): string {
let result = Constructors_toString({ env: this.env }, this.t);
if(result.tag === "Ok"){
result.value
}
else {
return distributionErrorToString(result.value)
}
}
toSparkline(n: number): result {
return Constructors_toSparkline({ env: this.env }, this.t, n);
}
algebraicAdd(d2: Distribution): result {
return this.mapResultDist(
Constructors_algebraicAdd({ env: this.env }, this.t, d2.t)
);
}
algebraicMultiply(d2: Distribution): result {
return this.mapResultDist(
Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t)
);
}
algebraicDivide(d2: Distribution): result {
return this.mapResultDist(
Constructors_algebraicDivide({ env: this.env }, this.t, d2.t)
);
}
algebraicSubtract(d2: Distribution): result {
return this.mapResultDist(
Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t)
);
}
algebraicLogarithm(d2: Distribution): result {
return this.mapResultDist(
Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
);
}
algebraicPower(d2: Distribution): result {
return this.mapResultDist(
Constructors_algebraicPower({ env: this.env }, this.t, d2.t)
);
}
pointwiseAdd(d2: Distribution): result {
return this.mapResultDist(
Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t)
);
}
pointwiseMultiply(d2: Distribution): result {
return this.mapResultDist(
Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t)
);
}
pointwiseDivide(d2: Distribution): result {
return this.mapResultDist(
Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t)
);
}
pointwiseSubtract(d2: Distribution): result {
return this.mapResultDist(
Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t)
);
}
pointwiseLogarithm(d2: Distribution): result {
return this.mapResultDist(
Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
);
}
pointwisePower(d2: Distribution): result {
return this.mapResultDist(
Constructors_pointwisePower({ env: this.env }, this.t, d2.t)
);
}
}