Simple minX and maxX for distributions
This commit is contained in:
parent
73dbd64686
commit
c3ca1a1a57
|
@ -16,15 +16,13 @@ let mixedDist =
|
|||
)
|
||||
|> GenericDistribution.renderIfNeeded(~sampleCount=1000);
|
||||
|
||||
// "mm(floor(uniform(30,35)), normal(50,20), [.25,.5])",
|
||||
let timeDist =
|
||||
GenericDistribution.make(
|
||||
~generationSource=
|
||||
GuesstimatorString(
|
||||
"mm(floor(uniform(40, 50)), normal(50,10), [.5,.5])",
|
||||
),
|
||||
~generationSource=GuesstimatorString("floor(normal(30,2))"),
|
||||
~probabilityType=Pdf,
|
||||
~domain=Complete,
|
||||
~unit=TimeDistribution({zero: MomentRe.momentNow(), unit: `years}),
|
||||
~unit=TimeDistribution({zero: MomentRe.momentNow(), unit: `days}),
|
||||
(),
|
||||
)
|
||||
|> GenericDistribution.renderIfNeeded(~sampleCount=1000);
|
||||
|
|
|
@ -63,38 +63,55 @@ let continuousComponent = (p: DistributionTypes.pointsType) =>
|
|||
| Continuous(c) => Some(c)
|
||||
};
|
||||
|
||||
module Cont = {
|
||||
[@react.component]
|
||||
let make = (~continuous, ~onHover, ~timeScale) => {
|
||||
let chart =
|
||||
React.useMemo1(
|
||||
() =>
|
||||
<CdfChart__Plain
|
||||
primaryDistribution=continuous
|
||||
color={`hex("333")}
|
||||
onHover
|
||||
timeScale
|
||||
/>,
|
||||
[|continuous|],
|
||||
);
|
||||
chart;
|
||||
};
|
||||
let discreteScaleFactor = (p: DistributionTypes.pointsType) =>
|
||||
switch (p) {
|
||||
| Mixed(mixedShape) => Some(mixedShape.discreteProbabilityMassFraction)
|
||||
| Discrete(_) => None
|
||||
| Continuous(_) => None
|
||||
};
|
||||
|
||||
module Shapee = {
|
||||
[@react.component]
|
||||
let make = (~shape: DistributionTypes.pointsType, ~timeScale, ~onHover) => {
|
||||
let continuous = continuousComponent(shape);
|
||||
let discrete = discreteComponent(shape);
|
||||
let discreteScaleFactor = shape |> discreteScaleFactor;
|
||||
let continuous =
|
||||
continuousComponent(shape)
|
||||
|> E.O.bind(
|
||||
_,
|
||||
Shape.Continuous.scalePdf(
|
||||
~scaleTo=
|
||||
discreteScaleFactor
|
||||
|> E.O.fmap(r => 1. -. r)
|
||||
|> E.O.default(1.0),
|
||||
),
|
||||
);
|
||||
let discrete =
|
||||
discreteComponent(shape)
|
||||
|> E.O.fmap(
|
||||
Shape.Discrete.scaleYToTotal(
|
||||
discreteScaleFactor |> E.O.default(1.0),
|
||||
),
|
||||
);
|
||||
let minX = {
|
||||
Shape.Any.minX(shape);
|
||||
};
|
||||
let maxX = {
|
||||
Shape.Any.maxX(shape);
|
||||
};
|
||||
<div>
|
||||
{continuous
|
||||
|> E.O.React.fmapOrNull(continuous =>
|
||||
<Cont continuous onHover timeScale />
|
||||
)}
|
||||
{discrete
|
||||
|> E.O.React.fmapOrNull(r =>
|
||||
r |> Shape.Discrete.scaleYToTotal(0.3) |> Shape.Discrete.render
|
||||
<CdfChart__Plain
|
||||
primaryDistribution=continuous
|
||||
minX
|
||||
maxX
|
||||
?discrete
|
||||
color={`hex("333")}
|
||||
onHover
|
||||
timeScale
|
||||
/>
|
||||
)}
|
||||
{discrete |> E.O.React.fmapOrNull(Shape.Discrete.render)}
|
||||
</div>;
|
||||
};
|
||||
};
|
||||
|
@ -105,12 +122,19 @@ module GenericDist = {
|
|||
let (x, setX) = React.useState(() => 0.);
|
||||
let timeScale =
|
||||
genericDistribution.unit |> DistributionTypes.DistributionUnit.toJson;
|
||||
<div>
|
||||
{genericDistribution
|
||||
let chart =
|
||||
React.useMemo1(
|
||||
() => {
|
||||
genericDistribution
|
||||
|> DistributionTypes.shape
|
||||
|> E.O.React.fmapOrNull(shape => {
|
||||
<Shapee shape timeScale onHover={r => setX(_ => r)} />
|
||||
})}
|
||||
})
|
||||
},
|
||||
[|genericDistribution|],
|
||||
);
|
||||
<div>
|
||||
chart
|
||||
<table className="table-auto">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -20,10 +20,26 @@ let renderIfNeeded =
|
|||
switch (t.generationSource) {
|
||||
| GuesstimatorString(s) =>
|
||||
let shape = Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ());
|
||||
shape
|
||||
|> E.O.fmap((shape: DistributionTypes.mixedShape) =>
|
||||
let newShape =
|
||||
switch (shape) {
|
||||
| Some({
|
||||
continuous: {xs: [||], ys: [||]},
|
||||
discrete: {xs: [||], ys: [||]},
|
||||
}) =>
|
||||
None
|
||||
| Some({continuous, discrete: {xs: [||], ys: [||]}}) =>
|
||||
Some(Continuous(continuous))
|
||||
| Some({continuous: {xs: [||], ys: [||]}, discrete}) =>
|
||||
Some(Discrete(discrete))
|
||||
| Some(shape) => Some(Mixed(shape))
|
||||
| _ => None
|
||||
};
|
||||
|
||||
Js.log(newShape);
|
||||
newShape
|
||||
|> E.O.fmap((shape: DistributionTypes.pointsType) =>
|
||||
make(
|
||||
~generationSource=Shape(Mixed(shape)),
|
||||
~generationSource=Shape(shape),
|
||||
~probabilityType=Cdf,
|
||||
~domain=t.domain,
|
||||
~unit=t.unit,
|
||||
|
@ -52,7 +68,7 @@ let normalizePdf = (t: DistributionTypes.pointsType) => {
|
|||
switch (t) {
|
||||
| Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
|
||||
continuous
|
||||
|> Shape.Continuous.normalizePdf
|
||||
|> Shape.Continuous.scalePdf(~scaleTo=1.0)
|
||||
|> E.O.fmap(r =>
|
||||
Mixed({
|
||||
continuous: r,
|
||||
|
@ -63,7 +79,7 @@ let normalizePdf = (t: DistributionTypes.pointsType) => {
|
|||
| Discrete(d) => Some(Discrete(d |> Shape.Discrete.scaleYToTotal(1.0)))
|
||||
| Continuous(continuousShape) =>
|
||||
continuousShape
|
||||
|> Shape.Continuous.normalizePdf
|
||||
|> Shape.Continuous.scalePdf(~scaleTo=1.0)
|
||||
|> E.O.fmap(r => Continuous(r))
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,6 +17,10 @@ module XYShape = {
|
|||
{"xs": t.xs, "ys": t.ys};
|
||||
};
|
||||
|
||||
let minX = (t: t) => t.xs |> E.A.get(_, 0);
|
||||
// TODO: Check if this actually gets the last element, I'm not sure it does.
|
||||
let maxX = (t: t) => t.xs |> (r => E.A.get(r, E.A.length(r) - 1));
|
||||
|
||||
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)};
|
||||
|
@ -101,6 +105,8 @@ module XYShape = {
|
|||
};
|
||||
|
||||
module Continuous = {
|
||||
let minX = XYShape.minX;
|
||||
let maxX = XYShape.maxX;
|
||||
let fromArrays = XYShape.fromArrays;
|
||||
let toJs = XYShape.toJs;
|
||||
let toPdf = XYShape.Range.derivative;
|
||||
|
@ -114,11 +120,16 @@ module Continuous = {
|
|||
let normalizeCdf = (continuousShape: continuousShape) =>
|
||||
continuousShape |> XYShape.scaleCdfTo(~scaleTo=1.0);
|
||||
|
||||
let normalizePdf = (continuousShape: continuousShape) =>
|
||||
continuousShape |> toCdf |> E.O.fmap(normalizeCdf) |> E.O.bind(_, toPdf);
|
||||
let scalePdf = (~scaleTo=1.0, continuousShape: continuousShape) =>
|
||||
continuousShape
|
||||
|> toCdf
|
||||
|> E.O.fmap(XYShape.scaleCdfTo(~scaleTo))
|
||||
|> E.O.bind(_, toPdf);
|
||||
};
|
||||
|
||||
module Discrete = {
|
||||
let minX = XYShape.minX;
|
||||
let maxX = XYShape.maxX;
|
||||
type t = discreteShape;
|
||||
let fromArrays = XYShape.fromArrays;
|
||||
let toJs = XYShape.toJs;
|
||||
|
@ -147,6 +158,7 @@ module Discrete = {
|
|||
|
||||
// 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.
|
||||
// It has a second bug that it assumes things are triangular, instead of interpolating via steps.
|
||||
let findIntegralY = (f, t: t) => {
|
||||
t |> XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
|
||||
};
|
||||
|
@ -159,6 +171,22 @@ module Discrete = {
|
|||
};
|
||||
};
|
||||
|
||||
let min = (f1: option(float), f2: option(float)) =>
|
||||
switch (f1, f2) {
|
||||
| (Some(f1), Some(f2)) => Some(f1 < f2 ? f1 : f2)
|
||||
| (Some(f1), None) => Some(f1)
|
||||
| (None, Some(f2)) => Some(f2)
|
||||
| (None, None) => None
|
||||
};
|
||||
|
||||
let max = (f1: option(float), f2: option(float)) =>
|
||||
switch (f1, f2) {
|
||||
| (Some(f1), Some(f2)) => Some(f1 > f2 ? f1 : f2)
|
||||
| (Some(f1), None) => Some(f1)
|
||||
| (None, Some(f2)) => Some(f2)
|
||||
| (None, None) => None
|
||||
};
|
||||
|
||||
module Mixed = {
|
||||
let make = (~continuous, ~discrete, ~discreteProbabilityMassFraction) => {
|
||||
continuous,
|
||||
|
@ -166,6 +194,12 @@ module Mixed = {
|
|||
discreteProbabilityMassFraction,
|
||||
};
|
||||
|
||||
let minX = (t: DistributionTypes.mixedShape) =>
|
||||
min(t.continuous |> Continuous.minX, t.discrete |> Discrete.minX);
|
||||
|
||||
let maxX = (t: DistributionTypes.mixedShape) =>
|
||||
min(t.continuous |> Continuous.maxX, t.discrete |> Discrete.maxX);
|
||||
|
||||
let mixedMultiply =
|
||||
(
|
||||
t: DistributionTypes.mixedShape,
|
||||
|
@ -197,10 +231,6 @@ module Mixed = {
|
|||
| _ => None
|
||||
};
|
||||
};
|
||||
//Do the math to add these distributions together
|
||||
// let integral =
|
||||
// (x: float, t: DistributionTypes.mixedShape): option(XYShape.t) => {
|
||||
// };
|
||||
};
|
||||
|
||||
module Any = {
|
||||
|
@ -223,6 +253,20 @@ module Any = {
|
|||
Continuous.findIntegralY(x, continuousShape)
|
||||
};
|
||||
|
||||
let minX = (t: t) =>
|
||||
switch (t) {
|
||||
| Mixed(m) => Mixed.minX(m)
|
||||
| Discrete(discreteShape) => Discrete.minX(discreteShape)
|
||||
| Continuous(continuousShape) => Continuous.minX(continuousShape)
|
||||
};
|
||||
|
||||
let maxX = (t: t) =>
|
||||
switch (t) {
|
||||
| Mixed(m) => Mixed.maxX(m)
|
||||
| Discrete(discreteShape) => Discrete.maxX(discreteShape)
|
||||
| Continuous(continuousShape) => Continuous.maxX(continuousShape)
|
||||
};
|
||||
|
||||
// TODO: This is wrong. The discrete component should be made continuous when integrating.
|
||||
let pdfToCdf = (t: t) =>
|
||||
switch (t) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user