The slow replacement of Shape.re begins

This commit is contained in:
Ozzie Gooen 2020-02-22 19:21:04 +00:00
parent 0d2c53eca4
commit cd1b114295
5 changed files with 175 additions and 204 deletions

View File

@ -45,7 +45,7 @@ let make =
?minX
?scale
?timeScale
discrete={discrete |> E.O.fmap(Shape.Discrete.toJs)}
discrete={discrete |> E.O.fmap(XYShape.toJs)}
height
marginBottom=50
marginTop=0

View File

@ -49,6 +49,12 @@ module Dist = (T: dist) => {
let xToY = T.integralXtoY;
let sum = T.integralSum;
};
// This is suboptimal because it could get the cache but doesn't here.
let scaleToIntegralSum = (~intendedSum=1.0, t: t) => {
let scale = intendedSum /. Integral.sum(~cache=None, t);
scaleBy(~scale, t);
};
};
module Continuous = {
@ -123,6 +129,31 @@ module Discrete = {
};
module Mixed = {
let make =
(~continuous, ~discrete, ~discreteProbabilityMassFraction)
: DistributionTypes.mixedShape => {
continuous,
discrete,
discreteProbabilityMassFraction,
};
let clean =
(t: DistributionTypes.mixedShape): option(DistributionTypes.shape) => {
switch (t) {
| {
continuous: {xyShape: {xs: [||], ys: [||]}},
discrete: {xs: [||], ys: [||]},
} =>
None
| {discrete: {xs: [|_|], ys: [|_|]}} => None
| {continuous, discrete: {xs: [||], ys: [||]}} =>
Some(Continuous(continuous))
| {continuous: {xyShape: {xs: [||], ys: [||]}}, discrete} =>
Some(Discrete(discrete))
| shape => Some(Mixed(shape))
};
};
module T =
Dist({
type t = DistributionTypes.mixedShape;
@ -312,24 +343,24 @@ module WithMetadata = {
type t = DistributionTypes.complexPower;
type integral = DistributionTypes.complexPower;
let toShape = ({shape, _}: t) => shape;
let toContinuous = (t: t) => t |> toShape |> Shape.T.toContinuous;
let toDiscrete = (t: t) => t |> toShape |> Shape.T.toDiscrete;
let shapeFn = (fn, t: t) => t |> toShape |> fn;
let toContinuous = shapeFn(Shape.T.toContinuous);
let toDiscrete = shapeFn(Shape.T.toDiscrete);
// todo: adjust for limit, and the fact that total mass is lower.
let xToY = (f, t: t) => t |> toShape |> Shape.T.xToY(f);
let minX = (t: t) => t |> toShape |> Shape.T.minX;
let maxX = (t: t) => t |> toShape |> Shape.T.maxX;
let xToY = f => shapeFn(Shape.T.xToY(f));
let minX = shapeFn(Shape.T.minX);
let maxX = shapeFn(Shape.T.maxX);
let fromShape = (shape, t): t => DistributionTypes.update(~shape, t);
// todo: adjust for limit
let pointwiseFmap = (fn, {shape, _} as t: t): t =>
fromShape(Shape.T.pointwiseFmap(fn, shape), t);
let integral = (~cache as _, t: t) =>
fromShape(Continuous(t.integralCache), t);
let integralSum = (~cache as _, t: t) =>
t |> toShape |> Shape.T.Integral.sum(~cache=Some(t.integralCache));
Shape.T.Integral.sum(~cache=Some(t.integralCache), toShape(t));
// TODO: Fix this below, obviously. Adjust for limit.
let integralXtoY = (~cache as _, f, t) => {
1337.0;
let integralXtoY = (~cache as _, f, t: t) => {
Shape.T.Integral.xToY(~cache=Some(t.integralCache), f, toShape(t));
};
});
};

View File

@ -49,7 +49,7 @@ let renderIfNeeded =
switch (t.generationSource) {
| GuesstimatorString(s) =>
Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ())
|> E.O.bind(_, Shape.Mixed.clean)
|> E.O.bind(_, DistFunctor.Mixed.clean)
|> E.O.fmap((shape: DistributionTypes.shape) =>
make(
~generationSource=Shape(shape),
@ -71,13 +71,9 @@ let normalize = (t: genericDistribution): option(genericDistribution) => {
};
let yIntegral = (t: DistributionTypes.genericDistribution, x) => {
let addInitialMass = n => n +. Domain.initialProbabilityMass(t.domain);
let normalize = n => n *. Domain.normalizeProbabilityMass(t.domain);
switch (t) {
| {generationSource: Shape(shape)} =>
Shape.T.yIntegral(shape, x)
|> E.O.fmap(addInitialMass)
|> E.O.fmap(normalize)
Some(DistFunctor.Shape.T.Integral.xToY(~cache=None, x, shape))
| _ => None
};
};

View File

@ -17,7 +17,7 @@ let build = (~continuous, ~discrete, ~assumptions) =>
} =>
// TODO: Fix this, it's wrong :(
Some(
Shape.Mixed.make(
DistFunctor.Mixed.make(
~continuous,
~discrete,
~discreteProbabilityMassFraction=r,
@ -30,7 +30,7 @@ let build = (~continuous, ~discrete, ~assumptions) =>
discreteProbabilityMass: Some(r),
} =>
Some(
Shape.Mixed.make(
DistFunctor.Mixed.make(
~continuous,
~discrete,
~discreteProbabilityMassFraction=r,
@ -56,10 +56,12 @@ let build = (~continuous, ~discrete, ~assumptions) =>
discrete: ADDS_TO_CORRECT_PROBABILITY,
discreteProbabilityMass: None,
} =>
let discreteProbabilityMassFraction = Shape.Discrete.ySum(discrete);
let discrete = Shape.Discrete.scaleYToTotal(1.0, discrete);
let discreteProbabilityMassFraction =
DistFunctor.Discrete.T.Integral.sum(~cache=None, discrete);
let discrete =
DistFunctor.Discrete.T.scaleToIntegralSum(~intendedSum=1.0, discrete);
Some(
Shape.Mixed.make(
DistFunctor.Mixed.make(
~continuous,
~discrete,
~discreteProbabilityMassFraction,

View File

@ -115,11 +115,11 @@ let max = (f1: option(float), f2: option(float)) =>
};
module Mixed = {
let make = (~continuous, ~discrete, ~discreteProbabilityMassFraction) => {
continuous,
discrete,
discreteProbabilityMassFraction,
};
// let make = (~continuous, ~discrete, ~discreteProbabilityMassFraction) => {
// continuous,
// discrete,
// discreteProbabilityMassFraction,
// };
let minX = (t: DistributionTypes.mixedShape) =>
min(t.continuous |> Continuous.minX, t.discrete |> Discrete.minX);
@ -163,193 +163,135 @@ module Mixed = {
| _ => None
};
};
} /* }*/;
let clean = (t: DistributionTypes.mixedShape) =>
switch (t) {
| {
continuous: {xyShape: {xs: [||], ys: [||]}},
discrete: {xs: [||], ys: [||]},
} =>
None
| {discrete: {xs: [|_|], ys: [|_|]}} => None
| {continuous, discrete: {xs: [||], ys: [||]}} =>
Some(Continuous(continuous))
| {continuous: {xyShape: {xs: [||], ys: [||]}}, discrete} =>
Some(Discrete(discrete))
| shape => Some(Mixed(shape))
};
};
// module T = {
// type t = DistributionTypes.shape;
module T = {
type t = DistributionTypes.shape;
// let y = (t: t, x: float) =>
// switch (t) {
// | Mixed(m) => `mixed(Mixed.findY(m, x))
// | Discrete(discreteShape) => `discrete(Discrete.findY(x, discreteShape))
// | Continuous(continuousShape) =>
// `continuous(Continuous.findY(x, continuousShape))
// };
let y = (t: t, x: float) =>
switch (t) {
| Mixed(m) => `mixed(Mixed.findY(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.findYIntegral(x, m)
// | Discrete(discreteShape) =>
// Discrete.findIntegralY(x, discreteShape) |> E.O.some
// | Continuous(continuousShape) =>
// Continuous.findIntegralY(x, continuousShape)
// };
let yIntegral = (t: t, x: float) =>
switch (t) {
| Mixed(m) => Mixed.findYIntegral(x, m)
| Discrete(discreteShape) =>
Discrete.findIntegralY(x, discreteShape) |> E.O.some
| Continuous(continuousShape) =>
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 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)
// };
let maxX = (t: t) =>
switch (t) {
| Mixed(m) => Mixed.maxX(m)
| Discrete(discreteShape) => Discrete.maxX(discreteShape)
| Continuous(continuousShape) => Continuous.maxX(continuousShape)
};
// let discreteComponent = (t: t) =>
// switch (t) {
// | Mixed({discrete}) => Some(discrete)
// | Discrete(d) => Some(d)
// | Continuous(_) => None
// };
let discreteComponent = (t: t) =>
switch (t) {
| Mixed({discrete}) => Some(discrete)
| Discrete(d) => Some(d)
| Continuous(_) => None
};
// let continuousComponent = (t: t) =>
// switch (t) {
// | Mixed({continuous}) => Some(continuous)
// | Continuous(c) => Some(c)
// | Discrete(_) => None
// };
// // let scaledContinuousComponent = (t: t): option(continuousShape) => {
// // switch (t) {
// // | Mixed({continuous, discreteProbabilityMassFraction}) =>
// // Continuous.scalePdf(
// // ~scaleTo=1.0 -. discreteProbabilityMassFraction,
// // continuous,
// // )
// // | Discrete(_) => None
// // | Continuous(c) => Some(c)
// // };
// // };
// // let scaledDiscreteComponent = (t: t): option(discreteShape) => {
// // switch (t) {
// // | Mixed({discrete, discreteProbabilityMassFraction}) =>
// // Some(Discrete.scaleYToTotal(discreteProbabilityMassFraction, discrete))
// // | Discrete(d) => Some(d)
// // | Continuous(_) => None
// // };
// // };
// // let pointwiseFmap = (fn, t: t): shape =>
// // switch (t) {
// // | Mixed({discrete, continuous, discreteProbabilityMassFraction}) =>
// // Mixed({
// // continuous: XYShape.pointwiseMap(fn, continuous),
// // discrete: XYShape.pointwiseMap(fn, discrete),
// // discreteProbabilityMassFraction,
// // })
// // | Discrete(x) => Discrete(XYShape.pointwiseMap(fn, x))
// // | Continuous(x) => Continuous(XYShape.pointwiseMap(fn, x))
// // };
// // module Cdf = {
// // let normalizeCdf = (t: DistributionTypes.shape) => {
// // switch (t) {
// // | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
// // Mixed({
// // continuous: continuous |> Continuous.normalizeCdf,
// // discrete: discrete |> Discrete.scaleYToTotal(1.0),
// // discreteProbabilityMassFraction,
// // })
// // | Discrete(d) => Discrete(d |> Discrete.scaleYToTotal(1.0))
// // | Continuous(continuousShape) =>
// // Continuous(Continuous.normalizeCdf(continuousShape))
// // };
// // };
// // };
// };
let continuousComponent = (t: t) =>
switch (t) {
| Mixed({continuous}) => Some(continuous)
| Continuous(c) => Some(c)
| Discrete(_) => None
};
// module PdfCdfShape = {
// type t = pdfCdfCombo;
// let pdf = (t: t) =>
// switch (t.pdf) {
// | Mixed(pdf) => Mixed(pdf)
// | Discrete(pdf) => Discrete(pdf)
// | Continuous(pdf) => Continuous(pdf)
// };
// let cdf = (t: t) => t.cdf;
// };
// let scaledContinuousComponent = (t: t): option(continuousShape) => {
// switch (t) {
// | Mixed({continuous, discreteProbabilityMassFraction}) =>
// Continuous.scalePdf(
// ~scaleTo=1.0 -. discreteProbabilityMassFraction,
// continuous,
// )
// | Discrete(_) => None
// | Continuous(c) => Some(c)
// };
// };
// type distributionUnit =
// | UnspecifiedDistribution
// | TimeDistribution(TimeTypes.timeVector);
// let scaledDiscreteComponent = (t: t): option(discreteShape) => {
// switch (t) {
// | Mixed({discrete, discreteProbabilityMassFraction}) =>
// Some(Discrete.scaleYToTotal(discreteProbabilityMassFraction, discrete))
// | Discrete(d) => Some(d)
// | Continuous(_) => None
// };
// };
// type withLimitedDomain = {
// domain,
// dist: pdfCdfCombo,
// };
// let pointwiseFmap = (fn, t: t): shape =>
// switch (t) {
// | Mixed({discrete, continuous, discreteProbabilityMassFraction}) =>
// Mixed({
// continuous: XYShape.pointwiseMap(fn, continuous),
// discrete: XYShape.pointwiseMap(fn, discrete),
// discreteProbabilityMassFraction,
// })
// | Discrete(x) => Discrete(XYShape.pointwiseMap(fn, x))
// | Continuous(x) => Continuous(XYShape.pointwiseMap(fn, x))
// };
// module WithLimitedDomain = {
// type t = withLimitedDomain;
// let dist = (t: t) => t.dist;
// let pdf = (t: t) => PdfCdfShape.pdf(t.dist);
// let cdf = (t: t) => PdfCdfShape.cdf(t.dist);
// // TODO: This is bad, obviously needs to be fixed.
// let distScaleFactor = (t: t) => 3.0;
// // let scaledPdfShape = (scaleFactor, t: t) =>
// // t |> pdf |> T.pointwiseFmap(r => r *. scaleFactor);
// // let scaledCdfShape = (scaleFactor, t: t) =>
// // t |> cdf |> XYShape.pointwiseMap(r => r *. scaleFactor);
// };
// module Cdf = {
// let normalizeCdf = (t: DistributionTypes.shape) => {
// switch (t) {
// | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
// Mixed({
// continuous: continuous |> Continuous.normalizeCdf,
// discrete: discrete |> Discrete.scaleYToTotal(1.0),
// discreteProbabilityMassFraction,
// })
// | Discrete(d) => Discrete(d |> Discrete.scaleYToTotal(1.0))
// | Continuous(continuousShape) =>
// Continuous(Continuous.normalizeCdf(continuousShape))
// };
// };
// };
module Pdf = {
// TODO: This is wrong. The discrete component should be made continuous when integrating.
// let toCdf = (t: t) =>
// switch (t) {
// | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
// Some(
// Mixed({
// continuous: Continuous.toCdf(continuous) |> E.O.toExt(""),
// discrete: discrete |> Discrete.integrate,
// discreteProbabilityMassFraction,
// }),
// )
// | Discrete(discrete) =>
// Some(Continuous(discrete |> Discrete.integrate))
// | Continuous(continuous) =>
// Continuous.toCdf(continuous) |> E.O.fmap(e => Continuous(e))
// };
// let normalize = (t: DistributionTypes.shape): option(shape) => {
// switch (t) {
// | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
// continuous
// |> Continuous.scalePdf(~scaleTo=1.0)
// |> E.O.fmap(r =>
// Mixed({
// continuous: r,
// discrete: discrete |> Discrete.scaleYToTotal(1.0),
// discreteProbabilityMassFraction,
// })
// )
// | Discrete(d) => Some(Discrete(d |> Discrete.scaleYToTotal(1.0)))
// | Continuous(continuousShape) =>
// continuousShape
// |> Continuous.scalePdf(~scaleTo=1.0)
// |> E.O.fmap(r => Continuous(r))
// };
// };
};
};
module PdfCdfShape = {
type t = pdfCdfCombo;
let pdf = (t: t) =>
switch (t.pdf) {
| Mixed(pdf) => Mixed(pdf)
| Discrete(pdf) => Discrete(pdf)
| Continuous(pdf) => Continuous(pdf)
};
let cdf = (t: t) => t.cdf;
};
type distributionUnit =
| UnspecifiedDistribution
| TimeDistribution(TimeTypes.timeVector);
type withLimitedDomain = {
domain,
dist: pdfCdfCombo,
};
module WithLimitedDomain = {
type t = withLimitedDomain;
let dist = (t: t) => t.dist;
let pdf = (t: t) => PdfCdfShape.pdf(t.dist);
let cdf = (t: t) => PdfCdfShape.cdf(t.dist);
// TODO: This is bad, obviously needs to be fixed.
let distScaleFactor = (t: t) => 3.0;
// let scaledPdfShape = (scaleFactor, t: t) =>
// t |> pdf |> T.pointwiseFmap(r => r *. scaleFactor);
// let scaledCdfShape = (scaleFactor, t: t) =>
// t |> cdf |> XYShape.pointwiseMap(r => r *. scaleFactor);
};
type withTimeVector = {
timeVector: TimeTypes.timeVector,
dist: withLimitedDomain,
};
// type withTimeVector = {
// timeVector: TimeTypes.timeVector,
// dist: withLimitedDomain,