diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 18dd2a3e..276e73d5 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -153,6 +153,7 @@ type SummaryTableProps = { const SummaryTable: React.FC = ({ distribution }) => { const mean = distribution.mean(); + const stdev = distribution.stdev(); const p5 = distribution.inv(0.05); const p10 = distribution.inv(0.1); const p25 = distribution.inv(0.25); @@ -161,6 +162,9 @@ const SummaryTable: React.FC = ({ distribution }) => { const p90 = distribution.inv(0.9); const p95 = distribution.inv(0.95); + const hasResult = (x: result): boolean => + x.tag === "Ok"; + const unwrapResult = ( x: result ): React.ReactNode => { @@ -180,6 +184,7 @@ const SummaryTable: React.FC = ({ distribution }) => { {"Mean"} + {hasResult(stdev) && {"Stdev"}} {"5%"} {"10%"} {"25%"} @@ -192,6 +197,7 @@ const SummaryTable: React.FC = ({ distribution }) => { {unwrapResult(mean)} + {hasResult(stdev) && {unwrapResult(stdev)}} {unwrapResult(p5)} {unwrapResult(p10)} {unwrapResult(p25)} diff --git a/packages/squiggle-lang/src/js/distribution.ts b/packages/squiggle-lang/src/js/distribution.ts index eaa76c47..9bd3723b 100644 --- a/packages/squiggle-lang/src/js/distribution.ts +++ b/packages/squiggle-lang/src/js/distribution.ts @@ -11,6 +11,7 @@ import { import { result, resultMap, Ok } from "./types"; import { Constructors_mean, + Constructors_stdev, Constructors_sample, Constructors_pdf, Constructors_cdf, @@ -69,6 +70,10 @@ export class Distribution { return Constructors_mean({ env: this.env }, this.t); } + stdev(): result { + return Constructors_stdev({ env: this.env }, this.t); + } + sample(): result { return Constructors_sample({ env: this.env }, this.t); } diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res index 61b5cd6b..668fcd07 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res @@ -265,6 +265,8 @@ module Constructors = { module C = DistributionTypes.Constructors.UsingDists open OutputLocal let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR + let stdev = (~env, dist) => C.stdev(dist)->run(~env)->toFloatR + let variance = (~env, dist) => C.variance(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 diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi index aa006c06..454b2729 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi @@ -49,6 +49,10 @@ module Constructors: { @genType let mean: (~env: env, genericDist) => result @genType + let stdev: (~env: env, genericDist) => result + @genType + let variance: (~env: env, genericDist) => result + @genType let sample: (~env: env, genericDist) => result @genType let cdf: (~env: env, genericDist, float) => result diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index 5bba9f1d..a6eb0431 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -30,9 +30,9 @@ module Error = { @genType let toString = (err: error): string => switch err { - | NotYetImplemented => "Function Not Yet Implemented" + | NotYetImplemented => "Function not yet implemented" | Unreachable => "Unreachable" - | DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift is Invalid" + | DistributionVerticalShiftIsInvalid => "Distribution vertical shift is invalid" | ArgumentError(s) => `Argument Error ${s}` | LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}` | SampleSetError(TooFewSamples) => "Too Few Samples" @@ -68,6 +68,11 @@ module DistributionOperation = { | #Mean | #Sample | #IntegralSum + | #Mode + | #Stdev + | #Min + | #Max + | #Variance ] type toScaleFn = [ @@ -117,6 +122,11 @@ module DistributionOperation = { | ToFloat(#Cdf(r)) => `cdf(${E.Float.toFixed(r)})` | ToFloat(#Inv(r)) => `inv(${E.Float.toFixed(r)})` | ToFloat(#Mean) => `mean` + | ToFloat(#Min) => `min` + | ToFloat(#Max) => `max` + | ToFloat(#Stdev) => `stdev` + | ToFloat(#Variance) => `variance` + | ToFloat(#Mode) => `mode` | ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})` | ToFloat(#Sample) => `sample` | ToFloat(#IntegralSum) => `integralSum` @@ -151,6 +161,8 @@ module Constructors = { module UsingDists = { @genType let mean = (dist): t => FromDist(ToFloat(#Mean), dist) + let stdev = (dist): t => FromDist(ToFloat(#Stdev), dist) + let variance = (dist): t => FromDist(ToFloat(#Variance), dist) let sample = (dist): t => FromDist(ToFloat(#Sample), dist) let cdf = (dist, x): t => FromDist(ToFloat(#Cdf(x)), dist) let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist) diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res index 4a541ce1..f7d1e4f5 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res @@ -108,7 +108,7 @@ let toFloatOperation = ( ) => { switch distToFloatOperation { | #IntegralSum => Ok(integralEndY(t)) - | (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample) as op => { + | (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample | #Min | #Max) as op => { let trySymbolicSolution = switch (t: t) { | Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption | _ => None @@ -118,6 +118,8 @@ let toFloatOperation = ( | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some + | (SampleSet(sampleSet), #Min) => SampleSetDist.min(sampleSet)->Some + | (SampleSet(sampleSet), #Max) => SampleSetDist.max(sampleSet)->Some | _ => None } @@ -130,6 +132,16 @@ let toFloatOperation = ( } } } + | (#Stdev | #Variance | #Mode) as op => + switch t { + | SampleSet(s) => + switch op { + | #Stdev => SampleSetDist.stdev(s)->Ok + | #Variance => SampleSetDist.variance(s)->Ok + | #Mode => SampleSetDist.mode(s)->Ok + } + | _ => Error(DistributionTypes.NotYetImplemented) + } } } diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res index 92398099..74913d06 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res @@ -254,6 +254,8 @@ let operate = (distToFloatOp: Operation.distToFloatOperation, s): float => | #Inv(f) => inv(f, s) | #Sample => sample(s) | #Mean => T.mean(s) + | #Min => T.minX(s) + | #Max => T.maxX(s) } let toSparkline = (t: t, bucketCount): result => diff --git a/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res b/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res index d1fcb9ef..ff29bc65 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res @@ -449,6 +449,8 @@ module T = { | #Cdf(f) => Ok(cdf(f, s)) | #Pdf(f) => Ok(pdf(f, s)) | #Inv(f) => Ok(inv(f, s)) + | #Min => Ok(min(s)) + | #Max => Ok(max(s)) | #Sample => Ok(sample(s)) | #Mean => mean(s) } diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 7e3493b7..20b8498a 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -209,7 +209,18 @@ let dispatchToGenericOutput = ( | ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env) | ("sampleN", [EvDistribution(dist), EvNumber(n)]) => Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n)))) - | ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist, ~env) + | (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [EvDistribution(dist)]) => { + let fn = switch op { + | "mean" => #Mean + | "stdev" => #Stdev + | "variance" => #Variance + | "min" => #Min + | "max" => #Max + | "mode" => #Mode + | _ => #Mean + } + Helpers.toFloatFn(fn, dist, ~env) + } | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env) | ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env) | ("toSparkline", [EvDistribution(dist)]) => diff --git a/packages/squiggle-lang/src/rescript/Utility/Operation.res b/packages/squiggle-lang/src/rescript/Utility/Operation.res index 6476850d..8e22169c 100644 --- a/packages/squiggle-lang/src/rescript/Utility/Operation.res +++ b/packages/squiggle-lang/src/rescript/Utility/Operation.res @@ -26,6 +26,8 @@ type distToFloatOperation = [ | #Inv(float) | #Mean | #Sample + | #Min + | #Max ] module Convolution = {