From f3f1861ba665e31cb9681dff7a557028c15858d1 Mon Sep 17 00:00:00 2001 From: Sebastian Kosch Date: Tue, 2 Jun 2020 15:08:41 -0700 Subject: [PATCH 1/3] Realistic x selection for uniform distribution rendering --- src/distPlus/symbolic/SymbolicDist.re | 24 +++++++++++++++++++++--- yarn.lock | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/distPlus/symbolic/SymbolicDist.re b/src/distPlus/symbolic/SymbolicDist.re index c3c1b998..e476e974 100644 --- a/src/distPlus/symbolic/SymbolicDist.re +++ b/src/distPlus/symbolic/SymbolicDist.re @@ -255,13 +255,31 @@ module GenericSimple = { | `Uniform({high}) => high | `Float(n) => n; + + /* This function returns a list of x's at which to evaluate the overall distribution (for rendering). + This function is called separately for each individual distribution. + + When called with xSelection=`Linear, this function will return (sampleCount) x's, evenly + distributed between the min and max of the distribution (whatever those are defined to be above). + + When called with xSelection=`ByWeight, this function will distribute the x's such as to + match the cumulative shape of the distribution. This is slower but may give better results. + */ let interpolateXs = (~xSelection: [ | `Linear | `ByWeight]=`Linear, dist: dist, sampleCount) => { + switch (xSelection) { | `Linear => E.A.Floats.range(min(dist), max(dist), sampleCount) | `ByWeight => - E.A.Floats.range(minCdfValue, maxCdfValue, sampleCount) - |> E.A.fmap(x => inv(x, dist)) + switch (dist) { + // In `ByWeight mode, uniform distributions get special treatment because we need two x's + // on either side for proper rendering (just left and right of the discontinuities). + | `Uniform(n) => E.A.of_list([n.low -. minCdfValue, n.low +. minCdfValue, + n.high -. minCdfValue, n.high +. minCdfValue]) + | dist => + let ys = E.A.Floats.range(minCdfValue, maxCdfValue, sampleCount) + ys |> E.A.fmap(y => inv(y, dist)) + } }; }; @@ -379,4 +397,4 @@ let toShape = n => fun | `Simple(d) => GenericSimple.toShape(~xSelection=`ByWeight, d, n) | `PointwiseCombination(d) => - PointwiseAddDistributionsWeighted.toShape(d, n); \ No newline at end of file + PointwiseAddDistributionsWeighted.toShape(d, n); diff --git a/yarn.lock b/yarn.lock index 42114acc..a15e386c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2491,7 +2491,7 @@ bs-moment@0.4.5, bs-moment@^0.4.4: resolved "https://registry.yarnpkg.com/bs-moment/-/bs-moment-0.4.5.tgz#3f84fed55c2a70d25b0b6025e4e8d821fcdd4dc8" integrity sha512-anPYkFSof+X8EeomnP0fbQBvWFJeganwPqqARVB+fcdKYX2Uog/n3CCiFGEA+66yHbwnWZD5YFhtHCuyLMcQfQ== -bs-platform@7.2.2, bs-platform@^7.2.2: +bs-platform@7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/bs-platform/-/bs-platform-7.2.2.tgz#76fdc63e4889458ae3d257a0132107a792f2309c" integrity sha512-PWcFfN+jCTtT/rMaHDhKh+W9RUTpaRunmSF9vbLYcrJbpgCNW6aFKAY33u0P3mLxwuhshN3b4FxqGUBPj6exZQ== From 68efbf0396022f0cd4a8d3866bcdd1225b97fa08 Mon Sep 17 00:00:00 2001 From: Sebastian Kosch Date: Tue, 2 Jun 2020 15:24:09 -0700 Subject: [PATCH 2/3] Fix normal distribution from 90CI (stdev was double what it should be) --- src/distPlus/symbolic/SymbolicDist.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/distPlus/symbolic/SymbolicDist.re b/src/distPlus/symbolic/SymbolicDist.re index e476e974..ada4e2c0 100644 --- a/src/distPlus/symbolic/SymbolicDist.re +++ b/src/distPlus/symbolic/SymbolicDist.re @@ -100,7 +100,7 @@ module Normal = { let from90PercentCI = (low, high) => { let mean = E.A.Floats.mean([|low, high|]); - let stdev = (high -. low) /. 1.645; + let stdev = (high -. low) /. (2. *. 1.644854); `Normal({mean, stdev}); }; let inv = (p, t: t) => Jstat.normal##inv(p, t.mean, t.stdev); From 6306fa9ca25242c2cf7ea1ae60e05bfa029cfd9c Mon Sep 17 00:00:00 2001 From: Sebastian Kosch Date: Wed, 3 Jun 2020 09:24:55 -0700 Subject: [PATCH 3/3] Clean up interpolateXs function --- src/distPlus/symbolic/SymbolicDist.re | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/distPlus/symbolic/SymbolicDist.re b/src/distPlus/symbolic/SymbolicDist.re index ada4e2c0..d867eb22 100644 --- a/src/distPlus/symbolic/SymbolicDist.re +++ b/src/distPlus/symbolic/SymbolicDist.re @@ -268,18 +268,16 @@ module GenericSimple = { let interpolateXs = (~xSelection: [ | `Linear | `ByWeight]=`Linear, dist: dist, sampleCount) => { - switch (xSelection) { - | `Linear => E.A.Floats.range(min(dist), max(dist), sampleCount) - | `ByWeight => - switch (dist) { + switch (xSelection, dist) { + | (`Linear, _) => E.A.Floats.range(min(dist), max(dist), sampleCount) + | (`ByWeight, `Uniform(n)) => // In `ByWeight mode, uniform distributions get special treatment because we need two x's // on either side for proper rendering (just left and right of the discontinuities). - | `Uniform(n) => E.A.of_list([n.low -. minCdfValue, n.low +. minCdfValue, - n.high -. minCdfValue, n.high +. minCdfValue]) - | dist => - let ys = E.A.Floats.range(minCdfValue, maxCdfValue, sampleCount) - ys |> E.A.fmap(y => inv(y, dist)) - } + let dx = 0.00001 *. (n.high -. n.low); + [|n.low -. dx, n.low +. dx, n.high -. dx, n.high +. dx|] + | (`ByWeight, _) => + let ys = E.A.Floats.range(minCdfValue, maxCdfValue, sampleCount) + ys |> E.A.fmap(y => inv(y, dist)) }; };