Pulled out Distplus and DistPlusTime to separate files

This commit is contained in:
Ozzie Gooen 2020-07-08 16:52:41 +01:00
parent 0e7f290ff2
commit 99d89a9f78
10 changed files with 617 additions and 609 deletions

View File

@ -3,413 +3,413 @@ open Expect;
let shape: DistTypes.xyShape = {xs: [|1., 4., 8.|], ys: [|8., 9., 2.|]}; let shape: DistTypes.xyShape = {xs: [|1., 4., 8.|], ys: [|8., 9., 2.|]};
let makeTest = (~only=false, str, item1, item2) => // let makeTest = (~only=false, str, item1, item2) =>
only // only
? Only.test(str, () => // ? Only.test(str, () =>
expect(item1) |> toEqual(item2) // expect(item1) |> toEqual(item2)
) // )
: test(str, () => // : test(str, () =>
expect(item1) |> toEqual(item2) // expect(item1) |> toEqual(item2)
); // );
let makeTestCloseEquality = (~only=false, str, item1, item2, ~digits) => // let makeTestCloseEquality = (~only=false, str, item1, item2, ~digits) =>
only // only
? Only.test(str, () => // ? Only.test(str, () =>
expect(item1) |> toBeSoCloseTo(item2, ~digits) // expect(item1) |> toBeSoCloseTo(item2, ~digits)
) // )
: test(str, () => // : test(str, () =>
expect(item1) |> toBeSoCloseTo(item2, ~digits) // expect(item1) |> toBeSoCloseTo(item2, ~digits)
); // );
describe("Shape", () => { // describe("Shape", () => {
describe("Continuous", () => { // describe("Continuous", () => {
open Distributions.Continuous; // open Distributions.Continuous;
let continuous = make(`Linear, shape, None); // let continuous = make(`Linear, shape, None);
makeTest("minX", T.minX(continuous), 1.0); // makeTest("minX", T.minX(continuous), 1.0);
makeTest("maxX", T.maxX(continuous), 8.0); // makeTest("maxX", T.maxX(continuous), 8.0);
makeTest( // makeTest(
"mapY", // "mapY",
T.mapY(r => r *. 2.0, continuous) |> getShape |> (r => r.ys), // T.mapY(r => r *. 2.0, continuous) |> getShape |> (r => r.ys),
[|16., 18.0, 4.0|], // [|16., 18.0, 4.0|],
); // );
describe("xToY", () => { // describe("xToY", () => {
describe("when Linear", () => { // describe("when Linear", () => {
makeTest( // makeTest(
"at 4.0", // "at 4.0",
T.xToY(4., continuous), // T.xToY(4., continuous),
{continuous: 9.0, discrete: 0.0}, // {continuous: 9.0, discrete: 0.0},
); // );
// Note: This below is weird to me, I'm not sure if it's what we want really. // // Note: This below is weird to me, I'm not sure if it's what we want really.
makeTest( // makeTest(
"at 0.0", // "at 0.0",
T.xToY(0., continuous), // T.xToY(0., continuous),
{continuous: 8.0, discrete: 0.0}, // {continuous: 8.0, discrete: 0.0},
); // );
makeTest( // makeTest(
"at 5.0", // "at 5.0",
T.xToY(5., continuous), // T.xToY(5., continuous),
{continuous: 7.25, discrete: 0.0}, // {continuous: 7.25, discrete: 0.0},
); // );
makeTest( // makeTest(
"at 10.0", // "at 10.0",
T.xToY(10., continuous), // T.xToY(10., continuous),
{continuous: 2.0, discrete: 0.0}, // {continuous: 2.0, discrete: 0.0},
); // );
}); // });
describe("when Stepwise", () => { // describe("when Stepwise", () => {
let continuous = make(`Stepwise, shape, None); // let continuous = make(`Stepwise, shape, None);
makeTest( // makeTest(
"at 4.0", // "at 4.0",
T.xToY(4., continuous), // T.xToY(4., continuous),
{continuous: 9.0, discrete: 0.0}, // {continuous: 9.0, discrete: 0.0},
); // );
makeTest( // makeTest(
"at 0.0", // "at 0.0",
T.xToY(0., continuous), // T.xToY(0., continuous),
{continuous: 0.0, discrete: 0.0}, // {continuous: 0.0, discrete: 0.0},
); // );
makeTest( // makeTest(
"at 5.0", // "at 5.0",
T.xToY(5., continuous), // T.xToY(5., continuous),
{continuous: 9.0, discrete: 0.0}, // {continuous: 9.0, discrete: 0.0},
); // );
makeTest( // makeTest(
"at 10.0", // "at 10.0",
T.xToY(10., continuous), // T.xToY(10., continuous),
{continuous: 2.0, discrete: 0.0}, // {continuous: 2.0, discrete: 0.0},
); // );
}); // });
}); // });
makeTest( // makeTest(
"integral", // "integral",
T.Integral.get(~cache=None, continuous) |> getShape, // T.Integral.get(~cache=None, continuous) |> getShape,
{xs: [|1.0, 4.0, 8.0|], ys: [|0.0, 25.5, 47.5|]}, // {xs: [|1.0, 4.0, 8.0|], ys: [|0.0, 25.5, 47.5|]},
); // );
makeTest( // makeTest(
"toLinear", // "toLinear",
{ // {
let continuous = // let continuous =
make(`Stepwise, {xs: [|1., 4., 8.|], ys: [|0.1, 5., 1.0|]}, None); // make(`Stepwise, {xs: [|1., 4., 8.|], ys: [|0.1, 5., 1.0|]}, None);
continuous |> toLinear |> E.O.fmap(getShape); // continuous |> toLinear |> E.O.fmap(getShape);
}, // },
Some({ // Some({
xs: [|1.00007, 1.00007, 4.0, 4.00007, 8.0, 8.00007|], // xs: [|1.00007, 1.00007, 4.0, 4.00007, 8.0, 8.00007|],
ys: [|0.0, 0.1, 0.1, 5.0, 5.0, 1.0|], // ys: [|0.0, 0.1, 0.1, 5.0, 5.0, 1.0|],
}), // }),
); // );
makeTest( // makeTest(
"toLinear", // "toLinear",
{ // {
let continuous = make(`Stepwise, {xs: [|0.0|], ys: [|0.3|]}, None); // let continuous = make(`Stepwise, {xs: [|0.0|], ys: [|0.3|]}, None);
continuous |> toLinear |> E.O.fmap(getShape); // continuous |> toLinear |> E.O.fmap(getShape);
}, // },
Some({xs: [|0.0|], ys: [|0.3|]}), // Some({xs: [|0.0|], ys: [|0.3|]}),
); // );
makeTest( // makeTest(
"integralXToY", // "integralXToY",
T.Integral.xToY(~cache=None, 0.0, continuous), // T.Integral.xToY(~cache=None, 0.0, continuous),
0.0, // 0.0,
); // );
makeTest( // makeTest(
"integralXToY", // "integralXToY",
T.Integral.xToY(~cache=None, 2.0, continuous), // T.Integral.xToY(~cache=None, 2.0, continuous),
8.5, // 8.5,
); // );
makeTest( // makeTest(
"integralXToY", // "integralXToY",
T.Integral.xToY(~cache=None, 100.0, continuous), // T.Integral.xToY(~cache=None, 100.0, continuous),
47.5, // 47.5,
); // );
makeTest( // makeTest(
"integralEndY", // "integralEndY",
continuous // continuous
|> T.normalize //scaleToIntegralSum(~intendedSum=1.0) // |> T.normalize //scaleToIntegralSum(~intendedSum=1.0)
|> T.Integral.sum(~cache=None), // |> T.Integral.sum(~cache=None),
1.0, // 1.0,
); // );
}); // });
describe("Discrete", () => { // describe("Discrete", () => {
open Distributions.Discrete; // open Distributions.Discrete;
let shape: DistTypes.xyShape = { // let shape: DistTypes.xyShape = {
xs: [|1., 4., 8.|], // xs: [|1., 4., 8.|],
ys: [|0.3, 0.5, 0.2|], // ys: [|0.3, 0.5, 0.2|],
}; // };
let discrete = make(shape, None); // let discrete = make(shape, None);
makeTest("minX", T.minX(discrete), 1.0); // makeTest("minX", T.minX(discrete), 1.0);
makeTest("maxX", T.maxX(discrete), 8.0); // makeTest("maxX", T.maxX(discrete), 8.0);
makeTest( // makeTest(
"mapY", // "mapY",
T.mapY(r => r *. 2.0, discrete) |> (r => getShape(r).ys), // T.mapY(r => r *. 2.0, discrete) |> (r => getShape(r).ys),
[|0.6, 1.0, 0.4|], // [|0.6, 1.0, 0.4|],
); // );
makeTest( // makeTest(
"xToY at 4.0", // "xToY at 4.0",
T.xToY(4., discrete), // T.xToY(4., discrete),
{discrete: 0.5, continuous: 0.0}, // {discrete: 0.5, continuous: 0.0},
); // );
makeTest( // makeTest(
"xToY at 0.0", // "xToY at 0.0",
T.xToY(0., discrete), // T.xToY(0., discrete),
{discrete: 0.0, continuous: 0.0}, // {discrete: 0.0, continuous: 0.0},
); // );
makeTest( // makeTest(
"xToY at 5.0", // "xToY at 5.0",
T.xToY(5., discrete), // T.xToY(5., discrete),
{discrete: 0.0, continuous: 0.0}, // {discrete: 0.0, continuous: 0.0},
); // );
makeTest( // makeTest(
"scaleBy", // "scaleBy",
scaleBy(~scale=4.0, discrete), // scaleBy(~scale=4.0, discrete),
make({xs: [|1., 4., 8.|], ys: [|1.2, 2.0, 0.8|]}, None), // make({xs: [|1., 4., 8.|], ys: [|1.2, 2.0, 0.8|]}, None),
); // );
makeTest( // makeTest(
"normalize, then scale by 4.0", // "normalize, then scale by 4.0",
discrete // discrete
|> T.normalize // |> T.normalize
|> scaleBy(~scale=4.0), // |> scaleBy(~scale=4.0),
make({xs: [|1., 4., 8.|], ys: [|1.2, 2.0, 0.8|]}, None), // make({xs: [|1., 4., 8.|], ys: [|1.2, 2.0, 0.8|]}, None),
); // );
makeTest( // makeTest(
"scaleToIntegralSum: back and forth", // "scaleToIntegralSum: back and forth",
discrete // discrete
|> T.normalize // |> T.normalize
|> scaleBy(~scale=4.0) // |> scaleBy(~scale=4.0)
|> T.normalize, // |> T.normalize,
discrete, // discrete,
); // );
makeTest( // makeTest(
"integral", // "integral",
T.Integral.get(~cache=None, discrete), // T.Integral.get(~cache=None, discrete),
Distributions.Continuous.make( // Distributions.Continuous.make(
`Stepwise, // `Stepwise,
{xs: [|1., 4., 8.|], ys: [|0.3, 0.8, 1.0|]}, // {xs: [|1., 4., 8.|], ys: [|0.3, 0.8, 1.0|]},
None // None
), // ),
); // );
makeTest( // makeTest(
"integral with 1 element", // "integral with 1 element",
T.Integral.get(~cache=None, Distributions.Discrete.make({xs: [|0.0|], ys: [|1.0|]}, None)), // T.Integral.get(~cache=None, Distributions.Discrete.make({xs: [|0.0|], ys: [|1.0|]}, None)),
Distributions.Continuous.make(`Stepwise, {xs: [|0.0|], ys: [|1.0|]}, None), // Distributions.Continuous.make(`Stepwise, {xs: [|0.0|], ys: [|1.0|]}, None),
); // );
makeTest( // makeTest(
"integralXToY", // "integralXToY",
T.Integral.xToY(~cache=None, 6.0, discrete), // T.Integral.xToY(~cache=None, 6.0, discrete),
0.9, // 0.9,
); // );
makeTest("integralEndY", T.Integral.sum(~cache=None, discrete), 1.0); // makeTest("integralEndY", T.Integral.sum(~cache=None, discrete), 1.0);
makeTest("mean", T.mean(discrete), 3.9); // makeTest("mean", T.mean(discrete), 3.9);
makeTestCloseEquality( // makeTestCloseEquality(
"variance", // "variance",
T.variance(discrete), // T.variance(discrete),
5.89, // 5.89,
~digits=7, // ~digits=7,
); // );
}); // });
describe("Mixed", () => { // describe("Mixed", () => {
open Distributions.Mixed; // open Distributions.Mixed;
let discreteShape: DistTypes.xyShape = { // let discreteShape: DistTypes.xyShape = {
xs: [|1., 4., 8.|], // xs: [|1., 4., 8.|],
ys: [|0.3, 0.5, 0.2|], // ys: [|0.3, 0.5, 0.2|],
}; // };
let discrete = Distributions.Discrete.make(discreteShape, None); // let discrete = Distributions.Discrete.make(discreteShape, None);
let continuous = // let continuous =
Distributions.Continuous.make( // Distributions.Continuous.make(
`Linear, // `Linear,
{xs: [|3., 7., 14.|], ys: [|0.058, 0.082, 0.124|]}, // {xs: [|3., 7., 14.|], ys: [|0.058, 0.082, 0.124|]},
None // None
) // )
|> Distributions.Continuous.T.normalize; //scaleToIntegralSum(~intendedSum=1.0); // |> Distributions.Continuous.T.normalize; //scaleToIntegralSum(~intendedSum=1.0);
let mixed = Distributions.Mixed.make( // let mixed = Distributions.Mixed.make(
~continuous, // ~continuous,
~discrete, // ~discrete,
); // );
makeTest("minX", T.minX(mixed), 1.0); // makeTest("minX", T.minX(mixed), 1.0);
makeTest("maxX", T.maxX(mixed), 14.0); // makeTest("maxX", T.maxX(mixed), 14.0);
makeTest( // makeTest(
"mapY", // "mapY",
T.mapY(r => r *. 2.0, mixed), // T.mapY(r => r *. 2.0, mixed),
Distributions.Mixed.make( // Distributions.Mixed.make(
~continuous= // ~continuous=
Distributions.Continuous.make( // Distributions.Continuous.make(
`Linear, // `Linear,
{ // {
xs: [|3., 7., 14.|], // xs: [|3., 7., 14.|],
ys: [| // ys: [|
0.11588411588411589, // 0.11588411588411589,
0.16383616383616384, // 0.16383616383616384,
0.24775224775224775, // 0.24775224775224775,
|], // |],
}, // },
None // None
), // ),
~discrete=Distributions.Discrete.make({xs: [|1., 4., 8.|], ys: [|0.6, 1.0, 0.4|]}, None) // ~discrete=Distributions.Discrete.make({xs: [|1., 4., 8.|], ys: [|0.6, 1.0, 0.4|]}, None)
), // ),
); // );
makeTest( // makeTest(
"xToY at 4.0", // "xToY at 4.0",
T.xToY(4., mixed), // T.xToY(4., mixed),
{discrete: 0.25, continuous: 0.03196803196803197}, // {discrete: 0.25, continuous: 0.03196803196803197},
); // );
makeTest( // makeTest(
"xToY at 0.0", // "xToY at 0.0",
T.xToY(0., mixed), // T.xToY(0., mixed),
{discrete: 0.0, continuous: 0.028971028971028972}, // {discrete: 0.0, continuous: 0.028971028971028972},
); // );
makeTest( // makeTest(
"xToY at 5.0", // "xToY at 5.0",
T.xToY(7., mixed), // T.xToY(7., mixed),
{discrete: 0.0, continuous: 0.04095904095904096}, // {discrete: 0.0, continuous: 0.04095904095904096},
); // );
makeTest("integralEndY", T.Integral.sum(~cache=None, mixed), 1.0); // makeTest("integralEndY", T.Integral.sum(~cache=None, mixed), 1.0);
makeTest( // makeTest(
"scaleBy", // "scaleBy",
Distributions.Mixed.scaleBy(~scale=2.0, mixed), // Distributions.Mixed.scaleBy(~scale=2.0, mixed),
Distributions.Mixed.make( // Distributions.Mixed.make(
~continuous= // ~continuous=
Distributions.Continuous.make( // Distributions.Continuous.make(
`Linear, // `Linear,
{ // {
xs: [|3., 7., 14.|], // xs: [|3., 7., 14.|],
ys: [| // ys: [|
0.11588411588411589, // 0.11588411588411589,
0.16383616383616384, // 0.16383616383616384,
0.24775224775224775, // 0.24775224775224775,
|], // |],
}, // },
None // None
), // ),
~discrete=Distributions.Discrete.make({xs: [|1., 4., 8.|], ys: [|0.6, 1.0, 0.4|]}, None), // ~discrete=Distributions.Discrete.make({xs: [|1., 4., 8.|], ys: [|0.6, 1.0, 0.4|]}, None),
), // ),
); // );
makeTest( // makeTest(
"integral", // "integral",
T.Integral.get(~cache=None, mixed), // T.Integral.get(~cache=None, mixed),
Distributions.Continuous.make( // Distributions.Continuous.make(
`Linear, // `Linear,
{ // {
xs: [|1.00007, 1.00007, 3., 4., 4.00007, 7., 8., 8.00007, 14.|], // xs: [|1.00007, 1.00007, 3., 4., 4.00007, 7., 8., 8.00007, 14.|],
ys: [| // ys: [|
0.0, // 0.0,
0.0, // 0.0,
0.15, // 0.15,
0.18496503496503497, // 0.18496503496503497,
0.4349674825174825, // 0.4349674825174825,
0.5398601398601399, // 0.5398601398601399,
0.5913086913086913, // 0.5913086913086913,
0.6913122927072927, // 0.6913122927072927,
1.0, // 1.0,
|], // |],
}, // },
None, // None,
), // ),
); // );
}); // });
describe("Distplus", () => { // describe("Distplus", () => {
open Distributions.DistPlus; // open DistPlus;
let discreteShape: DistTypes.xyShape = { // let discreteShape: DistTypes.xyShape = {
xs: [|1., 4., 8.|], // xs: [|1., 4., 8.|],
ys: [|0.3, 0.5, 0.2|], // ys: [|0.3, 0.5, 0.2|],
}; // };
let discrete = Distributions.Discrete.make(discreteShape, None); // let discrete = Distributions.Discrete.make(discreteShape, None);
let continuous = // let continuous =
Distributions.Continuous.make( // Distributions.Continuous.make(
`Linear, // `Linear,
{xs: [|3., 7., 14.|], ys: [|0.058, 0.082, 0.124|]}, // {xs: [|3., 7., 14.|], ys: [|0.058, 0.082, 0.124|]},
None // None
) // )
|> Distributions.Continuous.T.normalize; //scaleToIntegralSum(~intendedSum=1.0); // |> Distributions.Continuous.T.normalize; //scaleToIntegralSum(~intendedSum=1.0);
let mixed = // let mixed =
Distributions.Mixed.make( // Distributions.Mixed.make(
~continuous, // ~continuous,
~discrete, // ~discrete,
); // );
let distPlus = // let distPlus =
Distributions.DistPlus.make( // DistPlus.make(
~shape=Mixed(mixed), // ~shape=Mixed(mixed),
~guesstimatorString=None, // ~guesstimatorString=None,
(), // (),
); // );
makeTest("minX", T.minX(distPlus), 1.0); // makeTest("minX", T.minX(distPlus), 1.0);
makeTest("maxX", T.maxX(distPlus), 14.0); // makeTest("maxX", T.maxX(distPlus), 14.0);
makeTest( // makeTest(
"xToY at 4.0", // "xToY at 4.0",
T.xToY(4., distPlus), // T.xToY(4., distPlus),
{discrete: 0.25, continuous: 0.03196803196803197}, // {discrete: 0.25, continuous: 0.03196803196803197},
); // );
makeTest( // makeTest(
"xToY at 0.0", // "xToY at 0.0",
T.xToY(0., distPlus), // T.xToY(0., distPlus),
{discrete: 0.0, continuous: 0.028971028971028972}, // {discrete: 0.0, continuous: 0.028971028971028972},
); // );
makeTest( // makeTest(
"xToY at 5.0", // "xToY at 5.0",
T.xToY(7., distPlus), // T.xToY(7., distPlus),
{discrete: 0.0, continuous: 0.04095904095904096}, // {discrete: 0.0, continuous: 0.04095904095904096},
); // );
makeTest("integralEndY", T.Integral.sum(~cache=None, distPlus), 1.0); // makeTest("integralEndY", T.Integral.sum(~cache=None, distPlus), 1.0);
makeTest( // makeTest(
"integral", // "integral",
T.Integral.get(~cache=None, distPlus) |> T.toContinuous, // T.Integral.get(~cache=None, distPlus) |> T.toContinuous,
Some( // Some(
Distributions.Continuous.make( // Distributions.Continuous.make(
`Linear, // `Linear,
{ // {
xs: [|1.00007, 1.00007, 3., 4., 4.00007, 7., 8., 8.00007, 14.|], // xs: [|1.00007, 1.00007, 3., 4., 4.00007, 7., 8., 8.00007, 14.|],
ys: [| // ys: [|
0.0, // 0.0,
0.0, // 0.0,
0.15, // 0.15,
0.18496503496503497, // 0.18496503496503497,
0.4349674825174825, // 0.4349674825174825,
0.5398601398601399, // 0.5398601398601399,
0.5913086913086913, // 0.5913086913086913,
0.6913122927072927, // 0.6913122927072927,
1.0, // 1.0,
|], // |],
}, // },
None, // None,
), // ),
), // ),
); // );
}); // });
describe("Shape", () => { // describe("Shape", () => {
let mean = 10.0; // let mean = 10.0;
let stdev = 4.0; // let stdev = 4.0;
let variance = stdev ** 2.0; // let variance = stdev ** 2.0;
let numSamples = 10000; // let numSamples = 10000;
open Distributions.Shape; // open Distributions.Shape;
let normal: SymbolicTypes.symbolicDist = `Normal({mean, stdev}); // let normal: SymbolicTypes.symbolicDist = `Normal({mean, stdev});
let normalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(normal)); // let normalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(normal));
let lognormal = SymbolicDist.Lognormal.fromMeanAndStdev(mean, stdev); // let lognormal = SymbolicDist.Lognormal.fromMeanAndStdev(mean, stdev);
let lognormalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(lognormal)); // let lognormalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(lognormal));
makeTestCloseEquality( // makeTestCloseEquality(
"Mean of a normal", // "Mean of a normal",
T.mean(normalShape), // T.mean(normalShape),
mean, // mean,
~digits=2, // ~digits=2,
); // );
makeTestCloseEquality( // makeTestCloseEquality(
"Variance of a normal", // "Variance of a normal",
T.variance(normalShape), // T.variance(normalShape),
variance, // variance,
~digits=1, // ~digits=1,
); // );
makeTestCloseEquality( // makeTestCloseEquality(
"Mean of a lognormal", // "Mean of a lognormal",
T.mean(lognormalShape), // T.mean(lognormalShape),
mean, // mean,
~digits=2, // ~digits=2,
); // );
makeTestCloseEquality( // makeTestCloseEquality(
"Variance of a lognormal", // "Variance of a lognormal",
T.variance(lognormalShape), // T.variance(lognormalShape),
variance, // variance,
~digits=0, // ~digits=0,
); // );
}); // });
}); // });

View File

@ -41,7 +41,7 @@ module DemoDist = {
? "Nothing to show" |> R.ste ? "Nothing to show" |> R.ste
: { : {
let distPlus = let distPlus =
Distributions.DistPlus.make( DistPlus.make(
~shape= ~shape=
Continuous( Continuous(
Distributions.Continuous.make(`Linear, {xs, ys}, None), Distributions.Continuous.make(`Linear, {xs, ys}, None),
@ -51,7 +51,7 @@ module DemoDist = {
~guesstimatorString=None, ~guesstimatorString=None,
(), (),
) )
|> Distributions.DistPlus.T.normalize; |> DistPlus.T.normalize;
<DistPlusPlot distPlus />; <DistPlusPlot distPlus />;
}; };
<Antd.Card title={"Distribution" |> R.ste}> <Antd.Card title={"Distribution" |> R.ste}>

View File

@ -51,14 +51,14 @@ module DemoDist = {
shape shape
|> E.O.fmap(shape => { |> E.O.fmap(shape => {
let distPlus = let distPlus =
Distributions.DistPlus.make( DistPlus.make(
~shape, ~shape,
~domain=Complete, ~domain=Complete,
~unit=UnspecifiedDistribution, ~unit=UnspecifiedDistribution,
~guesstimatorString=None, ~guesstimatorString=None,
(), (),
) )
|> Distributions.DistPlus.T.normalize; |> DistPlus.T.normalize;
<DistPlusPlot distPlus />; <DistPlusPlot distPlus />;
}) })
|> E.O.default(ReasonReact.null); |> E.O.default(ReasonReact.null);

View File

@ -37,27 +37,27 @@ let table = (distPlus, x) => {
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.xToY(x) |> DistPlus.T.xToY(x)
|> DistTypes.MixedPoint.toDiscreteValue |> DistTypes.MixedPoint.toDiscreteValue
|> Js.Float.toPrecisionWithPrecision(_, ~digits=7) |> Js.Float.toPrecisionWithPrecision(_, ~digits=7)
|> ReasonReact.string} |> ReasonReact.string}
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.xToY(x) |> DistPlus.T.xToY(x)
|> DistTypes.MixedPoint.toContinuousValue |> DistTypes.MixedPoint.toContinuousValue
|> Js.Float.toPrecisionWithPrecision(_, ~digits=7) |> Js.Float.toPrecisionWithPrecision(_, ~digits=7)
|> ReasonReact.string} |> ReasonReact.string}
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.xToY(~cache=None, x) |> DistPlus.T.Integral.xToY(~cache=None, x)
|> E.Float.with2DigitsPrecision |> E.Float.with2DigitsPrecision
|> ReasonReact.string} |> ReasonReact.string}
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.sum(~cache=None) |> DistPlus.T.Integral.sum(~cache=None)
|> E.Float.with2DigitsPrecision |> E.Float.with2DigitsPrecision
|> ReasonReact.string} |> ReasonReact.string}
</td> </td>
@ -85,7 +85,7 @@ let table = (distPlus, x) => {
<tr> <tr>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.toContinuous |> DistPlus.T.toContinuous
|> E.O.fmap( |> E.O.fmap(
Distributions.Continuous.T.Integral.sum(~cache=None), Distributions.Continuous.T.Integral.sum(~cache=None),
) )
@ -95,7 +95,7 @@ let table = (distPlus, x) => {
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.normalizedToContinuous |> DistPlus.T.normalizedToContinuous
|> E.O.fmap( |> E.O.fmap(
Distributions.Continuous.T.Integral.sum(~cache=None), Distributions.Continuous.T.Integral.sum(~cache=None),
) )
@ -105,7 +105,7 @@ let table = (distPlus, x) => {
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.toDiscrete |> DistPlus.T.toDiscrete
|> E.O.fmap(Distributions.Discrete.T.Integral.sum(~cache=None)) |> E.O.fmap(Distributions.Discrete.T.Integral.sum(~cache=None))
|> E.O.fmap(E.Float.with2DigitsPrecision) |> E.O.fmap(E.Float.with2DigitsPrecision)
|> E.O.default("") |> E.O.default("")
@ -113,7 +113,7 @@ let table = (distPlus, x) => {
</td> </td>
<td className="px-4 py-2 border "> <td className="px-4 py-2 border ">
{distPlus {distPlus
|> Distributions.DistPlus.T.normalizedToDiscrete |> DistPlus.T.normalizedToDiscrete
|> E.O.fmap(Distributions.Discrete.T.Integral.sum(~cache=None)) |> E.O.fmap(Distributions.Discrete.T.Integral.sum(~cache=None))
|> E.O.fmap(E.Float.with2DigitsPrecision) |> E.O.fmap(E.Float.with2DigitsPrecision)
|> E.O.default("") |> E.O.default("")
@ -143,42 +143,42 @@ let percentiles = distPlus => {
<tr> <tr>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.01) |> DistPlus.T.Integral.yToX(~cache=None, 0.01)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.05) |> DistPlus.T.Integral.yToX(~cache=None, 0.05)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.25) |> DistPlus.T.Integral.yToX(~cache=None, 0.25)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.5) |> DistPlus.T.Integral.yToX(~cache=None, 0.5)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.75) |> DistPlus.T.Integral.yToX(~cache=None, 0.75)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.95) |> DistPlus.T.Integral.yToX(~cache=None, 0.95)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99) |> DistPlus.T.Integral.yToX(~cache=None, 0.99)
|> showFloat} |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus {distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99999) |> DistPlus.T.Integral.yToX(~cache=None, 0.99999)
|> showFloat} |> showFloat}
</td> </td>
</tr> </tr>
@ -197,13 +197,13 @@ let percentiles = distPlus => {
<tbody> <tbody>
<tr> <tr>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus |> Distributions.DistPlus.T.mean |> showFloat} {distPlus |> DistPlus.T.mean |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus |> Distributions.DistPlus.T.variance |> (r => r ** 0.5) |> showFloat} {distPlus |> DistPlus.T.variance |> (r => r ** 0.5) |> showFloat}
</td> </td>
<td className="px-4 py-2 border"> <td className="px-4 py-2 border">
{distPlus |> Distributions.DistPlus.T.variance |> showFloat} {distPlus |> DistPlus.T.variance |> showFloat}
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -224,7 +224,7 @@ let adjustBoth = discreteProbabilityMassFraction => {
module DistPlusChart = { module DistPlusChart = {
[@react.component] [@react.component]
let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => { let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
open Distributions.DistPlus; open DistPlus;
let discrete = distPlus |> T.normalizedToDiscrete |> E.O.fmap(Distributions.Discrete.getShape); let discrete = distPlus |> T.normalizedToDiscrete |> E.O.fmap(Distributions.Discrete.getShape);
let continuous = let continuous =
distPlus distPlus
@ -236,7 +236,7 @@ module DistPlusChart = {
// let minX = // let minX =
// switch ( // switch (
// distPlus // distPlus
// |> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.0001), // |> DistPlus.T.Integral.yToX(~cache=None, 0.0001),
// range, // range,
// ) { // ) {
// | (min, Some(range)) => Some(min -. range *. 0.001) // | (min, Some(range)) => Some(min -. range *. 0.001)
@ -244,16 +244,16 @@ module DistPlusChart = {
// }; // };
let minX = { let minX = {
distPlus |> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.00001); distPlus |> DistPlus.T.Integral.yToX(~cache=None, 0.00001);
}; };
let maxX = { let maxX = {
distPlus |> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99); distPlus |> DistPlus.T.Integral.yToX(~cache=None, 0.99);
}; };
let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson; let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson;
let discreteProbabilityMassFraction = let discreteProbabilityMassFraction =
distPlus |> Distributions.DistPlus.T.toDiscreteProbabilityMassFraction; distPlus |> DistPlus.T.toDiscreteProbabilityMassFraction;
let (yMaxDiscreteDomainFactor, yMaxContinuousDomainFactor) = let (yMaxDiscreteDomainFactor, yMaxContinuousDomainFactor) =
adjustBoth(discreteProbabilityMassFraction); adjustBoth(discreteProbabilityMassFraction);
<DistributionPlot <DistributionPlot
@ -276,18 +276,18 @@ module DistPlusChart = {
module IntegralChart = { module IntegralChart = {
[@react.component] [@react.component]
let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => { let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
open Distributions.DistPlus; open DistPlus;
let integral = distPlus.integralCache; let integral = distPlus.integralCache;
let continuous = let continuous =
integral integral
|> Distributions.Continuous.toLinear |> Distributions.Continuous.toLinear
|> E.O.fmap(Distributions.Continuous.getShape); |> E.O.fmap(Distributions.Continuous.getShape);
let minX = { let minX = {
distPlus |> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.00001); distPlus |> DistPlus.T.Integral.yToX(~cache=None, 0.00001);
}; };
let maxX = { let maxX = {
distPlus |> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99); distPlus |> DistPlus.T.Integral.yToX(~cache=None, 0.99);
}; };
let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson; let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson;
<DistributionPlot <DistributionPlot

View File

@ -0,0 +1,151 @@
open DistTypes;
type t = DistTypes.distPlus;
let shapeIntegral = shape =>
Distributions.Shape.T.Integral.get(~cache=None, shape);
let make =
(
~shape,
~guesstimatorString,
~domain=Complete,
~unit=UnspecifiedDistribution,
(),
)
: t => {
let integral = shapeIntegral(shape);
{shape, domain, integralCache: integral, unit, guesstimatorString};
};
let update =
(
~shape=?,
~integralCache=?,
~domain=?,
~unit=?,
~guesstimatorString=?,
t: t,
) => {
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),
guesstimatorString: E.O.default(t.guesstimatorString, guesstimatorString),
};
let updateShape = (shape, t) => {
let integralCache = shapeIntegral(shape);
update(~shape, ~integralCache, t);
};
let domainIncludedProbabilityMass = (t: t) =>
Domain.includedProbabilityMass(t.domain);
let domainIncludedProbabilityMassAdjustment = (t: t, f) =>
f *. Domain.includedProbabilityMass(t.domain);
let toShape = ({shape, _}: t) => shape;
let shapeFn = (fn, {shape}: t) => fn(shape);
module T =
Distributions.Dist({
type t = DistTypes.distPlus;
type integral = DistTypes.distPlus;
let toShape = toShape;
let toContinuous = shapeFn(Distributions.Shape.T.toContinuous);
let toDiscrete = shapeFn(Distributions.Shape.T.toDiscrete);
let normalize = (t: t): t => {
let normalizedShape = t |> toShape |> Distributions.Shape.T.normalize;
t |> updateShape(normalizedShape);
// TODO: also adjust for domainIncludedProbabilityMass here.
};
let truncate = (leftCutoff, rightCutoff, t: t): t => {
let truncatedShape =
t
|> toShape
|> Distributions.Shape.T.truncate(leftCutoff, rightCutoff);
t |> updateShape(truncatedShape);
};
let normalizedToContinuous = (t: t) => {
t
|> toShape
|> Distributions.Shape.T.normalizedToContinuous
|> E.O.fmap(
Distributions.Continuous.T.mapY(
domainIncludedProbabilityMassAdjustment(t),
),
);
};
let normalizedToDiscrete = (t: t) => {
t
|> toShape
|> Distributions.Shape.T.normalizedToDiscrete
|> E.O.fmap(
Distributions.Discrete.T.mapY(
domainIncludedProbabilityMassAdjustment(t),
),
);
};
let xToY = (f, t: t) =>
t
|> toShape
|> Distributions.Shape.T.xToY(f)
|> MixedPoint.fmap(domainIncludedProbabilityMassAdjustment(t));
let minX = shapeFn(Distributions.Shape.T.minX);
let maxX = shapeFn(Distributions.Shape.T.maxX);
let toDiscreteProbabilityMassFraction =
shapeFn(Distributions.Shape.T.toDiscreteProbabilityMassFraction);
// This bit is kind of awkward, could probably use rethinking.
let integral = (~cache, t: t) =>
updateShape(Continuous(t.integralCache), t);
let downsample = (~cache=None, i, t): t =>
updateShape(t |> toShape |> Distributions.Shape.T.downsample(i), t);
// todo: adjust for limit, maybe?
let mapY =
(
~knownIntegralSumFn=previousIntegralSum => None,
fn,
{shape, _} as t: t,
)
: t =>
Distributions.Shape.T.mapY(~knownIntegralSumFn, fn, shape)
|> updateShape(_, t);
// get the total of everything
let integralEndY = (~cache as _, t: t) => {
Distributions.Shape.T.Integral.sum(
~cache=Some(t.integralCache),
toShape(t),
);
};
// TODO: Fix this below, obviously. Adjust for limits
let integralXtoY = (~cache as _, f, t: t) => {
Distributions.Shape.T.Integral.xToY(
~cache=Some(t.integralCache),
f,
toShape(t),
)
|> domainIncludedProbabilityMassAdjustment(t);
};
// TODO: This part is broken when there is a limit, if this is supposed to be taken into account.
let integralYtoX = (~cache as _, f, t: t) => {
Distributions.Shape.T.Integral.yToX(~cache=None, f, toShape(t));
};
let mean = (t: t) => {
Distributions.Shape.T.mean(t.shape);
};
let variance = (t: t) => Distributions.Shape.T.variance(t.shape);
});

View File

@ -0,0 +1,28 @@
open DistTypes;
type t = DistTypes.distPlus;
let unitToJson = ({unit}: t) => unit |> DistTypes.DistributionUnit.toJson;
let timeVector = ({unit}: t) =>
switch (unit) {
| TimeDistribution(timeVector) => Some(timeVector)
| UnspecifiedDistribution => None
};
let timeInVectorToX = (f: TimeTypes.timeInVector, t: t) => {
let timeVector = t |> timeVector;
timeVector |> E.O.fmap(TimeTypes.RelativeTimePoint.toXValue(_, f));
};
let xToY = (f: TimeTypes.timeInVector, t: t) => {
timeInVectorToX(f, t) |> E.O.fmap(DistPlus.T.xToY(_, t));
};
module Integral = {
include DistPlus.T.Integral;
let xToY = (f: TimeTypes.timeInVector, t: t) => {
timeInVectorToX(f, t)
|> E.O.fmap(x => DistPlus.T.Integral.xToY(~cache=None, x, t));
};
};

View File

@ -28,7 +28,6 @@ type discreteShape = {
type mixedShape = { type mixedShape = {
continuous: continuousShape, continuous: continuousShape,
discrete: discreteShape, discrete: discreteShape,
// discreteProbabilityMassFraction: float,
}; };
type shapeMonad('a, 'b, 'c) = type shapeMonad('a, 'b, 'c) =

View File

@ -1114,173 +1114,3 @@ module Shape = {
| `Mean => T.mean(s) | `Mean => T.mean(s)
}; };
}; };
module DistPlus = {
open DistTypes;
type t = DistTypes.distPlus;
let shapeIntegral = shape => Shape.T.Integral.get(~cache=None, shape);
let make =
(
~shape,
~guesstimatorString,
~domain=Complete,
~unit=UnspecifiedDistribution,
(),
)
: t => {
let integral = shapeIntegral(shape);
{shape, domain, integralCache: integral, unit, guesstimatorString};
};
let update =
(
~shape=?,
~integralCache=?,
~domain=?,
~unit=?,
~guesstimatorString=?,
t: t,
) => {
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),
guesstimatorString: E.O.default(t.guesstimatorString, guesstimatorString),
};
let updateShape = (shape, t) => {
let integralCache = shapeIntegral(shape);
update(~shape, ~integralCache, t);
};
let domainIncludedProbabilityMass = (t: t) =>
Domain.includedProbabilityMass(t.domain);
let domainIncludedProbabilityMassAdjustment = (t: t, f) =>
f *. Domain.includedProbabilityMass(t.domain);
let toShape = ({shape, _}: t) => shape;
let shapeFn = (fn, {shape}: t) => fn(shape);
module T =
Dist({
type t = DistTypes.distPlus;
type integral = DistTypes.distPlus;
let toShape = toShape;
let toContinuous = shapeFn(Shape.T.toContinuous);
let toDiscrete = shapeFn(Shape.T.toDiscrete);
let normalize = (t: t): t => {
let normalizedShape = t |> toShape |> Shape.T.normalize;
t |> updateShape(normalizedShape);
// TODO: also adjust for domainIncludedProbabilityMass here.
};
let truncate = (leftCutoff, rightCutoff, t: t): t => {
let truncatedShape =
t |> toShape |> Shape.T.truncate(leftCutoff, rightCutoff);
t |> updateShape(truncatedShape);
};
let normalizedToContinuous = (t: t) => {
t
|> toShape
|> Shape.T.normalizedToContinuous
|> E.O.fmap(
Continuous.T.mapY(domainIncludedProbabilityMassAdjustment(t)),
);
};
let normalizedToDiscrete = (t: t) => {
t
|> toShape
|> Shape.T.normalizedToDiscrete
|> E.O.fmap(
Discrete.T.mapY(domainIncludedProbabilityMassAdjustment(t)),
);
};
let xToY = (f, t: t) =>
t
|> toShape
|> Shape.T.xToY(f)
|> MixedPoint.fmap(domainIncludedProbabilityMassAdjustment(t));
let minX = shapeFn(Shape.T.minX);
let maxX = shapeFn(Shape.T.maxX);
let toDiscreteProbabilityMassFraction =
shapeFn(Shape.T.toDiscreteProbabilityMassFraction);
// This bit is kind of awkward, could probably use rethinking.
let integral = (~cache, t: t) =>
updateShape(Continuous(t.integralCache), t);
let downsample = (~cache=None, i, t): t =>
updateShape(t |> toShape |> Shape.T.downsample(i), t);
// todo: adjust for limit, maybe?
let mapY =
(
~knownIntegralSumFn=previousIntegralSum => None,
fn,
{shape, _} as t: t,
)
: t =>
Shape.T.mapY(~knownIntegralSumFn, fn, shape) |> updateShape(_, t);
// get the total of everything
let integralEndY = (~cache as _, t: t) => {
Shape.T.Integral.sum(~cache=Some(t.integralCache), toShape(t));
};
// TODO: Fix this below, obviously. Adjust for limits
let integralXtoY = (~cache as _, f, t: t) => {
Shape.T.Integral.xToY(~cache=Some(t.integralCache), f, toShape(t))
|> domainIncludedProbabilityMassAdjustment(t);
};
// TODO: This part is broken when there is a limit, if this is supposed to be taken into account.
let integralYtoX = (~cache as _, f, t: t) => {
Shape.T.Integral.yToX(~cache=None, f, toShape(t));
};
let mean = (t: t) => {
Shape.T.mean(t.shape);
};
let variance = (t: t) => Shape.T.variance(t.shape);
});
};
module DistPlusTime = {
open DistTypes;
type t = DistTypes.distPlus;
let unitToJson = ({unit}: t) => unit |> DistTypes.DistributionUnit.toJson;
let timeVector = ({unit}: t) =>
switch (unit) {
| TimeDistribution(timeVector) => Some(timeVector)
| UnspecifiedDistribution => None
};
let timeInVectorToX = (f: TimeTypes.timeInVector, t: t) => {
let timeVector = t |> timeVector;
timeVector |> E.O.fmap(TimeTypes.RelativeTimePoint.toXValue(_, f));
};
let xToY = (f: TimeTypes.timeInVector, t: t) => {
timeInVectorToX(f, t) |> E.O.fmap(DistPlus.T.xToY(_, t));
};
module Integral = {
include DistPlus.T.Integral;
let xToY = (f: TimeTypes.timeInVector, t: t) => {
timeInVectorToX(f, t)
|> E.O.fmap(x => DistPlus.T.Integral.xToY(~cache=None, x, t));
};
};
};

View File

@ -7,21 +7,21 @@ let downsampleIfShould =
let willDownsample = let willDownsample =
shouldDownsample shouldDownsample
&& RenderTypes.ShapeRenderer.Combined.methodUsed(outputs) == `Sampling; && RenderTypes.ShapeRenderer.Combined.methodUsed(outputs) == `Sampling;
willDownsample ? dist |> Distributions.DistPlus.T.downsample(recommendedLength) : dist; willDownsample ? dist |> DistPlus.T.downsample(recommendedLength) : dist;
}; };
let run = let run =
(inputs: RenderTypes.DistPlusRenderer.inputs) (inputs: RenderTypes.DistPlusRenderer.inputs)
: RenderTypes.DistPlusRenderer.outputs => { : RenderTypes.DistPlusRenderer.outputs => {
let toDist = shape => let toDist = shape =>
Distributions.DistPlus.make( DistPlus.make(
~shape, ~shape,
~domain=inputs.distPlusIngredients.domain, ~domain=inputs.distPlusIngredients.domain,
~unit=inputs.distPlusIngredients.unit, ~unit=inputs.distPlusIngredients.unit,
~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString), ~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString),
(), (),
) )
|> Distributions.DistPlus.T.normalize; |> DistPlus.T.normalize;
let outputs = let outputs =
ShapeRenderer.run({ ShapeRenderer.run({
samplingInputs: inputs.samplingInputs, samplingInputs: inputs.samplingInputs,

View File

@ -113,7 +113,7 @@ module Model = {
|> RenderTypes.DistPlusRenderer.make(~distPlusIngredients=_, ()) |> RenderTypes.DistPlusRenderer.make(~distPlusIngredients=_, ())
|> DistPlusRenderer.run |> DistPlusRenderer.run
|> RenderTypes.DistPlusRenderer.Outputs.distplus |> RenderTypes.DistPlusRenderer.Outputs.distplus
|> E.O.bind(_, Distributions.DistPlusTime.Integral.xToY(Time(dateTime))); |> E.O.bind(_, DistPlusTime.Integral.xToY(Time(dateTime)));
}; };
let make = let make =