From 57196c568b3b7f191c53f49965c593b4818bea26 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 14:42:14 -0400 Subject: [PATCH 1/7] Added a bunch of manual functions for DistributionOperation --- packages/squiggle-lang/bsconfig.json | 2 +- packages/squiggle-lang/src/js/index.ts | 190 ++++++++++++++++-- .../DistributionOperation.res | 47 +++++ .../DistributionOperation.resi | 36 ++++ .../GenericDist/GenericDist_Types.res | 75 ++++++- .../Distributions/SampleSetDist/SampleSet.res | 1 + .../src/rescript/TSInterface.res | 14 ++ 7 files changed, 348 insertions(+), 17 deletions(-) create mode 100644 packages/squiggle-lang/src/rescript/TSInterface.res diff --git a/packages/squiggle-lang/bsconfig.json b/packages/squiggle-lang/bsconfig.json index e936eb82..958a3af8 100644 --- a/packages/squiggle-lang/bsconfig.json +++ b/packages/squiggle-lang/bsconfig.json @@ -33,7 +33,7 @@ "gentypeconfig": { "language": "typescript", "module": "commonjs", - "shims": {}, + "shims": {"Js": "Js"}, "debug": { "all": false, "basic": false diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 7856ef6f..5f12bf56 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -1,17 +1,181 @@ -import {runAll} from '../rescript/ProgramEvaluator.gen'; -import type { Inputs_SamplingInputs_t as SamplingInputs, exportEnv, exportType, exportDistribution} from '../rescript/ProgramEvaluator.gen'; -export type { SamplingInputs, exportEnv, exportDistribution } -export type {t as DistPlus} from '../rescript/OldInterpreter/DistPlus.gen'; +import { runAll } from "../rescript/ProgramEvaluator.gen"; +import type { + Inputs_SamplingInputs_t as SamplingInputs, + exportEnv, + exportType, + exportDistribution, +} from "../rescript/ProgramEvaluator.gen"; +export type { SamplingInputs, exportEnv, exportDistribution }; +export type { t as DistPlus } from "../rescript/OldInterpreter/DistPlus.gen"; +import type { Operation_genericFunctionCallInfo } from "../rescript/Distributions/GenericDist/GenericDist_Types.gen"; +import { genericDist } from "../rescript/TSInterface.gen"; +import { + run as runR, + env, + outputType, +} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; +import { add } from "lodash"; -export let defaultSamplingInputs : SamplingInputs = { - sampleCount : 10000, - outputXYPoints : 10000, - pointDistLength : 1000 +export let defaultSamplingInputs: SamplingInputs = { + sampleCount: 10000, + outputXYPoints: 10000, + pointDistLength: 1000, +}; + +export function run( + squiggleString: string, + samplingInputs?: SamplingInputs, + environment?: exportEnv +): { tag: "Ok"; value: exportType } | { tag: "Error"; value: string } { + let si: SamplingInputs = samplingInputs + ? samplingInputs + : defaultSamplingInputs; + let env: exportEnv = environment ? environment : []; + return runAll(squiggleString, si, env); } -export function run(squiggleString : string, samplingInputs? : SamplingInputs, environment?: exportEnv) : { tag: "Ok"; value: exportType } - | { tag: "Error"; value: string } { - let si : SamplingInputs = samplingInputs ? samplingInputs : defaultSamplingInputs - let env : exportEnv = environment ? environment : [] - return runAll(squiggleString, si, env) +class GenericDist { + t: genericDist; + env: env; + + constructor(t: genericDist, env: env) { + this.t = t; + } + + mean(): outputType { + return runR( + { env: this.env }, + { tag: "FromDist", value: [{ tag: "ToFloat", value: "Mean" }, this.t] } + ); + } + + pdf(n: number): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [{ tag: "ToFloat", value: { NAME: "Pdf", VAL: n } }, this.t], + } + ); + } + + cdf(n: number): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [{ tag: "ToFloat", value: { NAME: "Pdf", VAL: n } }, this.t], + } + ); + } + + inv(n: number): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [{ tag: "ToFloat", value: { NAME: "Pdf", VAL: n } }, this.t], + } + ); + } + + normalize(n: number): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [{ tag: "ToDist", value: "Normalize" }, this.t], + } + ); + } + + toPointSet(): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [{ tag: "ToDist", value: "ToPointSet" }, this.t], + } + ); + } + + inspect(): outputType { + return runR( + { env: this.env }, + { tag: "FromDist", value: [{ tag: "ToDist", value: "Inspect" }, this.t] } + ); + } + + toSampleSet(n: number): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [ + { tag: "ToDist", value: { tag: "ToSampleSet", value: n } }, + this.t, + ], + } + ); + } + + truncate( + left: null | undefined | number, + right: null | undefined | number + ): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [ + { tag: "ToDist", value: { tag: "Truncate", value: [left, right] } }, + this.t, + ], + } + ); + } + + toString(): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [{ tag: "ToString", value: "ToString" }, this.t], + } + ); + } + + toSparkline(n: number): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [ + { tag: "ToString", value: { tag: "ToSparkline", value: n } }, + this.t, + ], + } + ); + } + + add(g2: genericDist): outputType { + return runR( + { env: this.env }, + { + tag: "FromDist", + value: [ + { + tag: "ToDistCombination", + value: [ + { + tag: "ToDistCombination", + value: ["Algebraic", "Add", { NAME: "Dist", VAL: g2 }], + }, + ], + }, + this.t, + ], + } + ); + } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 14e7b6c4..1d25f64c 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -185,3 +185,50 @@ module Output = { newFnCall->E.R2.fmap(run(~env))->OutputLocal.fromResult } } + +module Constructors = { + module UsingDists = { + module C = GenericDist_Types.Constructors.UsingDists + open OutputLocal + type dist = GenericDist_Types.genericDist + type fResult = result + type dResult = result + type sResult = result + + let mean = (~env, dist) => run(~env, C.mean(dist))->toFloatR + let sample = (~env, dist) => run(~env, C.sample(dist))->toFloatR + let cdf = (~env, dist, f) => run(~env, C.cdf(dist, f))->toFloatR + let inv = (~env, dist, f) => run(~env, C.inv(dist, f))->toFloatR + let pdf = (~env, dist, f) => run(~env, C.pdf(dist, f))->toFloatR + let normalize = (~env, dist) => run(~env, C.normalize(dist))->toDistR + let toPointSet = (~env, dist) => run(~env, C.toPointSet(dist))->toDistR + let toSampleSet = (~env, dist, n) => run(~env, C.toSampleSet(dist, n))->toDistR + let truncate = (~env, dist, leftCutoff, rightCutoff) => + run(~env, C.truncate(dist, leftCutoff, rightCutoff))->toDistR + let inspect = (~env, dist) => run(~env, C.inspect(dist))->toDistR + let toString = (~env, dist) => run(~env, C.toString(dist))->toStringR + let toSparkline = (~env, dist, buckets) => run(~env, C.toSparkline(dist, buckets))->toStringR + let algebraicAdd = (~env, dist1, dist2) => run(~env, C.algebraicAdd(dist1, dist2))->toDistR + let algebraicMultiply = (~env, dist1, dist2) => + run(~env, C.algebraicMultiply(dist1, dist2))->toDistR + let algebraicDivide = (~env, dist1, dist2) => + run(~env, C.algebraicDivide(dist1, dist2))->toDistR + let algebraicSubtract = (~env, dist1, dist2) => + run(~env, C.algebraicSubtract(dist1, dist2))->toDistR + let algebraicLogarithm = (~env, dist1, dist2) => + run(~env, C.algebraicLogarithm(dist1, dist2))->toDistR + let algebraicExponentiate = (~env, dist1, dist2) => + run(~env, C.algebraicExponentiate(dist1, dist2))->toDistR + let pointwiseAdd = (~env, dist1, dist2) => run(~env, C.pointwiseAdd(dist1, dist2))->toDistR + let pointwiseMultiply = (~env, dist1, dist2) => + run(~env, C.pointwiseMultiply(dist1, dist2))->toDistR + let pointwiseDivide = (~env, dist1, dist2) => + run(~env, C.pointwiseDivide(dist1, dist2))->toDistR + let pointwiseSubtract = (~env, dist1, dist2) => + run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR + let pointwiseLogarithm = (~env, dist1, dist2) => + run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR + let pointwiseExponentiate = (~env, dist1, dist2) => + run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR + } +} diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi index 3c3e132a..e39d5848 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi @@ -1,14 +1,17 @@ +@genType type env = { sampleCount: int, xyPointLength: int, } +@genType type outputType = | Dist(GenericDist_Types.genericDist) | Float(float) | String(string) | GenDistError(GenericDist_Types.error) +@genType let run: (~env: env, GenericDist_Types.Operation.genericFunctionCallInfo) => outputType let runFromDist: ( ~env: env, @@ -32,3 +35,36 @@ module Output: { let toError: t => option let fmap: (~env: env, t, GenericDist_Types.Operation.singleParamaterFunction) => t } + +module Constructors: { + module UsingDists: { + type dist = GenericDist_Types.genericDist + type fResult = result + type dResult = result + type sResult = result + let mean: (~env: env, dist) => fResult + let sample: (~env: env, dist) => fResult + let cdf: (~env: env, dist, float) => fResult + let inv: (~env: env, dist, float) => fResult + let pdf: (~env: env, dist, float) => fResult + let normalize: (~env: env, dist) => dResult + let toPointSet: (~env: env, dist) => dResult + let toSampleSet: (~env: env, dist, int) => dResult + let truncate: (~env: env, dist, option, option) => dResult + let inspect: (~env: env, dist) => dResult + let toString: (~env: env, dist) => sResult + let toSparkline: (~env: env, dist, int) => sResult + let algebraicAdd: (~env: env, dist, dist) => dResult + let algebraicMultiply: (~env: env, dist, dist) => dResult + let algebraicDivide: (~env: env, dist, dist) => dResult + let algebraicSubtract: (~env: env, dist, dist) => dResult + let algebraicLogarithm: (~env: env, dist, dist) => dResult + let algebraicExponentiate: (~env: env, dist, dist) => dResult + let pointwiseAdd: (~env: env, dist, dist) => dResult + let pointwiseMultiply: (~env: env, dist, dist) => dResult + let pointwiseDivide: (~env: env, dist, dist) => dResult + let pointwiseSubtract: (~env: env, dist, dist) => dResult + let pointwiseLogarithm: (~env: env, dist, dist) => dResult + let pointwiseExponentiate: (~env: env, dist, dist) => dResult + } +} diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res index 0eb64bd7..f472a6e0 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res @@ -3,6 +3,7 @@ type genericDist = | SampleSet(SampleSet.t) | Symbolic(SymbolicDistTypes.symbolicDist) +@genType type error = | NotYetImplemented | Unreachable @@ -52,9 +53,9 @@ module Operation = { type toFloatArray = Sample(int) - type toString = - | ToString - | ToSparkline(int) + type toString = + | ToString + | ToSparkline(int) type fromDist = | ToFloat(toFloat) @@ -66,6 +67,7 @@ module Operation = { | FromDist(fromDist) | FromFloat(fromDist) + @genType type genericFunctionCallInfo = | FromDist(fromDist, genericDist) | FromFloat(fromDist, float) @@ -95,3 +97,70 @@ module Operation = { | Mixture(_) => `mixture` } } + +module Constructors = { + type t = Operation.genericFunctionCallInfo + + module UsingDists = { + let mean = (dist): t => FromDist(ToFloat(#Mean), dist) + let sample = (dist): t => FromDist(ToFloat(#Mean), dist) + let cdf = (dist, f): t => FromDist(ToFloat(#Cdf(f)), dist) + let inv = (dist, f): t => FromDist(ToFloat(#Inv(f)), dist) + let pdf = (dist, f): t => FromDist(ToFloat(#Pdf(f)), dist) + let normalize = (dist): t => FromDist(ToDist(Normalize), dist) + let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist) + let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist) + let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) + let inspect = (dist): t => FromDist(ToDist(Inspect), dist) + let toString = (dist): t => FromDist(ToString(ToString), dist) + let toSparkline = (dist, n): t => FromDist(ToString(ToSparkline(n)), dist) + let algebraicAdd = (dist1, dist2:genericDist): t => FromDist( + ToDistCombination(Algebraic, #Add, #Dist(dist2)), + dist1, + ) + let algebraicMultiply = (dist1, dist2): t => FromDist( + ToDistCombination(Algebraic, #Multiply, #Dist(dist2)), + dist1, + ) + let algebraicDivide = (dist1, dist2): t => FromDist( + ToDistCombination(Algebraic, #Divide, #Dist(dist2)), + dist1, + ) + let algebraicSubtract = (dist1, dist2): t => FromDist( + ToDistCombination(Algebraic, #Subtract, #Dist(dist2)), + dist1, + ) + let algebraicLogarithm = (dist1, dist2): t => FromDist( + ToDistCombination(Algebraic, #Logarithm, #Dist(dist2)), + dist1, + ) + let algebraicExponentiate = (dist1, dist2): t => FromDist( + ToDistCombination(Algebraic, #Exponentiate, #Dist(dist2)), + dist1, + ) + let pointwiseAdd = (dist1, dist2): t => FromDist( + ToDistCombination(Algebraic, #Add, #Dist(dist2)), + dist1, + ) + let pointwiseMultiply = (dist1, dist2): t => FromDist( + ToDistCombination(Pointwise, #Multiply, #Dist(dist2)), + dist1, + ) + let pointwiseDivide = (dist1, dist2): t => FromDist( + ToDistCombination(Pointwise, #Divide, #Dist(dist2)), + dist1, + ) + let pointwiseSubtract = (dist1, dist2): t => FromDist( + ToDistCombination(Pointwise, #Subtract, #Dist(dist2)), + dist1, + ) + let pointwiseLogarithm = (dist1, dist2): t => FromDist( + ToDistCombination(Pointwise, #Logarithm, #Dist(dist2)), + dist1, + ) + let pointwiseExponentiate = (dist1, dist2): t => FromDist( + ToDistCombination(Pointwise, #Exponentiate, #Dist(dist2)), + dist1, + ) + } +} diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res index eebb9efc..3c8f686a 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res @@ -1,3 +1,4 @@ +@genType type t = array // TODO: Refactor to raise correct error when not enough samples diff --git a/packages/squiggle-lang/src/rescript/TSInterface.res b/packages/squiggle-lang/src/rescript/TSInterface.res new file mode 100644 index 00000000..8df300f8 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/TSInterface.res @@ -0,0 +1,14 @@ +@genType +type functionCallInfo = GenericDist_Types.Operation.genericFunctionCallInfo; + +@genType +type env = DistributionOperation.env; + +@genType +type genericDist = GenericDist_Types.genericDist; + +@genType +type error = GenericDist_Types.error; + +@genType +let runDistributionOperation = DistributionOperation.run; \ No newline at end of file From e065a57a665e3c0cedb9588576f92742edb52b26 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 15:55:04 -0400 Subject: [PATCH 2/7] Added to index.ts --- packages/squiggle-lang/src/js/index.ts | 224 ++++++++++-------- .../DistributionOperation.res | 7 +- .../DistributionOperation.resi | 99 +++++--- .../GenericDist/GenericDist_Types.res | 62 ++++- .../src/rescript/TSInterface.res | 9 +- 5 files changed, 265 insertions(+), 136 deletions(-) diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 5f12bf56..a250c4fc 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -8,13 +8,39 @@ import type { export type { SamplingInputs, exportEnv, exportDistribution }; export type { t as DistPlus } from "../rescript/OldInterpreter/DistPlus.gen"; import type { Operation_genericFunctionCallInfo } from "../rescript/Distributions/GenericDist/GenericDist_Types.gen"; -import { genericDist } from "../rescript/TSInterface.gen"; import { - run as runR, + genericDist, + resultDist, + resultFloat, + resultString, +} from "../rescript/TSInterface.gen"; +import { env, - outputType, + Constructors_UsingDists_mean, + Constructors_UsingDists_sample, + Constructors_UsingDists_pdf, + Constructors_UsingDists_cdf, + Constructors_UsingDists_inv, + Constructors_UsingDists_normalize, + Constructors_UsingDists_toPointSet, + Constructors_UsingDists_toSampleSet, + Constructors_UsingDists_truncate, + Constructors_UsingDists_inspect, + Constructors_UsingDists_toString, + Constructors_UsingDists_toSparkline, + Constructors_UsingDists_algebraicAdd, + Constructors_UsingDists_algebraicMultiply, + Constructors_UsingDists_algebraicDivide, + Constructors_UsingDists_algebraicSubtract, + Constructors_UsingDists_algebraicLogarithm, + Constructors_UsingDists_algebraicExponentiate, + Constructors_UsingDists_pointwiseAdd, + Constructors_UsingDists_pointwiseMultiply, + Constructors_UsingDists_pointwiseDivide, + Constructors_UsingDists_pointwiseSubtract, + Constructors_UsingDists_pointwiseLogarithm, + Constructors_UsingDists_pointwiseExponentiate, } from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; -import { add } from "lodash"; export let defaultSamplingInputs: SamplingInputs = { sampleCount: 10000, @@ -42,140 +68,152 @@ class GenericDist { this.t = t; } - mean(): outputType { - return runR( + mean(): resultFloat { + return Constructors_UsingDists_mean({ env: this.env }, this.t); + } + + sample(): resultFloat { + return Constructors_UsingDists_sample({ env: this.env }, this.t); + } + + pdf(n: number): resultFloat { + return Constructors_UsingDists_pdf({ env: this.env }, this.t, n); + } + + cdf(n: number): resultFloat { + return Constructors_UsingDists_cdf({ env: this.env }, this.t, n); + } + + inv(n: number): resultFloat { + return Constructors_UsingDists_inv({ env: this.env }, this.t, n); + } + + normalize(): resultDist { + return Constructors_UsingDists_normalize({ env: this.env }, this.t); + } + + toPointSet(): resultDist { + return Constructors_UsingDists_toPointSet({ env: this.env }, this.t); + } + + toSampleSet(n: number): resultDist { + return Constructors_UsingDists_toSampleSet({ env: this.env }, this.t, n); + } + + truncate(left: number, right: number): resultDist { + return Constructors_UsingDists_truncate( { env: this.env }, - { tag: "FromDist", value: [{ tag: "ToFloat", value: "Mean" }, this.t] } + this.t, + left, + right ); } - pdf(n: number): outputType { - return runR( + inspect(): resultDist { + return Constructors_UsingDists_inspect({ env: this.env }, this.t); + } + + toString(): resultString { + return Constructors_UsingDists_toString({ env: this.env }, this.t); + } + + toSparkline(n: number): resultString { + return Constructors_UsingDists_toSparkline({ env: this.env }, this.t, n); + } + + algebraicAdd(d2: GenericDist): resultDist { + return Constructors_UsingDists_algebraicAdd( { env: this.env }, - { - tag: "FromDist", - value: [{ tag: "ToFloat", value: { NAME: "Pdf", VAL: n } }, this.t], - } + this.t, + d2.t ); } - cdf(n: number): outputType { - return runR( + algebraicMultiply(d2: GenericDist): resultDist { + return Constructors_UsingDists_algebraicMultiply( { env: this.env }, - { - tag: "FromDist", - value: [{ tag: "ToFloat", value: { NAME: "Pdf", VAL: n } }, this.t], - } + this.t, + d2.t ); } - inv(n: number): outputType { - return runR( + algebraicDivide(d2: GenericDist): resultDist { + return Constructors_UsingDists_algebraicDivide( { env: this.env }, - { - tag: "FromDist", - value: [{ tag: "ToFloat", value: { NAME: "Pdf", VAL: n } }, this.t], - } + this.t, + d2.t ); } - normalize(n: number): outputType { - return runR( + algebraicSubtract(d2: GenericDist): resultDist { + return Constructors_UsingDists_algebraicSubtract( { env: this.env }, - { - tag: "FromDist", - value: [{ tag: "ToDist", value: "Normalize" }, this.t], - } + this.t, + d2.t ); } - toPointSet(): outputType { - return runR( + algebraicLogarithm(d2: GenericDist): resultDist { + return Constructors_UsingDists_algebraicLogarithm( { env: this.env }, - { - tag: "FromDist", - value: [{ tag: "ToDist", value: "ToPointSet" }, this.t], - } + this.t, + d2.t ); } - inspect(): outputType { - return runR( + algebraicExponentiate(d2: GenericDist): resultDist { + return Constructors_UsingDists_algebraicExponentiate( { env: this.env }, - { tag: "FromDist", value: [{ tag: "ToDist", value: "Inspect" }, this.t] } + this.t, + d2.t ); } - toSampleSet(n: number): outputType { - return runR( + pointwiseAdd(d2: GenericDist): resultDist { + return Constructors_UsingDists_pointwiseAdd( { env: this.env }, - { - tag: "FromDist", - value: [ - { tag: "ToDist", value: { tag: "ToSampleSet", value: n } }, - this.t, - ], - } + this.t, + d2.t ); } - truncate( - left: null | undefined | number, - right: null | undefined | number - ): outputType { - return runR( + pointwiseMultiply(d2: GenericDist): resultDist { + return Constructors_UsingDists_pointwiseMultiply( { env: this.env }, - { - tag: "FromDist", - value: [ - { tag: "ToDist", value: { tag: "Truncate", value: [left, right] } }, - this.t, - ], - } + this.t, + d2.t ); } - toString(): outputType { - return runR( + pointwiseDivide(d2: GenericDist): resultDist { + return Constructors_UsingDists_pointwiseDivide( { env: this.env }, - { - tag: "FromDist", - value: [{ tag: "ToString", value: "ToString" }, this.t], - } + this.t, + d2.t ); } - toSparkline(n: number): outputType { - return runR( + pointwiseSubtract(d2: GenericDist): resultDist { + return Constructors_UsingDists_pointwiseSubtract( { env: this.env }, - { - tag: "FromDist", - value: [ - { tag: "ToString", value: { tag: "ToSparkline", value: n } }, - this.t, - ], - } + this.t, + d2.t ); } - add(g2: genericDist): outputType { - return runR( + pointwiseLogarithm(d2: GenericDist): resultDist { + return Constructors_UsingDists_pointwiseLogarithm( { env: this.env }, - { - tag: "FromDist", - value: [ - { - tag: "ToDistCombination", - value: [ - { - tag: "ToDistCombination", - value: ["Algebraic", "Add", { NAME: "Dist", VAL: g2 }], - }, - ], - }, - this.t, - ], - } + this.t, + d2.t + ); + } + + pointwiseExponentiate(d2: GenericDist): resultDist { + return Constructors_UsingDists_pointwiseExponentiate( + { env: this.env }, + this.t, + d2.t ); } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 1d25f64c..2014880f 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -190,10 +190,7 @@ module Constructors = { module UsingDists = { module C = GenericDist_Types.Constructors.UsingDists open OutputLocal - type dist = GenericDist_Types.genericDist - type fResult = result - type dResult = result - type sResult = result + type floatResult= result let mean = (~env, dist) => run(~env, C.mean(dist))->toFloatR let sample = (~env, dist) => run(~env, C.sample(dist))->toFloatR @@ -231,4 +228,4 @@ module Constructors = { let pointwiseExponentiate = (~env, dist1, dist2) => run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR } -} +} \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi index e39d5848..b0799dc9 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi @@ -4,19 +4,21 @@ type env = { xyPointLength: int, } +open GenericDist_Types + @genType type outputType = - | Dist(GenericDist_Types.genericDist) + | Dist(genericDist) | Float(float) | String(string) - | GenDistError(GenericDist_Types.error) + | GenDistError(error) @genType let run: (~env: env, GenericDist_Types.Operation.genericFunctionCallInfo) => outputType let runFromDist: ( ~env: env, ~functionCallInfo: GenericDist_Types.Operation.fromDist, - GenericDist_Types.genericDist, + genericDist, ) => outputType let runFromFloat: ( ~env: env, @@ -26,45 +28,70 @@ let runFromFloat: ( module Output: { type t = outputType - let toDist: t => option - let toDistR: t => result + let toDist: t => option + let toDistR: t => result let toFloat: t => option - let toFloatR: t => result + let toFloatR: t => result let toString: t => option - let toStringR: t => result - let toError: t => option + let toStringR: t => result + let toError: t => option let fmap: (~env: env, t, GenericDist_Types.Operation.singleParamaterFunction) => t } module Constructors: { module UsingDists: { - type dist = GenericDist_Types.genericDist - type fResult = result - type dResult = result - type sResult = result - let mean: (~env: env, dist) => fResult - let sample: (~env: env, dist) => fResult - let cdf: (~env: env, dist, float) => fResult - let inv: (~env: env, dist, float) => fResult - let pdf: (~env: env, dist, float) => fResult - let normalize: (~env: env, dist) => dResult - let toPointSet: (~env: env, dist) => dResult - let toSampleSet: (~env: env, dist, int) => dResult - let truncate: (~env: env, dist, option, option) => dResult - let inspect: (~env: env, dist) => dResult - let toString: (~env: env, dist) => sResult - let toSparkline: (~env: env, dist, int) => sResult - let algebraicAdd: (~env: env, dist, dist) => dResult - let algebraicMultiply: (~env: env, dist, dist) => dResult - let algebraicDivide: (~env: env, dist, dist) => dResult - let algebraicSubtract: (~env: env, dist, dist) => dResult - let algebraicLogarithm: (~env: env, dist, dist) => dResult - let algebraicExponentiate: (~env: env, dist, dist) => dResult - let pointwiseAdd: (~env: env, dist, dist) => dResult - let pointwiseMultiply: (~env: env, dist, dist) => dResult - let pointwiseDivide: (~env: env, dist, dist) => dResult - let pointwiseSubtract: (~env: env, dist, dist) => dResult - let pointwiseLogarithm: (~env: env, dist, dist) => dResult - let pointwiseExponentiate: (~env: env, dist, dist) => dResult + @genType + let mean: (~env: env, genericDist) => result + @genType + let sample: (~env: env, genericDist) => result + @genType + let cdf: (~env: env, genericDist, float) => result + @genType + let inv: (~env: env, genericDist, float) => result + @genType + let pdf: (~env: env, genericDist, float) => result + @genType + let normalize: (~env: env, genericDist) => result + @genType + let toPointSet: (~env: env, genericDist) => result + @genType + let toSampleSet: (~env: env, genericDist, int) => result + @genType + let truncate: ( + ~env: env, + genericDist, + option, + option, + ) => result + @genType + let inspect: (~env: env, genericDist) => result + @genType + let toString: (~env: env, genericDist) => result + @genType + let toSparkline: (~env: env, genericDist, int) => result + @genType + let algebraicAdd: (~env: env, genericDist, genericDist) => result + @genType + let algebraicMultiply: (~env: env, genericDist, genericDist) => result + @genType + let algebraicDivide: (~env: env, genericDist, genericDist) => result + @genType + let algebraicSubtract: (~env: env, genericDist, genericDist) => result + @genType + let algebraicLogarithm: (~env: env, genericDist, genericDist) => result + @genType + let algebraicExponentiate: (~env: env, genericDist, genericDist) => result + @genType + let pointwiseAdd: (~env: env, genericDist, genericDist) => result + @genType + let pointwiseMultiply: (~env: env, genericDist, genericDist) => result + @genType + let pointwiseDivide: (~env: env, genericDist, genericDist) => result + @genType + let pointwiseSubtract: (~env: env, genericDist, genericDist) => result + @genType + let pointwiseLogarithm: (~env: env, genericDist, genericDist) => result + @genType + let pointwiseExponentiate: (~env: env, genericDist, genericDist) => result } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res index f472a6e0..90189d00 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res @@ -114,7 +114,7 @@ module Constructors = { let inspect = (dist): t => FromDist(ToDist(Inspect), dist) let toString = (dist): t => FromDist(ToString(ToString), dist) let toSparkline = (dist, n): t => FromDist(ToString(ToSparkline(n)), dist) - let algebraicAdd = (dist1, dist2:genericDist): t => FromDist( + let algebraicAdd = (dist1, dist2: genericDist): t => FromDist( ToDistCombination(Algebraic, #Add, #Dist(dist2)), dist1, ) @@ -164,3 +164,63 @@ module Constructors = { ) } } + +module DistVariant = { + type t = + | Mean(genericDist) + | Sample(genericDist) + | Cdf(genericDist, float) + | Inv(genericDist, float) + | Pdf(genericDist, float) + | Normalize(genericDist) + | ToPointSet(genericDist) + | ToSampleSet(genericDist, int) + | Truncate(genericDist, option, option) + | Inspect(genericDist) + | ToString(genericDist) + | ToSparkline(genericDist, int) + | AlgebraicAdd(genericDist, genericDist) + | AlgebraicMultiply(genericDist, genericDist) + | AlgebraicDivide(genericDist, genericDist) + | AlgebraicSubtract(genericDist, genericDist) + | AlgebraicLogarithm(genericDist, genericDist) + | AlgebraicExponentiate(genericDist, genericDist) + | PointwiseAdd(genericDist, genericDist) + | PointwiseMultiply(genericDist, genericDist) + | PointwiseDivide(genericDist, genericDist) + | PointwiseSubtract(genericDist, genericDist) + | PointwiseLogarithm(genericDist, genericDist) + | PointwiseExponentiate(genericDist, genericDist) + + let toGenericFunctionCallInfo = (t: t) => + switch t { + | Mean(d) => Operation.FromDist(ToFloat(#Mean), d) + | Sample(d) => FromDist(ToFloat(#Mean), d) + | Cdf(d, f) => FromDist(ToFloat(#Cdf(f)), d) + | Inv(d, f) => FromDist(ToFloat(#Inv(f)), d) + | Pdf(d, f) => FromDist(ToFloat(#Pdf(f)), d) + | Normalize(d) => FromDist(ToDist(Normalize), d) + | ToPointSet(d) => FromDist(ToDist(ToPointSet), d) + | ToSampleSet(d, r) => FromDist(ToDist(ToSampleSet(r)), d) + | Truncate(d, left, right) => FromDist(ToDist(Truncate(left, right)), d) + | Inspect(d) => FromDist(ToDist(Inspect), d) + | ToString(d) => FromDist(ToString(ToString), d) + | ToSparkline(d, n) => FromDist(ToString(ToSparkline(n)), d) + | AlgebraicAdd(d1, d2) => FromDist(ToDistCombination(Algebraic, #Add, #Dist(d2)), d1) + | AlgebraicMultiply(d1, d2) => FromDist(ToDistCombination(Algebraic, #Multiply, #Dist(d2)), d1) + | AlgebraicDivide(d1, d2) => FromDist(ToDistCombination(Algebraic, #Divide, #Dist(d2)), d1) + | AlgebraicSubtract(d1, d2) => FromDist(ToDistCombination(Algebraic, #Subtract, #Dist(d2)), d1) + | AlgebraicLogarithm(d1, d2) => + FromDist(ToDistCombination(Algebraic, #Logarithm, #Dist(d2)), d1) + | AlgebraicExponentiate(d1, d2) => + FromDist(ToDistCombination(Algebraic, #Exponentiate, #Dist(d2)), d1) + | PointwiseAdd(d1, d2) => FromDist(ToDistCombination(Pointwise, #Add, #Dist(d2)), d1) + | PointwiseMultiply(d1, d2) => FromDist(ToDistCombination(Pointwise, #Multiply, #Dist(d2)), d1) + | PointwiseDivide(d1, d2) => FromDist(ToDistCombination(Pointwise, #Divide, #Dist(d2)), d1) + | PointwiseSubtract(d1, d2) => FromDist(ToDistCombination(Pointwise, #Subtract, #Dist(d2)), d1) + | PointwiseLogarithm(d1, d2) => + FromDist(ToDistCombination(Pointwise, #Logarithm, #Dist(d2)), d1) + | PointwiseExponentiate(d1, d2) => + FromDist(ToDistCombination(Pointwise, #Exponentiate, #Dist(d2)), d1) + } +} \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/TSInterface.res b/packages/squiggle-lang/src/rescript/TSInterface.res index 8df300f8..26b694a5 100644 --- a/packages/squiggle-lang/src/rescript/TSInterface.res +++ b/packages/squiggle-lang/src/rescript/TSInterface.res @@ -11,4 +11,11 @@ type genericDist = GenericDist_Types.genericDist; type error = GenericDist_Types.error; @genType -let runDistributionOperation = DistributionOperation.run; \ No newline at end of file +let runDistributionOperation = DistributionOperation.run; + +@genType +type resultDist = result +@genType +type resultFloat = result +@genType +type resultString = result \ No newline at end of file From 4c99a50d895328f87a7742ff0a461465ed0f154a Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 15:57:18 -0400 Subject: [PATCH 3/7] Fix from CR --- .../rescript/Distributions/GenericDist/GenericDist_Types.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res index 90189d00..45ad6f64 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res @@ -103,7 +103,7 @@ module Constructors = { module UsingDists = { let mean = (dist): t => FromDist(ToFloat(#Mean), dist) - let sample = (dist): t => FromDist(ToFloat(#Mean), dist) + let sample = (dist): t => FromDist(ToFloat(#Sample), dist) let cdf = (dist, f): t => FromDist(ToFloat(#Cdf(f)), dist) let inv = (dist, f): t => FromDist(ToFloat(#Inv(f)), dist) let pdf = (dist, f): t => FromDist(ToFloat(#Pdf(f)), dist) From d62ccc27bd9afd82573ff0d291ab52e301d72c47 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 16:09:00 -0400 Subject: [PATCH 4/7] Minor refactor of DistributionOperation Constructors --- .../DistributionOperation.res | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 2014880f..7d58af7b 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -190,42 +190,40 @@ module Constructors = { module UsingDists = { module C = GenericDist_Types.Constructors.UsingDists open OutputLocal - type floatResult= result - - let mean = (~env, dist) => run(~env, C.mean(dist))->toFloatR - let sample = (~env, dist) => run(~env, C.sample(dist))->toFloatR - let cdf = (~env, dist, f) => run(~env, C.cdf(dist, f))->toFloatR - let inv = (~env, dist, f) => run(~env, C.inv(dist, f))->toFloatR - let pdf = (~env, dist, f) => run(~env, C.pdf(dist, f))->toFloatR - let normalize = (~env, dist) => run(~env, C.normalize(dist))->toDistR - let toPointSet = (~env, dist) => run(~env, C.toPointSet(dist))->toDistR - let toSampleSet = (~env, dist, n) => run(~env, C.toSampleSet(dist, n))->toDistR + let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR + let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR + let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR + let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR + let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR + let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR + let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR + let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR let truncate = (~env, dist, leftCutoff, rightCutoff) => - run(~env, C.truncate(dist, leftCutoff, rightCutoff))->toDistR - let inspect = (~env, dist) => run(~env, C.inspect(dist))->toDistR - let toString = (~env, dist) => run(~env, C.toString(dist))->toStringR - let toSparkline = (~env, dist, buckets) => run(~env, C.toSparkline(dist, buckets))->toStringR - let algebraicAdd = (~env, dist1, dist2) => run(~env, C.algebraicAdd(dist1, dist2))->toDistR + C.truncate(dist, leftCutoff, rightCutoff)->run(~env)->toDistR + let inspect = (~env, dist) => C.inspect(dist)->run(~env)->toDistR + let toString = (~env, dist) => C.toString(dist)->run(~env)->toStringR + let toSparkline = (~env, dist, buckets) => C.toSparkline(dist, buckets)->run(~env)->toStringR + let algebraicAdd = (~env, dist1, dist2) => C.algebraicAdd(dist1, dist2)->run(~env)->toDistR let algebraicMultiply = (~env, dist1, dist2) => - run(~env, C.algebraicMultiply(dist1, dist2))->toDistR + C.algebraicMultiply(dist1, dist2)->run(~env)->toDistR let algebraicDivide = (~env, dist1, dist2) => - run(~env, C.algebraicDivide(dist1, dist2))->toDistR + C.algebraicDivide(dist1, dist2)->run(~env)->toDistR let algebraicSubtract = (~env, dist1, dist2) => - run(~env, C.algebraicSubtract(dist1, dist2))->toDistR + C.algebraicSubtract(dist1, dist2)->run(~env)->toDistR let algebraicLogarithm = (~env, dist1, dist2) => - run(~env, C.algebraicLogarithm(dist1, dist2))->toDistR + C.algebraicLogarithm(dist1, dist2)->run(~env)->toDistR let algebraicExponentiate = (~env, dist1, dist2) => - run(~env, C.algebraicExponentiate(dist1, dist2))->toDistR - let pointwiseAdd = (~env, dist1, dist2) => run(~env, C.pointwiseAdd(dist1, dist2))->toDistR + C.algebraicExponentiate(dist1, dist2)->run(~env)->toDistR + let pointwiseAdd = (~env, dist1, dist2) => C.pointwiseAdd(dist1, dist2)->run(~env)->toDistR let pointwiseMultiply = (~env, dist1, dist2) => - run(~env, C.pointwiseMultiply(dist1, dist2))->toDistR + C.pointwiseMultiply(dist1, dist2)->run(~env)->toDistR let pointwiseDivide = (~env, dist1, dist2) => - run(~env, C.pointwiseDivide(dist1, dist2))->toDistR + C.pointwiseDivide(dist1, dist2)->run(~env)->toDistR let pointwiseSubtract = (~env, dist1, dist2) => - run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR + C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR let pointwiseLogarithm = (~env, dist1, dist2) => - run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR + C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR let pointwiseExponentiate = (~env, dist1, dist2) => - run(~env, C.pointwiseSubtract(dist1, dist2))->toDistR + C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR } -} \ No newline at end of file +} From 0af0c9e274cd8ab49e32850b4f4f0a7c9373cc55 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 19:48:53 -0400 Subject: [PATCH 5/7] Added tests for index.js and fixed some corresponding functionality --- packages/squiggle-lang/__tests__/JS__Test.ts | 82 ++++-- packages/squiggle-lang/src/js/index.ts | 239 +++++++++--------- .../DistributionOperation.res | 4 +- .../DistributionOperation.resi | 2 - .../Distributions/GenericDist/GenericDist.res | 4 +- .../GenericDist/GenericDist_Types.res | 1 + .../Distributions/PointSetDist/Continuous.res | 3 + .../PointSetDist/PointSetDist.res | 3 +- 8 files changed, 191 insertions(+), 147 deletions(-) diff --git a/packages/squiggle-lang/__tests__/JS__Test.ts b/packages/squiggle-lang/__tests__/JS__Test.ts index aded69c1..07a4cabe 100644 --- a/packages/squiggle-lang/__tests__/JS__Test.ts +++ b/packages/squiggle-lang/__tests__/JS__Test.ts @@ -1,34 +1,66 @@ -import { run } from '../src/js/index'; +import { run, GenericDist, resultMap } from "../src/js/index"; let testRun = (x: string) => { - let result = run(x) - if(result.tag == 'Ok'){ - return { tag: 'Ok', value: result.value.exports } + let result = run(x); + if (result.tag == "Ok") { + return { tag: "Ok", value: result.value.exports }; + } else { + return result; } - else { - return result - } -} +}; describe("Simple calculations and results", () => { - test("mean(normal(5,2))", () => { - expect(testRun("mean(normal(5,2))")).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 5 } ] }) - }) - test("10+10", () => { - let foo = testRun("10 + 10") - expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 20 } ] }) - }) -}) + test("mean(normal(5,2))", () => { + expect(testRun("mean(normal(5,2))")).toEqual({ + tag: "Ok", + value: [{ NAME: "Float", VAL: 5 }], + }); + }); + test("10+10", () => { + let foo = testRun("10 + 10"); + expect(foo).toEqual({ tag: "Ok", value: [{ NAME: "Float", VAL: 20 }] }); + }); +}); describe("Log function", () => { - test("log(1) = 0", () => { - let foo = testRun("log(1)") - expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 0} ]}) - }) -}) + test("log(1) = 0", () => { + let foo = testRun("log(1)"); + expect(foo).toEqual({ tag: "Ok", value: [{ NAME: "Float", VAL: 0 }] }); + }); +}); describe("Multimodal too many weights error", () => { - test("mm(0,0,[0,0,0])", () => { - let foo = testRun("mm(0,0,[0,0,0])") - expect(foo).toEqual({ "tag": "Error", "value": "Function multimodal error: Too many weights provided" }) - }) + test("mm(0,0,[0,0,0])", () => { + let foo = testRun("mm(0,0,[0,0,0])"); + expect(foo).toEqual({ + tag: "Error", + value: "Function multimodal error: Too many weights provided", + }); + }); +}); + +describe("GenericDist", () => { + let dist = new GenericDist( + { tag: "SampleSet", value: [3, 4, 5, 6, 6, 7, 10, 15, 30] }, + { sampleCount: 100, xyPointLength: 100 } + ); + test("mean", () => { + expect(dist.mean().value).toBeCloseTo(3.737); + }); + test("pdf", () => { + expect(dist.pdf(5.0).value).toBeCloseTo(0.0431); + }); + test("cdf", () => { + expect(dist.cdf(5.0).value).toBeCloseTo(0.155); + }); + test("inv", () => { + expect(dist.inv(0.5).value).toBeCloseTo(9.458); + }); + test("toPointSet", () => { + expect( + resultMap(dist.toPointSet(), (r: GenericDist) => r.toString()).value.value + ).toBe("Point Set Distribution"); + }); + test("toSparkline", () => { + expect(dist.toSparkline(20).value).toBe("▁▁▃▅███▆▄▃▂▁▁▂▂▃▂▁▁▁"); + }); }); diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index a250c4fc..b690d581 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -7,7 +7,6 @@ import type { } from "../rescript/ProgramEvaluator.gen"; export type { SamplingInputs, exportEnv, exportDistribution }; export type { t as DistPlus } from "../rescript/OldInterpreter/DistPlus.gen"; -import type { Operation_genericFunctionCallInfo } from "../rescript/Distributions/GenericDist/GenericDist_Types.gen"; import { genericDist, resultDist, @@ -16,30 +15,30 @@ import { } from "../rescript/TSInterface.gen"; import { env, - Constructors_UsingDists_mean, - Constructors_UsingDists_sample, - Constructors_UsingDists_pdf, - Constructors_UsingDists_cdf, - Constructors_UsingDists_inv, - Constructors_UsingDists_normalize, - Constructors_UsingDists_toPointSet, - Constructors_UsingDists_toSampleSet, - Constructors_UsingDists_truncate, - Constructors_UsingDists_inspect, - Constructors_UsingDists_toString, - Constructors_UsingDists_toSparkline, - Constructors_UsingDists_algebraicAdd, - Constructors_UsingDists_algebraicMultiply, - Constructors_UsingDists_algebraicDivide, - Constructors_UsingDists_algebraicSubtract, - Constructors_UsingDists_algebraicLogarithm, - Constructors_UsingDists_algebraicExponentiate, - Constructors_UsingDists_pointwiseAdd, - Constructors_UsingDists_pointwiseMultiply, - Constructors_UsingDists_pointwiseDivide, - Constructors_UsingDists_pointwiseSubtract, - Constructors_UsingDists_pointwiseLogarithm, - Constructors_UsingDists_pointwiseExponentiate, + 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_algebraicExponentiate, + Constructors_pointwiseAdd, + Constructors_pointwiseMultiply, + Constructors_pointwiseDivide, + Constructors_pointwiseSubtract, + Constructors_pointwiseLogarithm, + Constructors_pointwiseExponentiate, } from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; export let defaultSamplingInputs: SamplingInputs = { @@ -60,160 +59,172 @@ export function run( return runAll(squiggleString, si, env); } -class GenericDist { +export function resultMap( + r: + | { + tag: "Ok"; + value: any; + } + | { + tag: "Error"; + value: any; + }, + mapFn: any +): + | { + tag: "Ok"; + value: any; + } + | { + tag: "Error"; + value: any; + } { + if (r.tag === "Ok") { + return { tag: "Ok", value: mapFn(r.value) }; + } else { + return r; + } +} + +export class GenericDist { t: genericDist; env: env; constructor(t: genericDist, env: env) { this.t = t; + this.env = env; + return this; } - mean(): resultFloat { - return Constructors_UsingDists_mean({ env: this.env }, this.t); + mapResultDist(r: resultDist) { + return resultMap(r, (v: genericDist) => new GenericDist(v, this.env)); + } + + mean() { + return Constructors_mean({ env: this.env }, this.t); } sample(): resultFloat { - return Constructors_UsingDists_sample({ env: this.env }, this.t); + return Constructors_sample({ env: this.env }, this.t); } pdf(n: number): resultFloat { - return Constructors_UsingDists_pdf({ env: this.env }, this.t, n); + return Constructors_pdf({ env: this.env }, this.t, n); } cdf(n: number): resultFloat { - return Constructors_UsingDists_cdf({ env: this.env }, this.t, n); + return Constructors_cdf({ env: this.env }, this.t, n); } inv(n: number): resultFloat { - return Constructors_UsingDists_inv({ env: this.env }, this.t, n); + return Constructors_inv({ env: this.env }, this.t, n); } - normalize(): resultDist { - return Constructors_UsingDists_normalize({ env: this.env }, this.t); - } - - toPointSet(): resultDist { - return Constructors_UsingDists_toPointSet({ env: this.env }, this.t); - } - - toSampleSet(n: number): resultDist { - return Constructors_UsingDists_toSampleSet({ env: this.env }, this.t, n); - } - - truncate(left: number, right: number): resultDist { - return Constructors_UsingDists_truncate( - { env: this.env }, - this.t, - left, - right + normalize() { + return this.mapResultDist( + Constructors_normalize({ env: this.env }, this.t) ); } - inspect(): resultDist { - return Constructors_UsingDists_inspect({ env: this.env }, this.t); + toPointSet() { + return this.mapResultDist( + Constructors_toPointSet({ env: this.env }, this.t) + ); + } + + toSampleSet(n: number) { + return this.mapResultDist( + Constructors_toSampleSet({ env: this.env }, this.t, n) + ); + } + + truncate(left: number, right: number) { + return this.mapResultDist( + Constructors_truncate({ env: this.env }, this.t, left, right) + ); + } + + inspect() { + return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t)); } toString(): resultString { - return Constructors_UsingDists_toString({ env: this.env }, this.t); + return Constructors_toString({ env: this.env }, this.t); } toSparkline(n: number): resultString { - return Constructors_UsingDists_toSparkline({ env: this.env }, this.t, n); + return Constructors_toSparkline({ env: this.env }, this.t, n); } - algebraicAdd(d2: GenericDist): resultDist { - return Constructors_UsingDists_algebraicAdd( - { env: this.env }, - this.t, - d2.t + algebraicAdd(d2: GenericDist) { + return this.mapResultDist( + Constructors_algebraicAdd({ env: this.env }, this.t, d2.t) ); } - algebraicMultiply(d2: GenericDist): resultDist { - return Constructors_UsingDists_algebraicMultiply( - { env: this.env }, - this.t, - d2.t + algebraicMultiply(d2: GenericDist) { + return this.mapResultDist( + Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t) ); } - algebraicDivide(d2: GenericDist): resultDist { - return Constructors_UsingDists_algebraicDivide( - { env: this.env }, - this.t, - d2.t + algebraicDivide(d2: GenericDist) { + return this.mapResultDist( + Constructors_algebraicDivide({ env: this.env }, this.t, d2.t) ); } - algebraicSubtract(d2: GenericDist): resultDist { - return Constructors_UsingDists_algebraicSubtract( - { env: this.env }, - this.t, - d2.t + algebraicSubtract(d2: GenericDist) { + return this.mapResultDist( + Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t) ); } - algebraicLogarithm(d2: GenericDist): resultDist { - return Constructors_UsingDists_algebraicLogarithm( - { env: this.env }, - this.t, - d2.t + algebraicLogarithm(d2: GenericDist) { + return this.mapResultDist( + Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t) ); } - algebraicExponentiate(d2: GenericDist): resultDist { - return Constructors_UsingDists_algebraicExponentiate( - { env: this.env }, - this.t, - d2.t + algebraicExponentiate(d2: GenericDist) { + return this.mapResultDist( + Constructors_algebraicExponentiate({ env: this.env }, this.t, d2.t) ); } - pointwiseAdd(d2: GenericDist): resultDist { - return Constructors_UsingDists_pointwiseAdd( - { env: this.env }, - this.t, - d2.t + pointwiseAdd(d2: GenericDist) { + return this.mapResultDist( + Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t) ); } - pointwiseMultiply(d2: GenericDist): resultDist { - return Constructors_UsingDists_pointwiseMultiply( - { env: this.env }, - this.t, - d2.t + pointwiseMultiply(d2: GenericDist) { + return this.mapResultDist( + Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t) ); } - pointwiseDivide(d2: GenericDist): resultDist { - return Constructors_UsingDists_pointwiseDivide( - { env: this.env }, - this.t, - d2.t + pointwiseDivide(d2: GenericDist) { + return this.mapResultDist( + Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t) ); } - pointwiseSubtract(d2: GenericDist): resultDist { - return Constructors_UsingDists_pointwiseSubtract( - { env: this.env }, - this.t, - d2.t + pointwiseSubtract(d2: GenericDist) { + return this.mapResultDist( + Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t) ); } - pointwiseLogarithm(d2: GenericDist): resultDist { - return Constructors_UsingDists_pointwiseLogarithm( - { env: this.env }, - this.t, - d2.t + pointwiseLogarithm(d2: GenericDist) { + return this.mapResultDist( + Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t) ); } - pointwiseExponentiate(d2: GenericDist): resultDist { - return Constructors_UsingDists_pointwiseExponentiate( - { env: this.env }, - this.t, - d2.t + pointwiseExponentiate(d2: GenericDist) { + return this.mapResultDist( + Constructors_pointwiseExponentiate({ env: this.env }, this.t, d2.t) ); } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 7d58af7b..12b94bcc 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -187,8 +187,7 @@ module Output = { } module Constructors = { - module UsingDists = { - module C = GenericDist_Types.Constructors.UsingDists + module C = GenericDist_Types.Constructors.UsingDists; open OutputLocal let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR @@ -225,5 +224,4 @@ module Constructors = { C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR let pointwiseExponentiate = (~env, dist1, dist2) => C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR - } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi index b0799dc9..ce0fca72 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi @@ -39,7 +39,6 @@ module Output: { } module Constructors: { - module UsingDists: { @genType let mean: (~env: env, genericDist) => result @genType @@ -93,5 +92,4 @@ module Constructors: { let pointwiseLogarithm: (~env: env, genericDist, genericDist) => result @genType let pointwiseExponentiate: (~env: env, genericDist, genericDist) => result - } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res index 58366a77..4815e98c 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res @@ -83,8 +83,8 @@ let toPointSet = ( let toSparkline = (t: t, ~sampleCount: int, ~buckets: int=20, unit): result => t - ->toPointSet(~xSelection=#Linear, ~xyPointLength=buckets, ~sampleCount, ()) - ->E.R.bind(r => r->PointSetDist.toSparkline->E.R2.errMap(r => Error(GenericDist_Types.Other(r)))) + ->toPointSet(~xSelection=#Linear, ~xyPointLength=buckets*3, ~sampleCount, ()) + ->E.R.bind(r => r->PointSetDist.toSparkline(buckets)->E.R2.errMap(r => Error(GenericDist_Types.Other(r)))) module Truncate = { let trySymbolicSimplification = (leftCutoff, rightCutoff, t: t): option => diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res index 45ad6f64..1bfb3e82 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res @@ -102,6 +102,7 @@ module Constructors = { type t = Operation.genericFunctionCallInfo module UsingDists = { + @genType let mean = (dist): t => FromDist(ToFloat(#Mean), dist) let sample = (dist): t => FromDist(ToFloat(#Sample), dist) let cdf = (dist, f): t => FromDist(ToFloat(#Cdf(f)), dist) diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res index f01457b7..aa27fb62 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res @@ -249,6 +249,9 @@ module T = Dist({ ) }) +let downsampleEquallyOverX = (length, t): t => + t |> shapeMap(XYShape.XsConversion.proportionEquallyOverX(length)) + /* This simply creates multiple copies of the continuous distribution, scaled and shifted according to each discrete data point, and then adds them all together. */ let combineAlgebraicallyWithDiscrete = ( diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res index 8224f4cb..c7bec8a9 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res @@ -203,7 +203,8 @@ let operate = (distToFloatOp: Operation.distToFloatOperation, s): float => | #Mean => T.mean(s) } -let toSparkline = (t: t) => +let toSparkline = (t: t, n) => T.toContinuous(t) + ->E.O2.fmap(Continuous.downsampleEquallyOverX(n)) ->E.O2.toResult("toContinous Error: Could not convert into continuous distribution") ->E.R2.fmap(r => Continuous.getShape(r).ys->Sparklines.create()) \ No newline at end of file From 2dc57bedc57a5b4545787b1e88a46c5cce51854b Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 21:31:08 -0400 Subject: [PATCH 6/7] Added more tests to JS__Test.ts, and added SampleN functionality to SampleSetDist --- packages/squiggle-lang/__tests__/JS__Test.ts | 22 ++++++++++++++++++- .../DistributionOperation.res | 4 ++-- .../Distributions/GenericDist/GenericDist.res | 8 ++++--- .../GenericDist/GenericDist_Types.res | 2 +- .../Distributions/SampleSetDist/SampleSet.res | 14 ++++++++++++ .../squiggle-lang/src/rescript/Utility/E.res | 2 ++ 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/packages/squiggle-lang/__tests__/JS__Test.ts b/packages/squiggle-lang/__tests__/JS__Test.ts index 07a4cabe..ba2f91f4 100644 --- a/packages/squiggle-lang/__tests__/JS__Test.ts +++ b/packages/squiggle-lang/__tests__/JS__Test.ts @@ -39,10 +39,18 @@ describe("Multimodal too many weights error", () => { }); describe("GenericDist", () => { + + //It's important that sampleCount is less than 9. If it's more, than that will create randomness + let env = { sampleCount: 8, xyPointLength: 100 }; let dist = new GenericDist( { tag: "SampleSet", value: [3, 4, 5, 6, 6, 7, 10, 15, 30] }, - { sampleCount: 100, xyPointLength: 100 } + env ); + let dist2 = new GenericDist( + { tag: "SampleSet", value: [20, 22, 24, 29, 30, 35, 38, 44, 52] }, + env + ); + test("mean", () => { expect(dist.mean().value).toBeCloseTo(3.737); }); @@ -63,4 +71,16 @@ describe("GenericDist", () => { test("toSparkline", () => { expect(dist.toSparkline(20).value).toBe("▁▁▃▅███▆▄▃▂▁▁▂▂▃▂▁▁▁"); }); + test("algebraicAdd", () => { + expect( + resultMap(dist.algebraicAdd(dist2), (r: GenericDist) => r.toSparkline(20)) + .value.value + ).toBe("▁▁▂▄▆████▇▆▄▄▃▃▃▂▁▁▁"); + }); + test("pointwiseAdd", () => { + expect( + resultMap(dist.pointwiseAdd(dist2), (r: GenericDist) => r.toSparkline(20)) + .value.value + ).toBe("▁▂▅██▅▅▅▆▇█▆▅▃▃▂▂▁▁▁"); + }); }); diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 12b94bcc..11e7f190 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -221,7 +221,7 @@ module Constructors = { let pointwiseSubtract = (~env, dist1, dist2) => C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR let pointwiseLogarithm = (~env, dist1, dist2) => - C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR + C.pointwiseLogarithm(dist1, dist2)->run(~env)->toDistR let pointwiseExponentiate = (~env, dist1, dist2) => - C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR + C.pointwiseExponentiate(dist1, dist2)->run(~env)->toDistR } diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res index 4815e98c..c321dc4a 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res @@ -10,7 +10,7 @@ let sampleN = (t: t, n) => switch t { | PointSet(r) => Ok(PointSetDist.sampleNRendered(n, r)) | Symbolic(r) => Ok(SymbolicDist.T.sampleN(n, r)) - | SampleSet(_) => Error(GenericDist_Types.NotYetImplemented) + | SampleSet(r) => Ok(SampleSet.sampleN(r, n)) } let fromFloat = (f: float): t => Symbolic(SymbolicDist.Float.make(f)) @@ -83,8 +83,10 @@ let toPointSet = ( let toSparkline = (t: t, ~sampleCount: int, ~buckets: int=20, unit): result => t - ->toPointSet(~xSelection=#Linear, ~xyPointLength=buckets*3, ~sampleCount, ()) - ->E.R.bind(r => r->PointSetDist.toSparkline(buckets)->E.R2.errMap(r => Error(GenericDist_Types.Other(r)))) + ->toPointSet(~xSelection=#Linear, ~xyPointLength=buckets * 3, ~sampleCount, ()) + ->E.R.bind(r => + r->PointSetDist.toSparkline(buckets)->E.R2.errMap(r => Error(GenericDist_Types.Other(r))) + ) module Truncate = { let trySymbolicSimplification = (leftCutoff, rightCutoff, t: t): option => diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res index 1bfb3e82..b0a30d52 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res @@ -140,7 +140,7 @@ module Constructors = { dist1, ) let pointwiseAdd = (dist1, dist2): t => FromDist( - ToDistCombination(Algebraic, #Add, #Dist(dist2)), + ToDistCombination(Pointwise, #Add, #Dist(dist2)), dist1, ) let pointwiseMultiply = (dist1, dist2): t => FromDist( diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res index 3c8f686a..07855686 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res @@ -60,6 +60,7 @@ module Internals = { : { let _ = Js.Array.push(element, continuous) } + () }) (continuous, discrete) @@ -143,4 +144,17 @@ let toPointSetDist = ( } samplesParse +} + +let sample = (t: t): float => { + let i = E.Int.random(~min=0, ~max=E.A.length(t) - 1) + E.A.unsafe_get(t, i) +} + +let sampleN = (t: t, n) => { + if n <= E.A.length(t) { + E.A.slice(t, ~offset=0, ~len=n) + } else { + Belt.Array.makeBy(n, _ => sample(t)) + } } \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index 01dbde7d..16d87896 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -24,6 +24,7 @@ module FloatFloatMap = { module Int = { let max = (i1: int, i2: int) => i1 > i2 ? i1 : i2 + let random = (~min, ~max) => Js.Math.random_int(min, max) } /* Utils */ module U = { @@ -277,6 +278,7 @@ module A = { let fold_right = Array.fold_right let concatMany = Belt.Array.concatMany let keepMap = Belt.Array.keepMap + let slice = Belt.Array.slice let init = Array.init let reduce = Belt.Array.reduce let reducei = Belt.Array.reduceWithIndex From 54b6b18d3a7d4c60e4755593c2c65495dbe145dc Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 8 Apr 2022 22:55:06 -0400 Subject: [PATCH 7/7] Cleanup and commenting for PR --- packages/squiggle-lang/src/js/index.ts | 23 ++---- .../DistributionOperation.res | 79 ++++++++++--------- .../Distributions/GenericDist/GenericDist.res | 12 ++- .../GenericDist/GenericDist.resi | 2 +- .../GenericDist/GenericDist_Types.res | 74 +++-------------- .../PointSetDist/PointSetDist.res | 4 +- .../Distributions/SampleSetDist/SampleSet.res | 11 ++- .../src/rescript/TSInterface.res | 21 ----- .../src/rescript/TypescriptInterface.res | 24 ++++++ 9 files changed, 105 insertions(+), 145 deletions(-) delete mode 100644 packages/squiggle-lang/src/rescript/TSInterface.res create mode 100644 packages/squiggle-lang/src/rescript/TypescriptInterface.res diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index b690d581..25515db6 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -9,12 +9,12 @@ export type { SamplingInputs, exportEnv, exportDistribution }; export type { t as DistPlus } from "../rescript/OldInterpreter/DistPlus.gen"; import { genericDist, + env, resultDist, resultFloat, resultString, -} from "../rescript/TSInterface.gen"; +} from "../rescript/TypescriptInterface.gen"; import { - env, Constructors_mean, Constructors_sample, Constructors_pdf, @@ -59,18 +59,9 @@ export function run( return runAll(squiggleString, si, env); } -export function resultMap( - r: - | { - tag: "Ok"; - value: any; - } - | { - tag: "Error"; - value: any; - }, - mapFn: any -): +//This is clearly not fully typed. I think later we should use a functional library to +// provide a better Either type and corresponding functions. +type result = | { tag: "Ok"; value: any; @@ -78,7 +69,9 @@ export function resultMap( | { tag: "Error"; value: any; - } { + }; + +export function resultMap(r: result, mapFn: any): result { if (r.tag === "Ok") { return { tag: "Ok", value: mapFn(r.value) }; } else { diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res index 11e7f190..a36674db 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res @@ -114,8 +114,8 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ->E.R2.fmap(r => Float(r)) ->OutputLocal.fromResult | ToString(ToString) => dist->GenericDist.toString->String - | ToString(ToSparkline(buckets)) => - GenericDist.toSparkline(dist, ~sampleCount, ~buckets, ()) + | ToString(ToSparkline(bucketCount)) => + GenericDist.toSparkline(dist, ~sampleCount, ~bucketCount, ()) ->E.R2.fmap(r => String(r)) ->OutputLocal.fromResult | ToDist(Inspect) => { @@ -186,42 +186,43 @@ module Output = { } } +// See comment above GenericDist_Types.Constructors to explain the purpose of this module. +// I tried having another internal module called UsingDists, similar to how its done in +// GenericDist_Types.Constructors. However, this broke GenType for me, so beware. module Constructors = { - module C = GenericDist_Types.Constructors.UsingDists; - open OutputLocal - let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR - let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR - let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR - let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR - let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR - let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR - let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR - let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR - let truncate = (~env, dist, leftCutoff, rightCutoff) => - C.truncate(dist, leftCutoff, rightCutoff)->run(~env)->toDistR - let inspect = (~env, dist) => C.inspect(dist)->run(~env)->toDistR - let toString = (~env, dist) => C.toString(dist)->run(~env)->toStringR - let toSparkline = (~env, dist, buckets) => C.toSparkline(dist, buckets)->run(~env)->toStringR - let algebraicAdd = (~env, dist1, dist2) => C.algebraicAdd(dist1, dist2)->run(~env)->toDistR - let algebraicMultiply = (~env, dist1, dist2) => - C.algebraicMultiply(dist1, dist2)->run(~env)->toDistR - let algebraicDivide = (~env, dist1, dist2) => - C.algebraicDivide(dist1, dist2)->run(~env)->toDistR - let algebraicSubtract = (~env, dist1, dist2) => - C.algebraicSubtract(dist1, dist2)->run(~env)->toDistR - let algebraicLogarithm = (~env, dist1, dist2) => - C.algebraicLogarithm(dist1, dist2)->run(~env)->toDistR - let algebraicExponentiate = (~env, dist1, dist2) => - C.algebraicExponentiate(dist1, dist2)->run(~env)->toDistR - let pointwiseAdd = (~env, dist1, dist2) => C.pointwiseAdd(dist1, dist2)->run(~env)->toDistR - let pointwiseMultiply = (~env, dist1, dist2) => - C.pointwiseMultiply(dist1, dist2)->run(~env)->toDistR - let pointwiseDivide = (~env, dist1, dist2) => - C.pointwiseDivide(dist1, dist2)->run(~env)->toDistR - let pointwiseSubtract = (~env, dist1, dist2) => - C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR - let pointwiseLogarithm = (~env, dist1, dist2) => - C.pointwiseLogarithm(dist1, dist2)->run(~env)->toDistR - let pointwiseExponentiate = (~env, dist1, dist2) => - C.pointwiseExponentiate(dist1, dist2)->run(~env)->toDistR + module C = GenericDist_Types.Constructors.UsingDists + open OutputLocal + let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR + let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR + let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR + let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR + let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR + let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR + let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR + let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR + let truncate = (~env, dist, leftCutoff, rightCutoff) => + C.truncate(dist, leftCutoff, rightCutoff)->run(~env)->toDistR + let inspect = (~env, dist) => C.inspect(dist)->run(~env)->toDistR + let toString = (~env, dist) => C.toString(dist)->run(~env)->toStringR + let toSparkline = (~env, dist, bucketCount) => C.toSparkline(dist, bucketCount)->run(~env)->toStringR + let algebraicAdd = (~env, dist1, dist2) => C.algebraicAdd(dist1, dist2)->run(~env)->toDistR + let algebraicMultiply = (~env, dist1, dist2) => + C.algebraicMultiply(dist1, dist2)->run(~env)->toDistR + let algebraicDivide = (~env, dist1, dist2) => C.algebraicDivide(dist1, dist2)->run(~env)->toDistR + let algebraicSubtract = (~env, dist1, dist2) => + C.algebraicSubtract(dist1, dist2)->run(~env)->toDistR + let algebraicLogarithm = (~env, dist1, dist2) => + C.algebraicLogarithm(dist1, dist2)->run(~env)->toDistR + let algebraicExponentiate = (~env, dist1, dist2) => + C.algebraicExponentiate(dist1, dist2)->run(~env)->toDistR + let pointwiseAdd = (~env, dist1, dist2) => C.pointwiseAdd(dist1, dist2)->run(~env)->toDistR + let pointwiseMultiply = (~env, dist1, dist2) => + C.pointwiseMultiply(dist1, dist2)->run(~env)->toDistR + let pointwiseDivide = (~env, dist1, dist2) => C.pointwiseDivide(dist1, dist2)->run(~env)->toDistR + let pointwiseSubtract = (~env, dist1, dist2) => + C.pointwiseSubtract(dist1, dist2)->run(~env)->toDistR + let pointwiseLogarithm = (~env, dist1, dist2) => + C.pointwiseLogarithm(dist1, dist2)->run(~env)->toDistR + let pointwiseExponentiate = (~env, dist1, dist2) => + C.pointwiseExponentiate(dist1, dist2)->run(~env)->toDistR } diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res index c321dc4a..6bcbb221 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res @@ -81,11 +81,17 @@ let toPointSet = ( } } -let toSparkline = (t: t, ~sampleCount: int, ~buckets: int=20, unit): result => +/* + PointSetDist.toSparkline calls "downsampleEquallyOverX", which downsamples it to n=bucketCount. + It first needs a pointSetDist, so we convert to a pointSetDist. In this process we want the + xyPointLength to be a bit longer than the eventual toSparkline downsampling. I chose 3 + fairly arbitrarily. + */ +let toSparkline = (t: t, ~sampleCount: int, ~bucketCount: int=20, unit): result => t - ->toPointSet(~xSelection=#Linear, ~xyPointLength=buckets * 3, ~sampleCount, ()) + ->toPointSet(~xSelection=#Linear, ~xyPointLength=bucketCount * 3, ~sampleCount, ()) ->E.R.bind(r => - r->PointSetDist.toSparkline(buckets)->E.R2.errMap(r => Error(GenericDist_Types.Other(r))) + r->PointSetDist.toSparkline(bucketCount)->E.R2.errMap(r => Error(GenericDist_Types.Other(r))) ) module Truncate = { diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi index 5fa24de9..adf3b9d4 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi @@ -26,7 +26,7 @@ let toPointSet: ( ~xSelection: GenericDist_Types.Operation.pointsetXSelection=?, unit, ) => result -let toSparkline: (t, ~sampleCount: int, ~buckets: int=?, unit) => result +let toSparkline: (t, ~sampleCount: int, ~bucketCount: int=?, unit) => result let truncate: ( t, diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res index b0a30d52..b3aeddac 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res @@ -98,6 +98,14 @@ module Operation = { } } +/* +It can be a pain to write out the genericFunctionCallInfo. The constructors help with this. +This code only covers some of genericFunctionCallInfo: many arguments could be called with either a +float or a distribution. The "UsingDists" module assumes that everything is a distribution. +This is a tradeoff of some generality in order to get a bit more simplicity. +I could see having a longer interface in the future, but it could be messy. +Like, algebraicAddDistFloat vs. algebraicAddDistDist +*/ module Constructors = { type t = Operation.genericFunctionCallInfo @@ -105,9 +113,9 @@ module Constructors = { @genType let mean = (dist): t => FromDist(ToFloat(#Mean), dist) let sample = (dist): t => FromDist(ToFloat(#Sample), dist) - let cdf = (dist, f): t => FromDist(ToFloat(#Cdf(f)), dist) - let inv = (dist, f): t => FromDist(ToFloat(#Inv(f)), dist) - let pdf = (dist, f): t => FromDist(ToFloat(#Pdf(f)), dist) + let cdf = (dist, x): t => FromDist(ToFloat(#Cdf(x)), dist) + let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist) + let pdf = (dist, x): t => FromDist(ToFloat(#Pdf(x)), dist) let normalize = (dist): t => FromDist(ToDist(Normalize), dist) let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist) let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist) @@ -165,63 +173,3 @@ module Constructors = { ) } } - -module DistVariant = { - type t = - | Mean(genericDist) - | Sample(genericDist) - | Cdf(genericDist, float) - | Inv(genericDist, float) - | Pdf(genericDist, float) - | Normalize(genericDist) - | ToPointSet(genericDist) - | ToSampleSet(genericDist, int) - | Truncate(genericDist, option, option) - | Inspect(genericDist) - | ToString(genericDist) - | ToSparkline(genericDist, int) - | AlgebraicAdd(genericDist, genericDist) - | AlgebraicMultiply(genericDist, genericDist) - | AlgebraicDivide(genericDist, genericDist) - | AlgebraicSubtract(genericDist, genericDist) - | AlgebraicLogarithm(genericDist, genericDist) - | AlgebraicExponentiate(genericDist, genericDist) - | PointwiseAdd(genericDist, genericDist) - | PointwiseMultiply(genericDist, genericDist) - | PointwiseDivide(genericDist, genericDist) - | PointwiseSubtract(genericDist, genericDist) - | PointwiseLogarithm(genericDist, genericDist) - | PointwiseExponentiate(genericDist, genericDist) - - let toGenericFunctionCallInfo = (t: t) => - switch t { - | Mean(d) => Operation.FromDist(ToFloat(#Mean), d) - | Sample(d) => FromDist(ToFloat(#Mean), d) - | Cdf(d, f) => FromDist(ToFloat(#Cdf(f)), d) - | Inv(d, f) => FromDist(ToFloat(#Inv(f)), d) - | Pdf(d, f) => FromDist(ToFloat(#Pdf(f)), d) - | Normalize(d) => FromDist(ToDist(Normalize), d) - | ToPointSet(d) => FromDist(ToDist(ToPointSet), d) - | ToSampleSet(d, r) => FromDist(ToDist(ToSampleSet(r)), d) - | Truncate(d, left, right) => FromDist(ToDist(Truncate(left, right)), d) - | Inspect(d) => FromDist(ToDist(Inspect), d) - | ToString(d) => FromDist(ToString(ToString), d) - | ToSparkline(d, n) => FromDist(ToString(ToSparkline(n)), d) - | AlgebraicAdd(d1, d2) => FromDist(ToDistCombination(Algebraic, #Add, #Dist(d2)), d1) - | AlgebraicMultiply(d1, d2) => FromDist(ToDistCombination(Algebraic, #Multiply, #Dist(d2)), d1) - | AlgebraicDivide(d1, d2) => FromDist(ToDistCombination(Algebraic, #Divide, #Dist(d2)), d1) - | AlgebraicSubtract(d1, d2) => FromDist(ToDistCombination(Algebraic, #Subtract, #Dist(d2)), d1) - | AlgebraicLogarithm(d1, d2) => - FromDist(ToDistCombination(Algebraic, #Logarithm, #Dist(d2)), d1) - | AlgebraicExponentiate(d1, d2) => - FromDist(ToDistCombination(Algebraic, #Exponentiate, #Dist(d2)), d1) - | PointwiseAdd(d1, d2) => FromDist(ToDistCombination(Pointwise, #Add, #Dist(d2)), d1) - | PointwiseMultiply(d1, d2) => FromDist(ToDistCombination(Pointwise, #Multiply, #Dist(d2)), d1) - | PointwiseDivide(d1, d2) => FromDist(ToDistCombination(Pointwise, #Divide, #Dist(d2)), d1) - | PointwiseSubtract(d1, d2) => FromDist(ToDistCombination(Pointwise, #Subtract, #Dist(d2)), d1) - | PointwiseLogarithm(d1, d2) => - FromDist(ToDistCombination(Pointwise, #Logarithm, #Dist(d2)), d1) - | PointwiseExponentiate(d1, d2) => - FromDist(ToDistCombination(Pointwise, #Exponentiate, #Dist(d2)), d1) - } -} \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res index c7bec8a9..f3f3c20c 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res @@ -203,8 +203,8 @@ let operate = (distToFloatOp: Operation.distToFloatOperation, s): float => | #Mean => T.mean(s) } -let toSparkline = (t: t, n) => +let toSparkline = (t: t, bucketCount) => T.toContinuous(t) - ->E.O2.fmap(Continuous.downsampleEquallyOverX(n)) + ->E.O2.fmap(Continuous.downsampleEquallyOverX(bucketCount)) ->E.O2.toResult("toContinous Error: Could not convert into continuous distribution") ->E.R2.fmap(r => Continuous.getShape(r).ys->Sparklines.create()) \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res index 07855686..f8bce6f6 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSet.res @@ -146,15 +146,24 @@ let toPointSetDist = ( samplesParse } +//Randomly get one sample from the distribution let sample = (t: t): float => { let i = E.Int.random(~min=0, ~max=E.A.length(t) - 1) E.A.unsafe_get(t, i) } +/* +If asked for a length of samples shorter or equal the length of the distribution, +return this first n samples of this distribution. +Else, return n random samples of the distribution. +The former helps in cases where multiple distributions are correlated. +However, if n > length(t), then there's no clear right answer, so we just randomly +sample everything. +*/ let sampleN = (t: t, n) => { if n <= E.A.length(t) { E.A.slice(t, ~offset=0, ~len=n) } else { Belt.Array.makeBy(n, _ => sample(t)) } -} \ No newline at end of file +} diff --git a/packages/squiggle-lang/src/rescript/TSInterface.res b/packages/squiggle-lang/src/rescript/TSInterface.res deleted file mode 100644 index 26b694a5..00000000 --- a/packages/squiggle-lang/src/rescript/TSInterface.res +++ /dev/null @@ -1,21 +0,0 @@ -@genType -type functionCallInfo = GenericDist_Types.Operation.genericFunctionCallInfo; - -@genType -type env = DistributionOperation.env; - -@genType -type genericDist = GenericDist_Types.genericDist; - -@genType -type error = GenericDist_Types.error; - -@genType -let runDistributionOperation = DistributionOperation.run; - -@genType -type resultDist = result -@genType -type resultFloat = result -@genType -type resultString = result \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/TypescriptInterface.res b/packages/squiggle-lang/src/rescript/TypescriptInterface.res new file mode 100644 index 00000000..fb30ea24 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/TypescriptInterface.res @@ -0,0 +1,24 @@ +/* +This is meant as a file to contain @genType declarations as needed for Typescript. +I would ultimately want to have all @genType declarations here, vs. other files, but +@genType doesn't play as nicely with renaming Modules and functions as +would be preferable. + +The below few seem to work fine. In the future there's definitely more work to do here. +*/ + +@genType +type env = DistributionOperation.env + +@genType +type genericDist = GenericDist_Types.genericDist + +@genType +type error = GenericDist_Types.error + +@genType +type resultDist = result +@genType +type resultFloat = result +@genType +type resultString = result