From e5fb663c5d9eba8dbd923e265faa603113369a34 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Wed, 19 Feb 2020 17:47:25 +0000 Subject: [PATCH] Minor improvement of integrals for mixed distributions --- __tests__/Foo/Foo__Test.re | 27 ++++++------ showcase/entries/Continuous.re | 11 ++--- .../charts/GenericDistributionChart.re | 4 +- src/core/Shape.re | 41 +++++++++++-------- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/__tests__/Foo/Foo__Test.re b/__tests__/Foo/Foo__Test.re index f2f1ad33..4f574267 100644 --- a/__tests__/Foo/Foo__Test.re +++ b/__tests__/Foo/Foo__Test.re @@ -6,21 +6,20 @@ let shape: DistributionTypes.xyShape = { ys: [|8., 9., 2.|], }; +let step: DistributionTypes.xyShape = { + xs: [|1., 4., 8.|], + ys: [|8., 17., 19.|], +}; + open Shape; describe("Shape", () => - describe("XYShape", () => - test("#ySum", () - => - expect(XYShape.ySum(shape)) |> toEqual(19.0) - ) - // test("#both", () => { - // let expected: DistributionTypes.xyShape = { - // xs: [|1., 4., 8.|], - // ys: [|8., 1., 1.|], - // }; - // expect(shape |> XYShape.derivative |> XYShape.integral) - // |> toEqual(shape); - // }); - ) + describe("XYShape", () => { + test("#ySum", () => + expect(XYShape.ySum(shape)) |> toEqual(19.0) + ); + test("#yFOo", () => + expect(Discrete.integrate(shape)) |> toEqual(step) + ); + }) ); \ No newline at end of file diff --git a/showcase/entries/Continuous.re b/showcase/entries/Continuous.re index f14b8a38..7eaec0b4 100644 --- a/showcase/entries/Continuous.re +++ b/showcase/entries/Continuous.re @@ -39,11 +39,12 @@ let domainLimitedDist = let distributions = () =>
-

{"Basic Mixed Distribution" |> ReasonReact.string}

- -

{"Simple Continuous" |> ReasonReact.string}

- -
+ +

{"Basic Mixed Distribution" |> ReasonReact.string}

+ +

{"Simple Continuous" |> ReasonReact.string}

+
+ // ; //
//

{"Time Distribution" |> ReasonReact.string}

diff --git a/src/components/charts/GenericDistributionChart.re b/src/components/charts/GenericDistributionChart.re index d40f2592..fa908216 100644 --- a/src/components/charts/GenericDistributionChart.re +++ b/src/components/charts/GenericDistributionChart.re @@ -20,7 +20,6 @@ module Mixed = { {"X Point" |> ReasonReact.string} - {"Y Pount" |> ReasonReact.string} {"Y Integral to Point" |> ReasonReact.string} @@ -41,6 +40,9 @@ module Mixed = {
+ {data.discrete + |> Shape.Discrete.scaleYToTotal(data.discreteProbabilityMassFraction) + |> Shape.Discrete.render}
; }; }; diff --git a/src/core/Shape.re b/src/core/Shape.re index d70e1409..1c596cfd 100644 --- a/src/core/Shape.re +++ b/src/core/Shape.re @@ -17,6 +17,8 @@ module XYShape = { {"xs": t.xs, "ys": t.ys}; }; + let zip = t => Belt.Array.zip(t.xs, t.ys); + let fmap = (t: t, y): t => {xs: t.xs, ys: t.ys |> E.A.fmap(y)}; let scaleCdfTo = (~scaleTo=1., t: t) => @@ -84,8 +86,6 @@ module XYShape = { let mapYsBasedOnRanges = fn => inRanges(r => (nextX(r), fn(r)), toT); - let toStepFn = z => mapYsBasedOnRanges(rangeAreaAssumingSteps, z); - let integrateWithSteps = z => mapYsBasedOnRanges(rangeAreaAssumingSteps, z) |> E.O.fmap(accumulateYs); @@ -142,23 +142,21 @@ module Discrete = { ) |> ReasonReact.array; - let findY = (x: float, t: t) => - switch (E.A.getBy(zip(t), ((ix, _)) => ix == x)) { - | Some((_, y)) => y - | None => 0. - }; - let integrate = XYShape.accumulateYs; let derivative = XYShape.subtractYs; - let findIntegralY = (f, t: t) => - t - |> XYShape.Range.toStepFn - |> E.O.fmap(XYShape.accumulateYs) - |> E.O.fmap(CdfLibrary.Distribution.findY(f)); + // TODO: This has a clear bug where it returns the Y value of the first item, + // even if X is less than the X of the first item. + let findIntegralY = (f, t: t) => { + t |> XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f); + }; - let findX = (f, t: t) => - t |> XYShape.Range.toStepFn |> E.O.fmap(CdfLibrary.Distribution.findX(f)); + let findY = (f, t: t) => { + Belt.Array.zip(t.xs, t.ys) + |> E.A.getBy(_, ((x, _)) => x == f) + |> E.O.fmap(((_, y)) => y) + |> E.O.default(0.); + }; }; module Mixed = { @@ -195,7 +193,7 @@ module Mixed = { let c = t.continuous |> Continuous.findIntegralY(x); let d = Discrete.findIntegralY(x, t.discrete); switch (c, d) { - | (Some(c), Some(d)) => Some(mixedMultiply(t, c, d)) + | (Some(c), d) => Some(mixedMultiply(t, c, d)) | _ => None }; }; @@ -208,13 +206,22 @@ module Mixed = { module Any = { type t = DistributionTypes.pointsType; - let x = (t: t, x: float) => + let y = (t: t, x: float) => switch (t) { | Mixed(m) => `mixed(Mixed.getY(m, x)) | Discrete(discreteShape) => `discrete(Discrete.findY(x, discreteShape)) | Continuous(continuousShape) => `continuous(Continuous.findY(x, continuousShape)) }; + + let yIntegral = (t: t, x: float) => + switch (t) { + | Mixed(m) => `mixed(Mixed.getYIntegral(x, m)) + | Discrete(discreteShape) => + `discrete(Discrete.findIntegralY(x, discreteShape)) + | Continuous(continuousShape) => + `continuous(Continuous.findIntegralY(x, continuousShape)) + }; }; module DomainMixed = {