Minor improvement of integrals for mixed distributions

This commit is contained in:
Ozzie Gooen 2020-02-19 17:47:25 +00:00
parent 7389fda068
commit e5fb663c5d
4 changed files with 46 additions and 37 deletions

View File

@ -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", ()
=>
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);
// });
)
);
test("#yFOo", () =>
expect(Discrete.integrate(shape)) |> toEqual(step)
);
})
);

View File

@ -39,11 +39,12 @@ let domainLimitedDist =
let distributions = () =>
<div>
<div>
<h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
<GenericDistributionChart dist=timeDist />
<h2> {"Simple Continuous" |> ReasonReact.string} </h2>
<GenericDistributionChart dist=mixedDist />
</div>
// <GenericDistributionChart dist=mixedDist />
</div>;
// <div>
// <h2> {"Time Distribution" |> ReasonReact.string} </h2>

View File

@ -20,7 +20,6 @@ module Mixed = {
<thead>
<tr>
<th className="px-4 py-2"> {"X Point" |> ReasonReact.string} </th>
<th className="px-4 py-2"> {"Y Pount" |> ReasonReact.string} </th>
<th className="px-4 py-2">
{"Y Integral to Point" |> ReasonReact.string}
</th>
@ -41,6 +40,9 @@ module Mixed = {
</tbody>
</table>
<div />
{data.discrete
|> Shape.Discrete.scaleYToTotal(data.discreteProbabilityMassFraction)
|> Shape.Discrete.render}
</div>;
};
};

View File

@ -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 = {