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 = () =>
<div>
<div>
<h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
<GenericDistributionChart dist=timeDist />
<h2> {"Simple Continuous" |> ReasonReact.string} </h2>
</div>
// <GenericDistributionChart dist=mixedDist />
<h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
{timeDist
|> E.O.React.fmapOrNull(dist => <GenericDistributionChart dist />)}
<h2> {"Simple Continuous" |> ReasonReact.string} </h2>
</div>
</div>;
// <GenericDistributionChart dist=mixedDist />
// <div>
// <h2> {"Time Distribution" |> ReasonReact.string} </h2>
// <GenericDistributionChart dist=timeDist />

View File

@ -7,7 +7,11 @@ module Mixed = {
React.useMemo1(
() =>
<CdfChart__Plain
data={data.continuous}
data={
data.continuous
|> Shape.Continuous.normalizePdf
|> E.O.toExt("")
}
color={`hex("333")}
timeScale
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]
let make = (~dist) => {
switch ((dist: option(DistributionTypes.genericDistribution))) {
| Some({
switch ((dist: DistributionTypes.genericDistribution)) {
| {
unit,
generationSource:
Shape(
@ -60,8 +150,9 @@ let make = (~dist) => {
discreteProbabilityMassFraction: f,
}),
),
}) =>
} =>
<div>
<GenericDist genericDistribution=dist />
<Mixed
unit
data={

View File

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

View File

@ -32,17 +32,97 @@ let renderIfNeeded =
);
| Shape(_) => Some(t)
};
} /* }*/;
};
// let getTimeY =
// (t: genericDistribution, point: TimeTypes.RelativeTimePoint.timeInVector) => {
// switch (t) {
// | {
// generationSource: Shape(shape),
// probabilityType: Pdf,
// unit: Time(timeVector),
// } =>
// TimeTypes.RelativeTimePoint.toXValue(timeVector, point)
// |> E.O.fmap(x => Shape.Mixed.getY(t, x))
// | _ => 2.0
// };
let normalizeCdf = (t: DistributionTypes.pointsType) => {
switch (t) {
| Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
Mixed({
continuous: continuous |> Shape.Continuous.normalizeCdf,
discrete: discrete |> Shape.Discrete.scaleYToTotal(1.0),
discreteProbabilityMassFraction,
})
| Discrete(d) => Discrete(d |> Shape.Discrete.scaleYToTotal(1.0))
| Continuous(continuousShape) =>
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 findY = CdfLibrary.Distribution.findY;
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 = {
@ -208,11 +214,11 @@ module Any = {
let yIntegral = (t: t, x: float) =>
switch (t) {
| Mixed(m) => `mixed(Mixed.findYIntegral(x, m))
| Mixed(m) => Mixed.findYIntegral(x, m)
| Discrete(discreteShape) =>
`discrete(Discrete.findIntegralY(x, discreteShape))
Discrete.findIntegralY(x, discreteShape) |> E.O.some
| Continuous(continuousShape) =>
`continuous(Continuous.findIntegralY(x, continuousShape))
Continuous.findIntegralY(x, continuousShape)
};
};