diff --git a/packages/squiggle-lang/__tests__/Distributions/Mixture_test.res b/packages/squiggle-lang/__tests__/Distributions/Mixture_test.res index 537a657f..dc19bfd2 100644 --- a/packages/squiggle-lang/__tests__/Distributions/Mixture_test.res +++ b/packages/squiggle-lang/__tests__/Distributions/Mixture_test.res @@ -17,6 +17,9 @@ let unpackFloat = x => x -> toFloat -> toExt let mkNormal = (mean, stdev) => GenericDist_Types.Symbolic(#Normal({mean: mean, stdev: stdev})) let mkBeta = (alpha, beta) => GenericDist_Types.Symbolic(#Beta({alpha: alpha, beta: beta})) let mkExponential = rate => GenericDist_Types.Symbolic(#Exponential({rate: rate})) +let mkUniform = (low, high) => GenericDist_Types.Symbolic(#Uniform({low: low, high: high})) +let mkCauchy = (local, scale) => GenericDist_Types.Symbolic(#Cauchy({local: local, scale: scale})) +let mkLognormal = (mu, sigma) => GenericDist_Types.Symbolic(#Lognormal({mu: mu, sigma: sigma})) describe("mixture", () => { testAll("fair mean of two normal distributions", list{(0.0, 1e2), (-1e1, -1e-4), (-1e1, 1e2), (-1e1, 1e1)}, tup => { // should be property @@ -51,5 +54,22 @@ describe("mixture", () => { ) } ) + testAll( + "weighted mean of lognormal and uniform", + list{}, + tup => { + let (uniformParams, lognormalParams) = tup + let (low, high) = uniformParams + let (mu, sigma) = lognormalParams + let theMean = { + run(Mixture([(mkUniform(low, high), 0.6), (mkLognormal(mu, sigma), 0.4)])) + -> outputMap(FromDist(ToFloat(#Mean))) + } + theMean + -> unpackFloat + -> expect + -> toBeSoCloseTo(0.6 *. (low +. high) /. 2.0 +. 0.4 *. (mu +. sigma ** 2.0 /. 2.0), ~digits=0) + } + ) }) diff --git a/packages/squiggle-lang/__tests__/Distributions/Symbolic_test.res b/packages/squiggle-lang/__tests__/Distributions/Symbolic_test.res index ae5d17c4..4f17fab2 100644 --- a/packages/squiggle-lang/__tests__/Distributions/Symbolic_test.res +++ b/packages/squiggle-lang/__tests__/Distributions/Symbolic_test.res @@ -21,7 +21,7 @@ let toExtDist: option => GenericDist_Types.generi let unpackFloat = x => x -> toFloat -> toExtFloat let unpackDist = y => y -> toDist -> toExtDist -describe("normalize", () => { +describe("(Symbolic) normalize", () => { testAll("has no impact on normal distributions", list{-1e8, -16.0, -1e-2, 0.0, 1e-4, 32.0, 1e16}, mean => { let theNormal = mkNormal(mean, 2.0) let theNormalized = run(FromDist(ToDist(Normalize), theNormal)) @@ -68,17 +68,19 @@ describe("(Symbolic) mean", () => { //-> toBe(GenDistError(Other("Cauchy distributions may have no mean value."))) }) - test("of a triangular distribution", () => { // should be property + testAll("of triangular distributions", list{(1.0,2.0,3.0), (-1e7,-1e-7,1e-7), (-1e-7,1e0,1e7), (-1e-16,0.0,1e-16)}, tup => { + let (low, medium, high) = tup let theMean = run(FromDist( ToFloat(#Mean), - GenericDist_Types.Symbolic(#Triangular({low: - 5.0, medium: 1e-3, high: 10.0})) + GenericDist_Types.Symbolic(#Triangular({low: low, medium: medium, high: high})) )) theMean -> unpackFloat -> expect - -> toBeCloseTo((-5.0 +. 1e-3 +. 10.0) /. 3.0) // https://www.statology.org/triangular-distribution/ + -> toBeCloseTo((low +. medium +. high) /. 3.0) // https://www.statology.org/triangular-distribution/ }) + // TODO: nonpositive inputs are SUPPOSED to crash. testAll("of beta distributions", list{(1e-4, 6.4e1), (1.28e2, 1e0), (1e-16, 1e-16), (1e16, 1e16), (-1e4, 1e1), (1e1, -1e4)}, tup => { let (alpha, beta) = tup let theMean = run(FromDist( @@ -91,6 +93,7 @@ describe("(Symbolic) mean", () => { -> toBeCloseTo(1.0 /. (1.0 +. (beta /. alpha))) // https://en.wikipedia.org/wiki/Beta_distribution#Mean }) + // TODO: When we have our theory of validators we won't want this to be NaN but to be an error. test("of beta(0, 0)", () => { let theMean = run(FromDist( ToFloat(#Mean),