From 320b8da91af6aba68408a343ea4fd1e25f84ad59 Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Tue, 29 Mar 2022 15:10:20 -0400 Subject: [PATCH] most of the refactor based on @OAGr's comments --- .../squiggle-lang/__tests__/Symbolic_test.res | 38 ++++++++++--------- .../squiggle-lang/src/rescript/utility/E.res | 1 + .../src/rescript/utility/Sparklines.res | 33 ++++++++-------- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/packages/squiggle-lang/__tests__/Symbolic_test.res b/packages/squiggle-lang/__tests__/Symbolic_test.res index 98032804..7d2076ae 100644 --- a/packages/squiggle-lang/__tests__/Symbolic_test.res +++ b/packages/squiggle-lang/__tests__/Symbolic_test.res @@ -8,23 +8,27 @@ let makeTest = (~only=false, str, item1, item2) => ? Only.test(str, () => expect(item1) -> toEqual(item2)) : test(str, () => expect(item1) -> toEqual(item2)) -let normalParams1: SymbolicDistTypes.normal = {mean: 5.0, stdev: 2.0} -// let normalParams2: SymbolicDistTypes.normal = {mean: 10.0, stdev: 2.0} -let normalParams3: SymbolicDistTypes.normal = {mean: 20.0, stdev: 2.0} -let range20 = [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0] -let forSparkline = (thisPdf, inps) => map(thisPdf, inps) +let pdfImage = (thePdf, inps) => map(thePdf, inps) -describe("Normal with Sparklines", () => { - let pdf1 = x => Normal.pdf(x, normalParams1) - let forSparkline1 = forSparkline(pdf1, range20) - makeTest("mean=5", Sparklines.sparkly(forSparkline1, ~options={minimum: None, maximum: None}), `▁▂▃▅███▅▃▂▁▁▁▁▁▁▁▁▁▁▁`) - - let normal4 = Normal.add(normalParams1, normalParams3) - let normalParams4 = switch normal4 { - | #Normal(params) => params - | _ => {mean: 0.0, stdev: 1.0} +let parameterWiseAdditionHelper = (n1: SymbolicDistTypes.normal, n2: SymbolicDistTypes.normal) => { + let normalDistAtSumMeanConstr = Normal.add(n1, n2) + let normalDistAtSumMean: SymbolicDistTypes.normal = switch normalDistAtSumMeanConstr { + | #Normal(params) => params } - let pdf4 = x => Normal.pdf(x, normalParams4) - let forSparkline4 = forSparkline(pdf4, range20) - makeTest("mixture of two normals", Sparklines.sparkly(forSparkline4, ~options={minimum: None, maximum: None}), `▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂▅█`) + x => Normal.pdf(x, normalDistAtSumMean) +} + +describe("Normal distribution with sparklines", () => { + + let normalDistAtMean5: SymbolicDistTypes.normal = {mean: 5.0, stdev: 2.0} + let normalDistAtMean10: SymbolicDistTypes.normal = {mean: 10.0, stdev: 2.0} + let range20Float = [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,] + + let pdfNormalDistAtMean5 = x => Normal.pdf(x, normalDistAtMean5) + let sparklineMean5 = pdfImage(pdfNormalDistAtMean5, range20Float) + makeTest("mean=5", Sparklines.create(sparklineMean5, ()), `▁▂▃▅███▅▃▂▁▁▁▁▁▁▁▁▁▁`) + + let sparklineMean15 = normalDistAtMean5 -> parameterWiseAdditionHelper(normalDistAtMean10) -> pdfImage(range20Float) + // let sparklineMean15 = pdfImage(pdfNormalDistAtMean15, range20Float) + makeTest("parameter-wise addition of two normal distributions", Sparklines.create(sparklineMean15, ()), `▁▁▁▁▁▁▁▁▁▁▂▃▅▇███▇▅▃`) }) diff --git a/packages/squiggle-lang/src/rescript/utility/E.res b/packages/squiggle-lang/src/rescript/utility/E.res index d17850fd..19febbad 100644 --- a/packages/squiggle-lang/src/rescript/utility/E.res +++ b/packages/squiggle-lang/src/rescript/utility/E.res @@ -323,6 +323,7 @@ module A = { } ) let filter = (o, e) => Js.Array.filter(o, e) + let joinWith = (fill, arr) => Js.Array.joinWith(fill, arr) module O = { let concatSomes = (optionals: array>): array<'a> => diff --git a/packages/squiggle-lang/src/rescript/utility/Sparklines.res b/packages/squiggle-lang/src/rescript/utility/Sparklines.res index 2e5c9cf0..627804ca 100644 --- a/packages/squiggle-lang/src/rescript/utility/Sparklines.res +++ b/packages/squiggle-lang/src/rescript/utility/Sparklines.res @@ -2,31 +2,28 @@ // reference implementation: https://github.com/sindresorhus/sparkly // Omitting rgb "fire" style, so no `chalk` dependency -type sparklyConfig = { - minimum: option, - maximum: option -} - -let sparkly = ( +let create = ( numbers: array, - ~options = {minimum: None, maximum: None} + ~minimum=?, + ~maximum=?, + () ) => { // Unlike reference impl, we assume that all numbers are finite, i.e. no NaN. let ticks = [`▁`, `▂`, `▃`, `▄`, `▅`, `▆`, `▇`, `█`] - let minimum = E.O.default(Js.Math.minMany_float(numbers), options.minimum) - let maximum = E.O.default(Js.Math.maxMany_float(numbers), options.maximum) + let minimum = E.O.default(Js.Math.minMany_float(numbers), minimum) + let maximum = E.O.default(Js.Math.maxMany_float(numbers), maximum) - // Use a high tick if data is constant and max is not equal - let ticks = if minimum == maximum && maximum != 0.0 { - [ticks[4]] - } else { - ticks - } +// // Use a high tick if data is constant and max is not equal to min or zero +// let ticks = if minimum == maximum && maximum != 0.0 { +// [ticks[4]] +// } else { +// ticks +// } - let toMapWith = (number: float) => { - let tickIndex = Js.Math.ceil_int((number /. maximum) *. Belt.Int.toFloat(Belt.Array.length(ticks))) - 1 + let toHeight = (number: float) => { + let tickIndex = Js.Math.ceil_int((number /. maximum) *. (ticks -> Belt.Array.length -> Belt.Int.toFloat)) - 1 let tickIndex = if maximum == 0.0 || tickIndex < 0 { 0 @@ -36,5 +33,5 @@ let sparkly = ( ticks[tickIndex] } - Js.Array.joinWith("", Belt.Array.map(numbers, toMapWith)) + toHeight -> E.A.fmap(numbers) -> (arr => E.A.joinWith("", arr)) }