Starting to move functionality into functor
This commit is contained in:
parent
7bc62d3934
commit
745cf01317
|
@ -1,12 +1,12 @@
|
||||||
module Shapee = {
|
module Shapee = {
|
||||||
[@react.component]
|
[@react.component]
|
||||||
let make = (~shape: DistributionTypes.pointsType, ~timeScale, ~onHover) => {
|
let make = (~shape: DistributionTypes.shape, ~timeScale, ~onHover) => {
|
||||||
let discrete = Shape.PointsType.scaledDiscreteComponent(shape);
|
let discrete = Shape.T.scaledDiscreteComponent(shape);
|
||||||
let continuous = Shape.PointsType.scaledContinuousComponent(shape);
|
let continuous = Shape.T.scaledContinuousComponent(shape);
|
||||||
<div>
|
<div>
|
||||||
<CdfChart__Plain
|
<CdfChart__Plain
|
||||||
minX={Shape.PointsType.minX(shape)}
|
minX={Shape.T.minX(shape)}
|
||||||
maxX={Shape.PointsType.maxX(shape)}
|
maxX={Shape.T.maxX(shape)}
|
||||||
?discrete
|
?discrete
|
||||||
?continuous
|
?continuous
|
||||||
color={`hex("333")}
|
color={`hex("333")}
|
||||||
|
@ -28,7 +28,7 @@ module GenericDist = {
|
||||||
React.useMemo1(
|
React.useMemo1(
|
||||||
() => {
|
() => {
|
||||||
genericDistribution
|
genericDistribution
|
||||||
|> DistributionTypes.shape
|
|> DistributionTypes.shapee
|
||||||
|> E.O.React.fmapOrNull(shape => {
|
|> E.O.React.fmapOrNull(shape => {
|
||||||
<Shapee shape timeScale onHover={r => setX(_ => r)} />
|
<Shapee shape timeScale onHover={r => setX(_ => r)} />
|
||||||
})
|
})
|
||||||
|
|
218
src/core/DistFunctor.re
Normal file
218
src/core/DistFunctor.re
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
type yPoint =
|
||||||
|
| Mixed({
|
||||||
|
continuous: float,
|
||||||
|
discrete: float,
|
||||||
|
})
|
||||||
|
| Continuous(float)
|
||||||
|
| Discrete(float);
|
||||||
|
|
||||||
|
module type dist = {
|
||||||
|
type t;
|
||||||
|
type integral;
|
||||||
|
let minX: t => option(float);
|
||||||
|
let maxX: t => option(float);
|
||||||
|
let pointwiseFmap: (float => float, t) => t;
|
||||||
|
let xToY: (float, t) => yPoint;
|
||||||
|
let xToIntegralY: (float, t) => float;
|
||||||
|
let shape: t => DistributionTypes.shape;
|
||||||
|
let integral: t => integral;
|
||||||
|
let integralSum: t => float;
|
||||||
|
};
|
||||||
|
|
||||||
|
module Dist = (T: dist) => {
|
||||||
|
type t = T.t;
|
||||||
|
type integral = T.integral;
|
||||||
|
let minX = T.minX;
|
||||||
|
let maxX = T.maxX;
|
||||||
|
let pointwiseFmap = T.pointwiseFmap;
|
||||||
|
let xToIntegralY = T.xToIntegralY;
|
||||||
|
let xToY = T.xToY;
|
||||||
|
let shape = T.shape;
|
||||||
|
let integral = T.integral;
|
||||||
|
let integralSum = T.integralSum;
|
||||||
|
};
|
||||||
|
|
||||||
|
module Continuous =
|
||||||
|
Dist({
|
||||||
|
type t = DistributionTypes.continuousShape;
|
||||||
|
type integral = DistributionTypes.continuousShape;
|
||||||
|
let integral = t =>
|
||||||
|
t |> Shape.XYShape.Range.integrateWithTriangles |> E.O.toExt("");
|
||||||
|
let integralSum = t => t |> integral |> Shape.XYShape.ySum;
|
||||||
|
let minX = Shape.XYShape.minX;
|
||||||
|
let maxX = Shape.XYShape.maxX;
|
||||||
|
let pointwiseFmap = Shape.XYShape.pointwiseMap;
|
||||||
|
let shape = (t: t): DistributionTypes.shape => Continuous(t);
|
||||||
|
let xToY = (f, t) =>
|
||||||
|
CdfLibrary.Distribution.findY(f, t) |> (e => Continuous(e));
|
||||||
|
let xToIntegralY = (f, t) =>
|
||||||
|
t |> integral |> CdfLibrary.Distribution.findY(f);
|
||||||
|
});
|
||||||
|
|
||||||
|
module Discrete =
|
||||||
|
Dist({
|
||||||
|
type t = DistributionTypes.discreteShape;
|
||||||
|
type integral = DistributionTypes.continuousShape;
|
||||||
|
let integral = t => t |> Shape.Discrete.integrate;
|
||||||
|
let integralSum = t => t |> Shape.XYShape.ySum;
|
||||||
|
let minX = Shape.XYShape.minX;
|
||||||
|
let maxX = Shape.XYShape.maxX;
|
||||||
|
let pointwiseFmap = Shape.XYShape.pointwiseMap;
|
||||||
|
let shape = (t: t): DistributionTypes.shape => Discrete(t);
|
||||||
|
let xToY = (f, t) =>
|
||||||
|
CdfLibrary.Distribution.findY(f, t) |> (e => Discrete(e));
|
||||||
|
let xToIntegralY = (f, t) =>
|
||||||
|
t |> Shape.XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
|
||||||
|
});
|
||||||
|
|
||||||
|
module Mixed =
|
||||||
|
Dist({
|
||||||
|
type t = DistributionTypes.mixedShape;
|
||||||
|
type integral = DistributionTypes.continuousShape;
|
||||||
|
let minX = ({continuous, discrete}: t) =>
|
||||||
|
min(Continuous.minX(continuous), Discrete.minX(discrete));
|
||||||
|
let maxX = ({continuous, discrete}: t) =>
|
||||||
|
max(Continuous.maxX(continuous), Discrete.maxX(discrete));
|
||||||
|
let shape = (t: t): DistributionTypes.shape => Mixed(t);
|
||||||
|
let xToY =
|
||||||
|
(f, {discrete, continuous, discreteProbabilityMassFraction}: t) =>
|
||||||
|
Mixed({
|
||||||
|
continuous:
|
||||||
|
CdfLibrary.Distribution.findY(f, continuous)
|
||||||
|
|> (e => e *. (1. -. discreteProbabilityMassFraction)),
|
||||||
|
discrete:
|
||||||
|
Shape.Discrete.findY(f, discrete)
|
||||||
|
|> (e => e *. discreteProbabilityMassFraction),
|
||||||
|
});
|
||||||
|
|
||||||
|
let scaledContinuousComponent =
|
||||||
|
({continuous, discreteProbabilityMassFraction}: t)
|
||||||
|
: option(DistributionTypes.continuousShape) => {
|
||||||
|
Shape.Continuous.scalePdf(
|
||||||
|
~scaleTo=1.0 -. discreteProbabilityMassFraction,
|
||||||
|
continuous,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let scaledDiscreteComponent =
|
||||||
|
({discrete, discreteProbabilityMassFraction}: t)
|
||||||
|
: DistributionTypes.continuousShape =>
|
||||||
|
Discrete.pointwiseFmap(
|
||||||
|
f => f *. discreteProbabilityMassFraction,
|
||||||
|
discrete,
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Add these two directly, once interpolation is added.
|
||||||
|
let integral = t => {
|
||||||
|
// let cont = scaledContinuousComponent(t);
|
||||||
|
// let discrete = scaledDiscreteComponent(t);
|
||||||
|
scaledContinuousComponent(t) |> E.O.toExt("");
|
||||||
|
};
|
||||||
|
|
||||||
|
let integralSum =
|
||||||
|
({discrete, continuous, discreteProbabilityMassFraction}: t) => {
|
||||||
|
Discrete.integralSum(discrete)
|
||||||
|
*. discreteProbabilityMassFraction
|
||||||
|
+. Continuous.integralSum(continuous)
|
||||||
|
*. (1.0 -. discreteProbabilityMassFraction);
|
||||||
|
};
|
||||||
|
|
||||||
|
let xToIntegralY =
|
||||||
|
(f, {discrete, continuous, discreteProbabilityMassFraction}: t) => {
|
||||||
|
let cont = Continuous.xToIntegralY(f, continuous);
|
||||||
|
let discrete = Discrete.xToIntegralY(f, discrete);
|
||||||
|
discrete
|
||||||
|
*. discreteProbabilityMassFraction
|
||||||
|
+. cont
|
||||||
|
*. (1.0 -. discreteProbabilityMassFraction);
|
||||||
|
};
|
||||||
|
|
||||||
|
let pointwiseFmap =
|
||||||
|
(fn, {discrete, continuous, discreteProbabilityMassFraction}: t): t => {
|
||||||
|
{
|
||||||
|
discrete: Shape.XYShape.pointwiseMap(fn, discrete),
|
||||||
|
continuous: Shape.XYShape.pointwiseMap(fn, continuous),
|
||||||
|
discreteProbabilityMassFraction,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
module Shape =
|
||||||
|
Dist({
|
||||||
|
type t = DistributionTypes.shape;
|
||||||
|
type integral = DistributionTypes.continuousShape;
|
||||||
|
let xToY = (f, t) =>
|
||||||
|
Shape.T.mapToAll(
|
||||||
|
t,
|
||||||
|
(Mixed.xToY(f), Discrete.xToY(f), Continuous.xToY(f)),
|
||||||
|
);
|
||||||
|
let shape = (t: t) => t;
|
||||||
|
let minX = (t: t) =>
|
||||||
|
Shape.T.mapToAll(t, (Mixed.minX, Discrete.minX, Continuous.minX));
|
||||||
|
let integral = (t: t) =>
|
||||||
|
Shape.T.mapToAll(
|
||||||
|
t,
|
||||||
|
(Mixed.integral, Discrete.integral, Continuous.integral),
|
||||||
|
);
|
||||||
|
let integralSum = (t: t) =>
|
||||||
|
Shape.T.mapToAll(
|
||||||
|
t,
|
||||||
|
(Mixed.integralSum, Discrete.integralSum, Continuous.integralSum),
|
||||||
|
);
|
||||||
|
let xToIntegralY = (f, t) => {
|
||||||
|
Shape.T.mapToAll(
|
||||||
|
t,
|
||||||
|
(
|
||||||
|
Mixed.xToIntegralY(f),
|
||||||
|
Discrete.xToIntegralY(f),
|
||||||
|
Continuous.xToIntegralY(f),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
let maxX = (t: t) =>
|
||||||
|
Shape.T.mapToAll(t, (Mixed.minX, Discrete.minX, Continuous.minX));
|
||||||
|
let pointwiseFmap = (fn, t: t) =>
|
||||||
|
Shape.T.fmap(
|
||||||
|
t,
|
||||||
|
(
|
||||||
|
Mixed.pointwiseFmap(fn),
|
||||||
|
Discrete.pointwiseFmap(fn),
|
||||||
|
Continuous.pointwiseFmap(fn),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
module WithMetadata =
|
||||||
|
Dist({
|
||||||
|
type t = DistributionTypes.complexPower;
|
||||||
|
type integral = DistributionTypes.complexPower;
|
||||||
|
let shape = ({shape, _}: t) => shape;
|
||||||
|
let xToY = (f, t: t) => t |> shape |> Shape.xToY(f);
|
||||||
|
let minX = (t: t) => t |> shape |> Shape.minX;
|
||||||
|
let maxX = (t: t) => t |> shape |> Shape.maxX;
|
||||||
|
let fromShape = (shape, t): t => DistributionTypes.update(~shape, t);
|
||||||
|
let pointwiseFmap = (fn, {shape, _} as t: t): t =>
|
||||||
|
fromShape(Shape.pointwiseFmap(fn, shape), t);
|
||||||
|
|
||||||
|
let integral = (t: t) => fromShape(Continuous(t.integralCache), t);
|
||||||
|
let integralSum = (t: t) => t |> shape |> Shape.integralSum;
|
||||||
|
let xToIntegralY = (f, t) => {
|
||||||
|
3.0;
|
||||||
|
};
|
||||||
|
});
|
|
@ -23,14 +23,26 @@ type mixedShape = {
|
||||||
discreteProbabilityMassFraction: float,
|
discreteProbabilityMassFraction: float,
|
||||||
};
|
};
|
||||||
|
|
||||||
type pointsType =
|
type shapeMonad('a, 'b, 'c) =
|
||||||
| Mixed(mixedShape)
|
| Mixed('a)
|
||||||
| Discrete(discreteShape)
|
| Discrete('b)
|
||||||
| Continuous(continuousShape);
|
| Continuous('c);
|
||||||
|
|
||||||
|
type shape = shapeMonad(mixedShape, discreteShape, continuousShape);
|
||||||
|
|
||||||
|
module ShapeMonad = {
|
||||||
|
let fmap =
|
||||||
|
(t: shapeMonad('a, 'b, 'c), (fn1, fn2, fn3)): shapeMonad('d, 'e, 'f) =>
|
||||||
|
switch (t) {
|
||||||
|
| Mixed(m) => Mixed(fn1(m))
|
||||||
|
| Discrete(m) => Discrete(fn2(m))
|
||||||
|
| Continuous(m) => Continuous(fn3(m))
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
type generationSource =
|
type generationSource =
|
||||||
| GuesstimatorString(string)
|
| GuesstimatorString(string)
|
||||||
| Shape(pointsType);
|
| Shape(shape);
|
||||||
|
|
||||||
type distributionUnit =
|
type distributionUnit =
|
||||||
| UnspecifiedDistribution
|
| UnspecifiedDistribution
|
||||||
|
@ -48,12 +60,31 @@ type genericDistribution = {
|
||||||
unit: distributionUnit,
|
unit: distributionUnit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let shape = ({generationSource}: genericDistribution) =>
|
let shapee = ({generationSource}: genericDistribution) =>
|
||||||
switch (generationSource) {
|
switch (generationSource) {
|
||||||
| GuesstimatorString(_) => None
|
| GuesstimatorString(_) => None
|
||||||
| Shape(pointsType) => Some(pointsType)
|
| Shape(pointsType) => Some(pointsType)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type pdfCdfCombo = {
|
||||||
|
pdf: shape,
|
||||||
|
cdf: continuousShape,
|
||||||
|
};
|
||||||
|
|
||||||
|
type complexPower = {
|
||||||
|
shape,
|
||||||
|
integralCache: continuousShape,
|
||||||
|
domain: domainLimit,
|
||||||
|
unit: distributionUnit,
|
||||||
|
};
|
||||||
|
|
||||||
|
let update = (~shape=?, ~integralCache=?, ~domain=?, ~unit=?, t: complexPower) => {
|
||||||
|
shape: E.O.default(t.shape, shape),
|
||||||
|
integralCache: E.O.default(t.integralCache, integralCache),
|
||||||
|
domain: E.O.default(t.domain, domain),
|
||||||
|
unit: E.O.default(t.unit, unit),
|
||||||
|
};
|
||||||
|
|
||||||
module DistributionUnit = {
|
module DistributionUnit = {
|
||||||
let toJson = (distributionUnit: distributionUnit) =>
|
let toJson = (distributionUnit: distributionUnit) =>
|
||||||
switch (distributionUnit) {
|
switch (distributionUnit) {
|
||||||
|
|
|
@ -43,36 +43,22 @@ let make =
|
||||||
unit,
|
unit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: The fact that it is a CDF is really something you find later, this can't be chosen until GuesstimatorToString happens.
|
||||||
let renderIfNeeded =
|
let renderIfNeeded =
|
||||||
(~sampleCount=1000, t: genericDistribution): option(genericDistribution) => {
|
(~sampleCount=1000, t: genericDistribution): option(genericDistribution) => {
|
||||||
switch (t.generationSource) {
|
switch (t.generationSource) {
|
||||||
| GuesstimatorString(s) =>
|
| GuesstimatorString(s) =>
|
||||||
let shape = Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ());
|
Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ())
|
||||||
let newShape =
|
|> E.O.bind(_, Shape.Mixed.clean)
|
||||||
switch (shape) {
|
|> E.O.fmap((shape: DistributionTypes.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
|
|
||||||
};
|
|
||||||
|
|
||||||
newShape
|
|
||||||
|> E.O.fmap((shape: DistributionTypes.pointsType) =>
|
|
||||||
make(
|
make(
|
||||||
~generationSource=Shape(shape),
|
~generationSource=Shape(shape),
|
||||||
~probabilityType=Cdf,
|
~probabilityType=Pdf,
|
||||||
~domain=t.domain,
|
~domain=t.domain,
|
||||||
~unit=t.unit,
|
~unit=t.unit,
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
| Shape(_) => Some(t)
|
| Shape(_) => Some(t)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -80,7 +66,7 @@ let renderIfNeeded =
|
||||||
let normalize = (t: genericDistribution): option(genericDistribution) => {
|
let normalize = (t: genericDistribution): option(genericDistribution) => {
|
||||||
switch (t.generationSource) {
|
switch (t.generationSource) {
|
||||||
| Shape(shape) =>
|
| Shape(shape) =>
|
||||||
Shape.PointsType.normalizePdf(shape)
|
Shape.T.Pdf.normalize(shape)
|
||||||
|> E.O.fmap(shape => {...t, generationSource: Shape(shape)})
|
|> E.O.fmap(shape => {...t, generationSource: Shape(shape)})
|
||||||
| GuesstimatorString(_) => Some(t)
|
| GuesstimatorString(_) => Some(t)
|
||||||
};
|
};
|
||||||
|
@ -91,7 +77,7 @@ let yIntegral = (t: DistributionTypes.genericDistribution, x) => {
|
||||||
let normalize = n => n *. Domain.normalizeProbabilityMass(t.domain);
|
let normalize = n => n *. Domain.normalizeProbabilityMass(t.domain);
|
||||||
switch (t) {
|
switch (t) {
|
||||||
| {generationSource: Shape(shape)} =>
|
| {generationSource: Shape(shape)} =>
|
||||||
Shape.PointsType.yIntegral(shape, x)
|
Shape.T.yIntegral(shape, x)
|
||||||
|> E.O.fmap(addInitialMass)
|
|> E.O.fmap(addInitialMass)
|
||||||
|> E.O.fmap(normalize)
|
|> E.O.fmap(normalize)
|
||||||
| _ => None
|
| _ => None
|
||||||
|
|
|
@ -25,6 +25,8 @@ module XYShape = {
|
||||||
|
|
||||||
let fmap = (t: t, y): t => {xs: t.xs, ys: t.ys |> E.A.fmap(y)};
|
let fmap = (t: t, y): t => {xs: t.xs, ys: t.ys |> E.A.fmap(y)};
|
||||||
|
|
||||||
|
let pointwiseMap = (fn, t: t): t => {xs: t.xs, ys: t.ys |> E.A.fmap(fn)};
|
||||||
|
|
||||||
let scaleCdfTo = (~scaleTo=1., t: t) =>
|
let scaleCdfTo = (~scaleTo=1., t: t) =>
|
||||||
switch (_lastElement(t.ys)) {
|
switch (_lastElement(t.ys)) {
|
||||||
| Some(n) =>
|
| Some(n) =>
|
||||||
|
@ -135,6 +137,10 @@ module Discrete = {
|
||||||
let toJs = XYShape.toJs;
|
let toJs = XYShape.toJs;
|
||||||
let ySum = XYShape.ySum;
|
let ySum = XYShape.ySum;
|
||||||
let zip = t => Belt.Array.zip(t.xs, t.ys);
|
let zip = t => Belt.Array.zip(t.xs, t.ys);
|
||||||
|
let pointwiseMap = (t: discreteShape, fn): discreteShape => {
|
||||||
|
xs: t.xs,
|
||||||
|
ys: t.ys |> E.A.fmap(fn),
|
||||||
|
};
|
||||||
|
|
||||||
let scaleYToTotal = (totalDesired, t: t): t => {
|
let scaleYToTotal = (totalDesired, t: t): t => {
|
||||||
let difference = totalDesired /. ySum(t);
|
let difference = totalDesired /. ySum(t);
|
||||||
|
@ -214,13 +220,17 @@ module Mixed = {
|
||||||
type yPdfPoint = {
|
type yPdfPoint = {
|
||||||
continuous: option(float),
|
continuous: option(float),
|
||||||
discrete: option(float),
|
discrete: option(float),
|
||||||
discreteProbabilityMassFraction: float,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let findY = (t: DistributionTypes.mixedShape, x: float): yPdfPoint => {
|
let findY = (t: DistributionTypes.mixedShape, x: float): yPdfPoint => {
|
||||||
continuous: Continuous.findY(x, t.continuous) |> E.O.some,
|
continuous:
|
||||||
discrete: Discrete.findY(x, t.discrete) |> E.O.some,
|
Continuous.findY(x, t.continuous)
|
||||||
discreteProbabilityMassFraction: t.discreteProbabilityMassFraction,
|
|> (e => e *. (1. -. t.discreteProbabilityMassFraction))
|
||||||
|
|> E.O.some,
|
||||||
|
discrete:
|
||||||
|
Discrete.findY(x, t.discrete)
|
||||||
|
|> (e => e *. t.discreteProbabilityMassFraction)
|
||||||
|
|> E.O.some,
|
||||||
};
|
};
|
||||||
|
|
||||||
let findYIntegral =
|
let findYIntegral =
|
||||||
|
@ -232,10 +242,36 @@ module Mixed = {
|
||||||
| _ => None
|
| _ => None
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let clean = (t: DistributionTypes.mixedShape) =>
|
||||||
|
switch (t) {
|
||||||
|
| {continuous: {xs: [||], ys: [||]}, discrete: {xs: [||], ys: [||]}} =>
|
||||||
|
None
|
||||||
|
| {discrete: {xs: [|_|], ys: [|_|]}} => None
|
||||||
|
| {continuous, discrete: {xs: [||], ys: [||]}} =>
|
||||||
|
Some(Continuous(continuous))
|
||||||
|
| {continuous: {xs: [||], ys: [||]}, discrete} =>
|
||||||
|
Some(Discrete(discrete))
|
||||||
|
| shape => Some(Mixed(shape))
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
module PointsType = {
|
module T = {
|
||||||
type t = DistributionTypes.pointsType;
|
type t = DistributionTypes.shape;
|
||||||
|
|
||||||
|
let mapToAll = (t: t, (fn1, fn2, fn3)) =>
|
||||||
|
switch (t) {
|
||||||
|
| Mixed(m) => fn1(m)
|
||||||
|
| Discrete(m) => fn2(m)
|
||||||
|
| Continuous(m) => fn3(m)
|
||||||
|
};
|
||||||
|
|
||||||
|
let fmap = (t: t, (fn1, fn2, fn3)) =>
|
||||||
|
switch (t) {
|
||||||
|
| Mixed(m) => Mixed(fn1(m))
|
||||||
|
| Discrete(m) => Discrete(fn2(m))
|
||||||
|
| Continuous(m) => Continuous(fn3(m))
|
||||||
|
};
|
||||||
|
|
||||||
let y = (t: t, x: float) =>
|
let y = (t: t, x: float) =>
|
||||||
switch (t) {
|
switch (t) {
|
||||||
|
@ -268,22 +304,6 @@ module PointsType = {
|
||||||
| Continuous(continuousShape) => Continuous.maxX(continuousShape)
|
| Continuous(continuousShape) => Continuous.maxX(continuousShape)
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: This is wrong. The discrete component should be made continuous when integrating.
|
|
||||||
let pdfToCdf = (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 discreteComponent = (t: t) =>
|
let discreteComponent = (t: t) =>
|
||||||
switch (t) {
|
switch (t) {
|
||||||
| Mixed({discrete}) => Some(discrete)
|
| Mixed({discrete}) => Some(discrete)
|
||||||
|
@ -319,37 +339,123 @@ module PointsType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let normalizeCdf = (t: DistributionTypes.pointsType) => {
|
let pointwiseFmap = (fn, t: t): shape =>
|
||||||
switch (t) {
|
switch (t) {
|
||||||
| Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
|
| Mixed({discrete, continuous, discreteProbabilityMassFraction}) =>
|
||||||
Mixed({
|
Mixed({
|
||||||
continuous: continuous |> Continuous.normalizeCdf,
|
continuous: XYShape.pointwiseMap(fn, continuous),
|
||||||
discrete: discrete |> Discrete.scaleYToTotal(1.0),
|
discrete: XYShape.pointwiseMap(fn, discrete),
|
||||||
discreteProbabilityMassFraction,
|
discreteProbabilityMassFraction,
|
||||||
})
|
})
|
||||||
| Discrete(d) => Discrete(d |> Discrete.scaleYToTotal(1.0))
|
| Discrete(x) => Discrete(XYShape.pointwiseMap(fn, x))
|
||||||
| Continuous(continuousShape) =>
|
| Continuous(x) => Continuous(XYShape.pointwiseMap(fn, x))
|
||||||
Continuous(Continuous.normalizeCdf(continuousShape))
|
};
|
||||||
|
|
||||||
|
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 normalizePdf = (t: DistributionTypes.pointsType) => {
|
module Pdf = {
|
||||||
switch (t) {
|
// TODO: This is wrong. The discrete component should be made continuous when integrating.
|
||||||
| Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
|
let toCdf = (t: t) =>
|
||||||
continuous
|
switch (t) {
|
||||||
|> Continuous.scalePdf(~scaleTo=1.0)
|
| Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
|
||||||
|> E.O.fmap(r =>
|
Some(
|
||||||
Mixed({
|
Mixed({
|
||||||
continuous: r,
|
continuous: Continuous.toCdf(continuous) |> E.O.toExt(""),
|
||||||
discrete: discrete |> Discrete.scaleYToTotal(1.0),
|
discrete: discrete |> Discrete.integrate,
|
||||||
discreteProbabilityMassFraction,
|
discreteProbabilityMassFraction,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
| Discrete(d) => Some(Discrete(d |> Discrete.scaleYToTotal(1.0)))
|
| Discrete(discrete) =>
|
||||||
| Continuous(continuousShape) =>
|
Some(Continuous(discrete |> Discrete.integrate))
|
||||||
continuousShape
|
| Continuous(continuous) =>
|
||||||
|> Continuous.scalePdf(~scaleTo=1.0)
|
Continuous.toCdf(continuous) |> E.O.fmap(e => Continuous(e))
|
||||||
|> E.O.fmap(r => Continuous(r))
|
};
|
||||||
|
|
||||||
|
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))
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let toPdfCdfCombo = (t: t): option(pdfCdfCombo) =>
|
||||||
|
switch (t) {
|
||||||
|
| Mixed({continuous, discrete, discreteProbabilityMassFraction} as tt) =>
|
||||||
|
Some({
|
||||||
|
cdf: continuous |> Continuous.toCdf |> E.O.toExt(""),
|
||||||
|
pdf: Mixed(tt),
|
||||||
|
})
|
||||||
|
| Discrete(d) => Some({cdf: d |> Discrete.integrate, pdf: Discrete(d)})
|
||||||
|
| Continuous(c) =>
|
||||||
|
Some({
|
||||||
|
cdf: c |> Continuous.toCdf |> E.O.toExt(""),
|
||||||
|
pdf: Continuous(c),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
};
|
};
|
5
src/core/Try24.re
Normal file
5
src/core/Try24.re
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
open DistributionTypes;
|
||||||
|
|
||||||
|
module Shappe = {
|
||||||
|
type t = shape;
|
||||||
|
};
|
|
@ -25,6 +25,7 @@ module Internals = {
|
||||||
[@bs.module "./GuesstimatorLibrary.js"]
|
[@bs.module "./GuesstimatorLibrary.js"]
|
||||||
external toCombinedFormat: (string, int) => combined = "run";
|
external toCombinedFormat: (string, int) => combined = "run";
|
||||||
|
|
||||||
|
// todo: Format to correct mass, also normalize the pdf.
|
||||||
let toMixedShape = (r: combined): option(DistributionTypes.mixedShape) => {
|
let toMixedShape = (r: combined): option(DistributionTypes.mixedShape) => {
|
||||||
let assumptions: MixedShapeBuilder.assumptions = {
|
let assumptions: MixedShapeBuilder.assumptions = {
|
||||||
continuous: ADDS_TO_1,
|
continuous: ADDS_TO_1,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user