Simple normalizing functions

This commit is contained in:
Ozzie Gooen 2020-02-19 22:28:16 +00:00
parent 510519b24a
commit 25f83d5290
5 changed files with 209 additions and 26 deletions

View File

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

View File

@ -7,7 +7,11 @@ module Mixed = {
React.useMemo1( React.useMemo1(
() => () =>
<CdfChart__Plain <CdfChart__Plain
data={data.continuous} data={
data.continuous
|> Shape.Continuous.normalizePdf
|> E.O.toExt("")
}
color={`hex("333")} color={`hex("333")}
timeScale timeScale
onHover={r => setX(_ => r)} onHover={r => setX(_ => r)}
@ -47,10 +51,96 @@ module Mixed = {
}; };
}; };
let discreteComponent = (p: DistributionTypes.pointsType) =>
switch (p) {
| Mixed(mixedShape) => Some(mixedShape.discrete)
| Discrete(discreteShape) => Some(discreteShape)
| Continuous(_) => None
};
let continuousComponent = (p: DistributionTypes.pointsType) =>
switch (p) {
| Mixed(mixedShape) => Some(mixedShape.continuous)
| Discrete(_) => None
| Continuous(c) => Some(c)
};
module Cont = {
[@react.component]
let make = (~continuous, ~onHover, ~timeScale) => {
let chart =
React.useMemo1(
() => <CdfChart__Plain data=continuous color={`hex("333")} onHover />,
[|continuous|],
);
chart;
};
};
module Shapee = {
[@react.component]
let make = (~shape: DistributionTypes.pointsType, ~timeScale, ~onHover) => {
let continuous = continuousComponent(shape);
let discrete = discreteComponent(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
)}
</div>;
};
};
module GenericDist = {
[@react.component]
let make = (~genericDistribution: DistributionTypes.genericDistribution) => {
let (x, setX) = React.useState(() => 0.);
let timeScale =
genericDistribution.unit |> DistributionTypes.DistributionUnit.toJson;
<div>
{genericDistribution
|> DistributionTypes.shape
|> E.O.React.fmapOrNull(shape => {
<Shapee shape timeScale onHover={r => setX(_ => r)} />
})}
<table className="table-auto">
<thead>
<tr>
<th className="px-4 py-2"> {"X Point" |> ReasonReact.string} </th>
<th className="px-4 py-2">
{"Y Integral to Point" |> ReasonReact.string}
</th>
</tr>
</thead>
<tbody>
<tr>
<th className="px-4 py-2 border ">
{x |> E.Float.toString |> ReasonReact.string}
</th>
<th className="px-4 py-2 border ">
{genericDistribution
|> DistributionTypes.shape
|> E.O.bind(_, r => Shape.Any.yIntegral(r, x))
|> E.O.fmap(E.Float.with2DigitsPrecision)
|> E.O.default("")
|> ReasonReact.string}
</th>
</tr>
</tbody>
</table>
<div />
</div>;
};
};
[@react.component] [@react.component]
let make = (~dist) => { let make = (~dist) => {
switch ((dist: option(DistributionTypes.genericDistribution))) { switch ((dist: DistributionTypes.genericDistribution)) {
| Some({ | {
unit, unit,
generationSource: generationSource:
Shape( Shape(
@ -60,8 +150,9 @@ let make = (~dist) => {
discreteProbabilityMassFraction: f, discreteProbabilityMassFraction: f,
}), }),
), ),
}) => } =>
<div> <div>
<GenericDist genericDistribution=dist />
<Mixed <Mixed
unit unit
data={ data={

View File

@ -48,6 +48,12 @@ type genericDistribution = {
unit: distributionUnit, unit: distributionUnit,
}; };
let shape = ({generationSource}: genericDistribution) =>
switch (generationSource) {
| GuesstimatorString(_) => None
| Shape(pointsType) => Some(pointsType)
};
module DistributionUnit = { module DistributionUnit = {
let toJson = (distributionUnit: distributionUnit) => let toJson = (distributionUnit: distributionUnit) =>
switch (distributionUnit) { switch (distributionUnit) {

View File

@ -32,17 +32,97 @@ let renderIfNeeded =
); );
| Shape(_) => Some(t) | Shape(_) => Some(t)
}; };
} /* }*/; };
// let getTimeY = let normalizeCdf = (t: DistributionTypes.pointsType) => {
// (t: genericDistribution, point: TimeTypes.RelativeTimePoint.timeInVector) => { switch (t) {
// switch (t) { | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
// | { Mixed({
// generationSource: Shape(shape), continuous: continuous |> Shape.Continuous.normalizeCdf,
// probabilityType: Pdf, discrete: discrete |> Shape.Discrete.scaleYToTotal(1.0),
// unit: Time(timeVector), discreteProbabilityMassFraction,
// } => })
// TimeTypes.RelativeTimePoint.toXValue(timeVector, point) | Discrete(d) => Discrete(d |> Shape.Discrete.scaleYToTotal(1.0))
// |> E.O.fmap(x => Shape.Mixed.getY(t, x)) | Continuous(continuousShape) =>
// | _ => 2.0 Continuous(Shape.Continuous.normalizeCdf(continuousShape))
// }; };
};
let normalizePdf = (t: DistributionTypes.pointsType) => {
switch (t) {
| Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
continuous
|> Shape.Continuous.normalizePdf
|> E.O.fmap(r =>
Mixed({
continuous: r,
discrete: discrete |> Shape.Discrete.scaleYToTotal(1.0),
discreteProbabilityMassFraction,
})
)
| Discrete(d) => Some(Discrete(d |> Shape.Discrete.scaleYToTotal(1.0)))
| Continuous(continuousShape) =>
continuousShape
|> Shape.Continuous.normalizePdf
|> E.O.fmap(r => Continuous(r))
};
};
let normalize = (t: genericDistribution): genericDistribution => {
switch (t.generationSource) {
| Shape(shape) => t
| GuesstimatorString(_) => t
};
};
let excludedProbabilityMass = (t: DistributionTypes.domain) => {
switch (t) {
| Complete => 1.0
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
| RightLimited({excludingProbabilityMass}) => excludingProbabilityMass
| LeftAndRightLimited(
{excludingProbabilityMass: l},
{excludingProbabilityMass: r},
) =>
l +. r
};
};
let initialProbabilityMass = (t: DistributionTypes.domain) => {
switch (t) {
| Complete
| RightLimited(_) => 0.0
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
| LeftAndRightLimited({excludingProbabilityMass}, _) => excludingProbabilityMass
};
};
let normalizeProbabilityMass = (t: DistributionTypes.domain) => {
1. /. excludedProbabilityMass(t);
};
let yIntegral = (t: DistributionTypes.genericDistribution, x) => {
let addInitialMass = n => n +. initialProbabilityMass(t.domain);
let normalize = n => n *. normalizeProbabilityMass(t.domain);
switch (t) {
| {generationSource: Shape(shape)} =>
Shape.Any.yIntegral(shape, x)
|> E.O.fmap(addInitialMass)
|> E.O.fmap(normalize)
| _ => None
};
};
let integrate = (t: DistributionTypes.genericDistribution) => {
switch (t) {
| {probabilityType: Pdf, generationSource: Shape(shape), domain, unit} =>
Some({
generationSource: Shape(shape),
probabilityType: Cdf,
domain,
unit,
})
| {probabilityType: Cdf, generationSource, domain, unit} => None
| _ => None
};
};

View File

@ -108,6 +108,12 @@ module Continuous = {
let findX = CdfLibrary.Distribution.findX; let findX = CdfLibrary.Distribution.findX;
let findY = CdfLibrary.Distribution.findY; let findY = CdfLibrary.Distribution.findY;
let findIntegralY = (f, r) => r |> toCdf |> E.O.fmap(findY(f)); let findIntegralY = (f, r) => r |> toCdf |> E.O.fmap(findY(f));
let normalizeCdf = (continuousShape: continuousShape) =>
continuousShape |> XYShape.scaleCdfTo(~scaleTo=1.0);
let normalizePdf = (continuousShape: continuousShape) =>
continuousShape |> toCdf |> E.O.fmap(normalizeCdf) |> E.O.bind(_, toPdf);
}; };
module Discrete = { module Discrete = {
@ -208,11 +214,11 @@ module Any = {
let yIntegral = (t: t, x: float) => let yIntegral = (t: t, x: float) =>
switch (t) { switch (t) {
| Mixed(m) => `mixed(Mixed.findYIntegral(x, m)) | Mixed(m) => Mixed.findYIntegral(x, m)
| Discrete(discreteShape) => | Discrete(discreteShape) =>
`discrete(Discrete.findIntegralY(x, discreteShape)) Discrete.findIntegralY(x, discreteShape) |> E.O.some
| Continuous(continuousShape) => | Continuous(continuousShape) =>
`continuous(Continuous.findIntegralY(x, continuousShape)) Continuous.findIntegralY(x, continuousShape)
}; };
}; };