Desparately trying to work for many conditions
This commit is contained in:
parent
3182067a48
commit
8c625a6803
|
@ -3,10 +3,14 @@ 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 = (str, item1, item2) =>
|
let makeTest = (~only=false, str, item1, item2) =>
|
||||||
test(str, () =>
|
only
|
||||||
expect(item1) |> toEqual(item2)
|
? Only.test(str, () =>
|
||||||
);
|
expect(item1) |> toEqual(item2)
|
||||||
|
)
|
||||||
|
: test(str, () =>
|
||||||
|
expect(item1) |> toEqual(item2)
|
||||||
|
);
|
||||||
|
|
||||||
describe("Shape", () => {
|
describe("Shape", () => {
|
||||||
describe("Continuous", () => {
|
describe("Continuous", () => {
|
||||||
|
@ -77,12 +81,20 @@ describe("Shape", () => {
|
||||||
{
|
{
|
||||||
let continuous =
|
let continuous =
|
||||||
make({xs: [|1., 4., 8.|], ys: [|0.1, 5., 1.0|]}, `Stepwise);
|
make({xs: [|1., 4., 8.|], ys: [|0.1, 5., 1.0|]}, `Stepwise);
|
||||||
continuous |> toLinear |> getShape;
|
continuous |> toLinear |> E.O.fmap(getShape);
|
||||||
},
|
},
|
||||||
|
Some({
|
||||||
|
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|],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
makeTest(
|
||||||
|
"toLinear",
|
||||||
{
|
{
|
||||||
xs: [|1.00007, 4.0, 4.00007, 8.0, 8.00007|],
|
let continuous = make({xs: [|0.0|], ys: [|0.3|]}, `Stepwise);
|
||||||
ys: [|0.1, 0.1, 5.0, 5.0, 1.0|],
|
continuous |> toLinear |> E.O.fmap(getShape);
|
||||||
},
|
},
|
||||||
|
Some({xs: [|0.0|], ys: [|0.3|]}),
|
||||||
);
|
);
|
||||||
makeTest(
|
makeTest(
|
||||||
"integralXToY",
|
"integralXToY",
|
||||||
|
@ -99,7 +111,13 @@ describe("Shape", () => {
|
||||||
T.Integral.xToY(~cache=None, 100.0, continuous),
|
T.Integral.xToY(~cache=None, 100.0, continuous),
|
||||||
47.5,
|
47.5,
|
||||||
);
|
);
|
||||||
makeTest("integralSum", T.Integral.sum(~cache=None, continuous), 47.5);
|
makeTest(
|
||||||
|
"integralEndY",
|
||||||
|
continuous
|
||||||
|
|> T.scaleToIntegralSum(~intendedSum=1.0)
|
||||||
|
|> T.Integral.sum(~cache=None),
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Discrete", () => {
|
describe("Discrete", () => {
|
||||||
|
@ -166,7 +184,7 @@ describe("Shape", () => {
|
||||||
T.Integral.xToY(~cache=None, 6.0, discrete),
|
T.Integral.xToY(~cache=None, 6.0, discrete),
|
||||||
0.9,
|
0.9,
|
||||||
);
|
);
|
||||||
makeTest("integralSum", T.Integral.sum(~cache=None, discrete), 1.0);
|
makeTest("integralEndY", T.Integral.sum(~cache=None, discrete), 1.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Mixed", () => {
|
describe("Mixed", () => {
|
||||||
|
@ -229,6 +247,7 @@ describe("Shape", () => {
|
||||||
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(
|
makeTest(
|
||||||
"scaleBy",
|
"scaleBy",
|
||||||
T.scaleBy(~scale=2.0, mixed),
|
T.scaleBy(~scale=2.0, mixed),
|
||||||
|
@ -254,9 +273,10 @@ describe("Shape", () => {
|
||||||
T.Integral.get(~cache=None, mixed),
|
T.Integral.get(~cache=None, mixed),
|
||||||
Distributions.Continuous.make(
|
Distributions.Continuous.make(
|
||||||
{
|
{
|
||||||
xs: [|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.15,
|
0.0,
|
||||||
|
0.0,
|
||||||
0.15,
|
0.15,
|
||||||
0.18496503496503497,
|
0.18496503496503497,
|
||||||
0.4349674825174825,
|
0.4349674825174825,
|
||||||
|
@ -270,4 +290,76 @@ describe("Shape", () => {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Mixed", () => {
|
||||||
|
open Distributions.DistPlus;
|
||||||
|
let discrete: DistTypes.xyShape = {
|
||||||
|
xs: [|1., 4., 8.|],
|
||||||
|
ys: [|0.3, 0.5, 0.2|],
|
||||||
|
};
|
||||||
|
let continuous =
|
||||||
|
Distributions.Continuous.make(
|
||||||
|
{xs: [|3., 7., 14.|], ys: [|0.058, 0.082, 0.124|]},
|
||||||
|
`Linear,
|
||||||
|
)
|
||||||
|
|> Distributions.Continuous.T.scaleToIntegralSum(~intendedSum=1.0);
|
||||||
|
let mixed =
|
||||||
|
MixedShapeBuilder.build(
|
||||||
|
~continuous,
|
||||||
|
~discrete,
|
||||||
|
~assumptions={
|
||||||
|
continuous: ADDS_TO_CORRECT_PROBABILITY,
|
||||||
|
discrete: ADDS_TO_CORRECT_PROBABILITY,
|
||||||
|
discreteProbabilityMass: Some(0.5),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|> E.O.toExn("");
|
||||||
|
let distPlus =
|
||||||
|
Distributions.DistPlus.make(
|
||||||
|
~shape=Mixed(mixed),
|
||||||
|
~guesstimatorString=None,
|
||||||
|
(),
|
||||||
|
);
|
||||||
|
makeTest("minX", T.minX(distPlus), Some(1.0));
|
||||||
|
makeTest("maxX", T.maxX(distPlus), Some(14.0));
|
||||||
|
makeTest(
|
||||||
|
"xToY at 4.0",
|
||||||
|
T.xToY(4., distPlus),
|
||||||
|
{discrete: 0.25, continuous: 0.03196803196803197},
|
||||||
|
);
|
||||||
|
makeTest(
|
||||||
|
"xToY at 0.0",
|
||||||
|
T.xToY(0., distPlus),
|
||||||
|
{discrete: 0.0, continuous: 0.028971028971028972},
|
||||||
|
);
|
||||||
|
makeTest(
|
||||||
|
"xToY at 5.0",
|
||||||
|
T.xToY(7., distPlus),
|
||||||
|
{discrete: 0.0, continuous: 0.04095904095904096},
|
||||||
|
);
|
||||||
|
makeTest("integralEndY", T.Integral.sum(~cache=None, distPlus), 1.0);
|
||||||
|
makeTest(
|
||||||
|
"integral",
|
||||||
|
T.Integral.get(~cache=None, distPlus) |> T.toContinuous,
|
||||||
|
Some(
|
||||||
|
Distributions.Continuous.make(
|
||||||
|
{
|
||||||
|
xs: [|1.00007, 1.00007, 3., 4., 4.00007, 7., 8., 8.00007, 14.|],
|
||||||
|
ys: [|
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.15,
|
||||||
|
0.18496503496503497,
|
||||||
|
0.4349674825174825,
|
||||||
|
0.5398601398601399,
|
||||||
|
0.5913086913086913,
|
||||||
|
0.6913122927072927,
|
||||||
|
1.0,
|
||||||
|
|],
|
||||||
|
},
|
||||||
|
`Linear,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
|
@ -1,12 +1,18 @@
|
||||||
// "mm(floor(uniform(30,35)), normal(50,20), [.25,.5])",
|
// "mm(floor(uniform(30,35)), normal(50,20), [.25,.5])",
|
||||||
|
// "mm(floor(normal(28,4)), normal(32,2), uniform(20,24), [.5,.2,.1])",
|
||||||
|
let timeVector: TimeTypes.timeVector = {
|
||||||
|
zero: MomentRe.momentNow(),
|
||||||
|
unit: `years,
|
||||||
|
};
|
||||||
|
|
||||||
let timeDist =
|
let timeDist =
|
||||||
DistPlusIngredients.make(
|
DistPlusIngredients.make(
|
||||||
~guesstimatorString="mm(floor(normal(30,2)), normal(39,1), [.5,.5])",
|
~guesstimatorString="mm(floor(10 to 15), 10 to 11, [.9,.1])",
|
||||||
~domain=Complete,
|
~domain=Complete,
|
||||||
~unit=TimeDistribution({zero: MomentRe.momentNow(), unit: `days}),
|
~unit=DistTypes.TimeDistribution(timeVector),
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
|> DistPlusIngredients.toDistPlus(~sampleCount=1000);
|
|> DistPlusIngredients.toDistPlus(~sampleCount=5000, ~outputXYPoints=1000);
|
||||||
|
|
||||||
let distributions = () =>
|
let distributions = () =>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -103,9 +103,16 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
||||||
|> E.Float.with2DigitsPrecision
|
|> E.Float.with2DigitsPrecision
|
||||||
|> ReasonReact.string}
|
|> ReasonReact.string}
|
||||||
</th>
|
</th>
|
||||||
|
<th className="px-4 py-2 border ">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.sum(~cache=None)
|
||||||
|
|> E.Float.with2DigitsPrecision
|
||||||
|
|> ReasonReact.string}
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div />
|
<div />
|
||||||
</div>;
|
</div>;
|
||||||
|
// chart
|
||||||
};
|
};
|
|
@ -320,7 +320,7 @@ export class CdfChartD3 {
|
||||||
function mouseover() {
|
function mouseover() {
|
||||||
const mouse = d3.mouse(this);
|
const mouse = d3.mouse(this);
|
||||||
hoverLine.attr('opacity', 1).attr('x1', mouse[0]).attr('x2', mouse[0]);
|
hoverLine.attr('opacity', 1).attr('x1', mouse[0]).attr('x2', mouse[0]);
|
||||||
const xValue = xScale.invert(mouse[0]).toFixed(2);
|
const xValue = xScale.invert(mouse[0]);
|
||||||
// This used to be here, but doesn't seem important
|
// This used to be here, but doesn't seem important
|
||||||
// const xValue = (mouse[0] > range[0] && mouse[0] < range[1]) ? : 0;
|
// const xValue = (mouse[0] > range[0] && mouse[0] < range[1]) ? : 0;
|
||||||
context.attrs.onHover(xValue);
|
context.attrs.onHover(xValue);
|
||||||
|
|
|
@ -8,22 +8,27 @@ let make =
|
||||||
unit,
|
unit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let toDistPlus = (~sampleCount, t: distPlusIngredients): option(distPlus) => {
|
let toDistPlus =
|
||||||
|
(~sampleCount=1000, ~outputXYPoints=1000, t: distPlusIngredients)
|
||||||
|
: option(distPlus) => {
|
||||||
let shape =
|
let shape =
|
||||||
Guesstimator.stringToMixedShape(
|
Guesstimator.stringToMixedShape(
|
||||||
~string=t.guesstimatorString,
|
~string=t.guesstimatorString,
|
||||||
~sampleCount,
|
~sampleCount,
|
||||||
|
~outputXYPoints,
|
||||||
(),
|
(),
|
||||||
)
|
);
|
||||||
|> E.O.bind(_, Distributions.Mixed.clean);
|
Js.log2("Line 21 with shape:", shape);
|
||||||
shape
|
let ss =
|
||||||
|> E.O.fmap(shape =>
|
shape
|
||||||
Distributions.DistPlus.make(
|
|> E.O.fmap(
|
||||||
~shape,
|
Distributions.DistPlus.make(
|
||||||
~domain=t.domain,
|
~shape=_,
|
||||||
~unit=t.unit,
|
~domain=t.domain,
|
||||||
~guesstimatorString=None,
|
~unit=t.unit,
|
||||||
(),
|
~guesstimatorString=None,
|
||||||
)
|
(),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
ss;
|
||||||
};
|
};
|
|
@ -80,7 +80,7 @@ module DistributionUnit = {
|
||||||
module Domain = {
|
module Domain = {
|
||||||
let excludedProbabilityMass = (t: domain) => {
|
let excludedProbabilityMass = (t: domain) => {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
| Complete => 1.0
|
| Complete => 0.0
|
||||||
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
||||||
| RightLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
| RightLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
||||||
| LeftAndRightLimited(
|
| LeftAndRightLimited(
|
||||||
|
|
|
@ -28,7 +28,7 @@ module type dist = {
|
||||||
|
|
||||||
type integral;
|
type integral;
|
||||||
let integral: (~cache: option(integral), t) => integral;
|
let integral: (~cache: option(integral), t) => integral;
|
||||||
let integralSum: (~cache: option(integral), t) => float;
|
let integralEndY: (~cache: option(integral), t) => float;
|
||||||
let integralXtoY: (~cache: option(integral), float, t) => float;
|
let integralXtoY: (~cache: option(integral), float, t) => float;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,6 +37,11 @@ module Dist = (T: dist) => {
|
||||||
type integral = T.integral;
|
type integral = T.integral;
|
||||||
let minX = T.minX;
|
let minX = T.minX;
|
||||||
let maxX = T.maxX;
|
let maxX = T.maxX;
|
||||||
|
let xTotalRange = (t: t) =>
|
||||||
|
switch (minX(t), maxX(t)) {
|
||||||
|
| (Some(min), Some(max)) => Some(max -. min)
|
||||||
|
| _ => None
|
||||||
|
};
|
||||||
let pointwiseFmap = T.pointwiseFmap;
|
let pointwiseFmap = T.pointwiseFmap;
|
||||||
let xToY = T.xToY;
|
let xToY = T.xToY;
|
||||||
let toShape = T.toShape;
|
let toShape = T.toShape;
|
||||||
|
@ -51,7 +56,7 @@ module Dist = (T: dist) => {
|
||||||
type t = T.integral;
|
type t = T.integral;
|
||||||
let get = T.integral;
|
let get = T.integral;
|
||||||
let xToY = T.integralXtoY;
|
let xToY = T.integralXtoY;
|
||||||
let sum = T.integralSum;
|
let sum = T.integralEndY;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is suboptimal because it could get the cache but doesn't here.
|
// This is suboptimal because it could get the cache but doesn't here.
|
||||||
|
@ -78,20 +83,24 @@ module Continuous = {
|
||||||
(fn, {xyShape, interpolation}: t): option(DistTypes.continuousShape) =>
|
(fn, {xyShape, interpolation}: t): option(DistTypes.continuousShape) =>
|
||||||
fn(xyShape) |> E.O.fmap(make(_, interpolation));
|
fn(xyShape) |> E.O.fmap(make(_, interpolation));
|
||||||
|
|
||||||
let toLinear = (t: t): t =>
|
let toLinear = (t: t): option(t) => {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
| {interpolation: `Stepwise, xyShape} => {
|
| {interpolation: `Stepwise, xyShape} =>
|
||||||
interpolation: `Linear,
|
xyShape
|
||||||
xyShape: xyShape |> XYShape.Range.stepsToContinuous |> E.O.toExt(""),
|
|> XYShape.Range.stepsToContinuous
|
||||||
}
|
|> E.O.fmap(xyShape => make(xyShape, `Linear))
|
||||||
| {interpolation: `Linear, _} => t
|
| {interpolation: `Linear, _} => Some(t)
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
let shapeFn = (fn, t: t) => t |> xyShape |> fn;
|
||||||
|
|
||||||
|
let convertToNewLength = i =>
|
||||||
|
shapeMap(CdfLibrary.Distribution.convertToNewLength(i));
|
||||||
|
|
||||||
module T =
|
module T =
|
||||||
Dist({
|
Dist({
|
||||||
type t = DistTypes.continuousShape;
|
type t = DistTypes.continuousShape;
|
||||||
type integral = DistTypes.continuousShape;
|
type integral = DistTypes.continuousShape;
|
||||||
let shapeFn = (fn, t: t) => t |> xyShape |> fn;
|
|
||||||
let minX = shapeFn(XYShape.minX);
|
let minX = shapeFn(XYShape.minX);
|
||||||
let maxX = shapeFn(XYShape.maxX);
|
let maxX = shapeFn(XYShape.maxX);
|
||||||
let pointwiseFmap = (fn, t: t) =>
|
let pointwiseFmap = (fn, t: t) =>
|
||||||
|
@ -126,7 +135,7 @@ module Continuous = {
|
||||||
|> E.O.toExt("This should not have happened")
|
|> E.O.toExt("This should not have happened")
|
||||||
|> fromShape,
|
|> fromShape,
|
||||||
);
|
);
|
||||||
let integralSum = (~cache, t) => t |> integral(~cache) |> lastY;
|
let integralEndY = (~cache, t) => t |> integral(~cache) |> lastY;
|
||||||
let integralXtoY = (~cache, f, t) =>
|
let integralXtoY = (~cache, f, t) =>
|
||||||
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
|
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
|
||||||
let toContinuous = t => Some(t);
|
let toContinuous = t => Some(t);
|
||||||
|
@ -144,7 +153,7 @@ module Discrete = {
|
||||||
let integral = (~cache, t) =>
|
let integral = (~cache, t) =>
|
||||||
cache
|
cache
|
||||||
|> E.O.default(Continuous.make(XYShape.accumulateYs(t), `Stepwise));
|
|> E.O.default(Continuous.make(XYShape.accumulateYs(t), `Stepwise));
|
||||||
let integralSum = (~cache, t) =>
|
let integralEndY = (~cache, t) =>
|
||||||
t |> integral(~cache) |> Continuous.lastY;
|
t |> integral(~cache) |> Continuous.lastY;
|
||||||
let minX = XYShape.minX;
|
let minX = XYShape.minX;
|
||||||
let maxX = XYShape.maxX;
|
let maxX = XYShape.maxX;
|
||||||
|
@ -186,8 +195,6 @@ module Mixed = {
|
||||||
discrete: {xs: [||], ys: [||]},
|
discrete: {xs: [||], ys: [||]},
|
||||||
} =>
|
} =>
|
||||||
None
|
None
|
||||||
| {continuous, discrete: {xs: [|_|], ys: [|_|]}} =>
|
|
||||||
Some(Continuous(continuous))
|
|
||||||
| {continuous, discrete: {xs: [||], ys: [||]}} =>
|
| {continuous, discrete: {xs: [||], ys: [||]}} =>
|
||||||
Some(Continuous(continuous))
|
Some(Continuous(continuous))
|
||||||
| {continuous: {xyShape: {xs: [||], ys: [||]}}, discrete} =>
|
| {continuous: {xyShape: {xs: [||], ys: [||]}}, discrete} =>
|
||||||
|
@ -241,7 +248,6 @@ module Mixed = {
|
||||||
let toScaledDiscrete = ({discrete} as t: t) =>
|
let toScaledDiscrete = ({discrete} as t: t) =>
|
||||||
Some(scaleDiscrete(t, discrete));
|
Some(scaleDiscrete(t, discrete));
|
||||||
|
|
||||||
// TODO: Add these two directly, once interpolation is added.
|
|
||||||
let integral =
|
let integral =
|
||||||
(
|
(
|
||||||
~cache,
|
~cache,
|
||||||
|
@ -258,6 +264,7 @@ module Mixed = {
|
||||||
discrete
|
discrete
|
||||||
|> Discrete.T.Integral.get(~cache=None)
|
|> Discrete.T.Integral.get(~cache=None)
|
||||||
|> Continuous.toLinear
|
|> Continuous.toLinear
|
||||||
|
|> E.O.toExn("")
|
||||||
|> Continuous.T.scaleBy(
|
|> Continuous.T.scaleBy(
|
||||||
~scale=discreteProbabilityMassFraction,
|
~scale=discreteProbabilityMassFraction,
|
||||||
);
|
);
|
||||||
|
@ -274,17 +281,8 @@ module Mixed = {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: Get last element of actual sum.
|
let integralEndY = (~cache, t: t) => {
|
||||||
let integralSum = (~cache, {discrete, continuous} as t: t) => {
|
integral(~cache, t) |> Continuous.lastY;
|
||||||
switch (cache) {
|
|
||||||
| Some(cache) => 3.0
|
|
||||||
| None =>
|
|
||||||
scaleDiscreteFn(t, Discrete.T.Integral.sum(~cache=None, discrete))
|
|
||||||
+. scaleContinuousFn(
|
|
||||||
t,
|
|
||||||
Continuous.T.Integral.sum(~cache=None, continuous),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let integralXtoY = (~cache, f, {discrete, continuous} as t: t) => {
|
let integralXtoY = (~cache, f, {discrete, continuous} as t: t) => {
|
||||||
|
@ -381,7 +379,7 @@ module Shape = {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let integralSum = (~cache, t: t) =>
|
let integralEndY = (~cache, t: t) =>
|
||||||
mapToAll(
|
mapToAll(
|
||||||
t,
|
t,
|
||||||
(
|
(
|
||||||
|
@ -419,6 +417,7 @@ module DistPlus = {
|
||||||
|
|
||||||
type t = DistTypes.distPlus;
|
type t = DistTypes.distPlus;
|
||||||
|
|
||||||
|
let shapeIntegral = shape => Shape.T.Integral.get(~cache=None, shape);
|
||||||
let make =
|
let make =
|
||||||
(
|
(
|
||||||
~shape,
|
~shape,
|
||||||
|
@ -428,7 +427,7 @@ module DistPlus = {
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
: t => {
|
: t => {
|
||||||
let integral = Shape.T.Integral.get(~cache=None, shape);
|
let integral = shapeIntegral(shape);
|
||||||
{shape, domain, integralCache: integral, unit, guesstimatorString};
|
{shape, domain, integralCache: integral, unit, guesstimatorString};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -448,6 +447,11 @@ module DistPlus = {
|
||||||
guesstimatorString: E.O.default(t.guesstimatorString, guesstimatorString),
|
guesstimatorString: E.O.default(t.guesstimatorString, guesstimatorString),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let updateShape = (shape, t) => {
|
||||||
|
let integralCache = shapeIntegral(shape);
|
||||||
|
update(~shape, ~integralCache, t);
|
||||||
|
};
|
||||||
|
|
||||||
let domainIncludedProbabilityMass = (t: t) =>
|
let domainIncludedProbabilityMass = (t: t) =>
|
||||||
Domain.includedProbabilityMass(t.domain);
|
Domain.includedProbabilityMass(t.domain);
|
||||||
|
|
||||||
|
@ -499,15 +503,15 @@ module DistPlus = {
|
||||||
let maxX = shapeFn(Shape.T.maxX);
|
let maxX = shapeFn(Shape.T.maxX);
|
||||||
let fromShape = (t, shape): t => update(~shape, t);
|
let fromShape = (t, shape): t => update(~shape, t);
|
||||||
|
|
||||||
// todo: adjust for limit, maybe?
|
|
||||||
let pointwiseFmap = (fn, {shape, _} as t: t): t =>
|
|
||||||
Shape.T.pointwiseFmap(fn, shape) |> fromShape(t);
|
|
||||||
|
|
||||||
// This bit is kind of akward, could probably use rethinking.
|
// This bit is kind of akward, could probably use rethinking.
|
||||||
let integral = (~cache as _, t: t) =>
|
let integral = (~cache as _, t: t) =>
|
||||||
fromShape(t, Continuous(t.integralCache));
|
updateShape(Continuous(t.integralCache), t);
|
||||||
|
|
||||||
let integralSum = (~cache as _, t: t) =>
|
// todo: adjust for limit, maybe?
|
||||||
|
let pointwiseFmap = (fn, {shape, _} as t: t): t =>
|
||||||
|
Shape.T.pointwiseFmap(fn, shape) |> updateShape(_, t);
|
||||||
|
|
||||||
|
let integralEndY = (~cache as _, t: t) =>
|
||||||
Shape.T.Integral.sum(~cache=Some(t.integralCache), toShape(t));
|
Shape.T.Integral.sum(~cache=Some(t.integralCache), toShape(t));
|
||||||
|
|
||||||
// TODO: Fix this below, obviously. Adjust for limits
|
// TODO: Fix this below, obviously. Adjust for limits
|
||||||
|
|
|
@ -8,6 +8,29 @@ type assumptions = {
|
||||||
discreteProbabilityMass: option(float),
|
discreteProbabilityMass: option(float),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let buildSimple = (~continuous, ~discrete): option(DistTypes.shape) => {
|
||||||
|
let cLength =
|
||||||
|
continuous |> Distributions.Continuous.getShape |> XYShape.xs |> E.A.length;
|
||||||
|
let dLength = discrete |> XYShape.xs |> E.A.length;
|
||||||
|
switch (cLength, dLength) {
|
||||||
|
| (0 | 1, 0) => None
|
||||||
|
| (0 | 1, _) => Some(Discrete(discrete))
|
||||||
|
| (_, 0) => Some(Continuous(continuous))
|
||||||
|
| (_, _) =>
|
||||||
|
let discreteProbabilityMassFraction =
|
||||||
|
Distributions.Discrete.T.Integral.sum(~cache=None, discrete);
|
||||||
|
let discrete =
|
||||||
|
Distributions.Discrete.T.scaleToIntegralSum(~intendedSum=1.0, discrete);
|
||||||
|
let foobar =
|
||||||
|
Distributions.Mixed.make(
|
||||||
|
~continuous,
|
||||||
|
~discrete,
|
||||||
|
~discreteProbabilityMassFraction,
|
||||||
|
)
|
||||||
|
|> Distributions.Mixed.clean;
|
||||||
|
foobar;
|
||||||
|
};
|
||||||
|
};
|
||||||
let build = (~continuous, ~discrete, ~assumptions) =>
|
let build = (~continuous, ~discrete, ~assumptions) =>
|
||||||
switch (assumptions) {
|
switch (assumptions) {
|
||||||
| {
|
| {
|
||||||
|
|
|
@ -47,8 +47,9 @@ module XtoY = {
|
||||||
let stepwiseIncremental = (f, t: t) =>
|
let stepwiseIncremental = (f, t: t) =>
|
||||||
firstPairAtOrBeforeValue(f, t) |> E.O.fmap(((_, y)) => y);
|
firstPairAtOrBeforeValue(f, t) |> E.O.fmap(((_, y)) => y);
|
||||||
|
|
||||||
let stepwiseIfAtX = (f, t: t) =>
|
let stepwiseIfAtX = (f: float, t: t) => {
|
||||||
getBy(t, ((x, _)) => x == f) |> E.O.fmap(((_, y)) => y);
|
getBy(t, ((x: float, _)) => {x == f}) |> E.O.fmap(((_, y)) => y);
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: When Roman's PR comes in, fix this bit. This depends on interpolation, obviously.
|
// TODO: When Roman's PR comes in, fix this bit. This depends on interpolation, obviously.
|
||||||
let linear = (f, t: t) => t |> CdfLibrary.Distribution.findY(f);
|
let linear = (f, t: t) => t |> CdfLibrary.Distribution.findY(f);
|
||||||
|
@ -208,16 +209,28 @@ module Range = {
|
||||||
// TODO: It would be nicer if this the diff didn't change the first element, and also maybe if there were a more elegant way of doing this.
|
// TODO: It would be nicer if this the diff didn't change the first element, and also maybe if there were a more elegant way of doing this.
|
||||||
let stepsToContinuous = t => {
|
let stepsToContinuous = t => {
|
||||||
let diff = xTotalRange(t) |> E.O.fmap(r => r *. 0.00001);
|
let diff = xTotalRange(t) |> E.O.fmap(r => r *. 0.00001);
|
||||||
switch (diff, E.A.toRanges(Belt.Array.zip(t.xs, t.ys))) {
|
let items =
|
||||||
| (Some(diff), Ok(items)) =>
|
switch (diff, E.A.toRanges(Belt.Array.zip(t.xs, t.ys))) {
|
||||||
Some(
|
| (Some(diff), Ok(items)) =>
|
||||||
items
|
Some(
|
||||||
|> Belt.Array.map(_, rangePointAssumingSteps)
|
items
|
||||||
|> Belt.Array.unzip
|
|> Belt.Array.map(_, rangePointAssumingSteps)
|
||||||
|> fromArray
|
|> Belt.Array.unzip
|
||||||
|> intersperce(t |> xMap(e => e +. diff)),
|
|> fromArray
|
||||||
)
|
|> intersperce(t |> xMap(e => e +. diff)),
|
||||||
| _ => None
|
)
|
||||||
};
|
| _ => Some(t)
|
||||||
|
};
|
||||||
|
let bar = items |> E.O.fmap(zip) |> E.O.bind(_, E.A.get(_, 0));
|
||||||
|
let items =
|
||||||
|
switch (items, bar) {
|
||||||
|
| (Some(items), Some((0.0, _))) => Some(items)
|
||||||
|
| (Some(items), Some((firstX, _))) =>
|
||||||
|
let all = E.A.append([|(firstX, 0.0)|], items |> zip);
|
||||||
|
let foo = all |> Belt.Array.unzip |> fromArray;
|
||||||
|
Some(foo);
|
||||||
|
| _ => None
|
||||||
|
};
|
||||||
|
items;
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -151,7 +151,8 @@ module Model = {
|
||||||
| Some({truthValue: false}) => difference
|
| Some({truthValue: false}) => difference
|
||||||
| None =>
|
| None =>
|
||||||
let foo =
|
let foo =
|
||||||
getGlobalCatastropheChance(dateTime)
|
// getGlobalCatastropheChance(dateTime)
|
||||||
|
Some(0.5)
|
||||||
|> E.O.fmap(E.Float.with2DigitsPrecision)
|
|> E.O.fmap(E.Float.with2DigitsPrecision)
|
||||||
|> E.O.fmap((r: string) =>
|
|> E.O.fmap((r: string) =>
|
||||||
"uniform(0,1) > " ++ r ++ " ? " ++ difference ++ ": 0"
|
"uniform(0,1) > " ++ r ++ " ? " ++ difference ++ ": 0"
|
||||||
|
@ -177,7 +178,6 @@ module Model = {
|
||||||
GuesstimatorDist.logNormal(40., 4.),
|
GuesstimatorDist.logNormal(40., 4.),
|
||||||
),
|
),
|
||||||
~domain=RightLimited({xPoint: 100., excludingProbabilityMass: 0.3}),
|
~domain=RightLimited({xPoint: 100., excludingProbabilityMass: 0.3}),
|
||||||
~unit=TimeDistribution({zero: currentDateTime, unit: `years}),
|
|
||||||
(),
|
(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -96,6 +96,18 @@ const {
|
||||||
let cdf = new Cdf(xs, ys);
|
let cdf = new Cdf(xs, ys);
|
||||||
return cdf.findY(x);
|
return cdf.findY(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @param xs
|
||||||
|
* @param ys
|
||||||
|
* @returns {number[]}
|
||||||
|
*/
|
||||||
|
function convertToNewLength(n, { xs, ys }) {
|
||||||
|
let dist = new ContinuousDistribution(xs, ys);
|
||||||
|
return dist.convertToNewLength(n);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -153,6 +165,7 @@ const {
|
||||||
pdfToCdf,
|
pdfToCdf,
|
||||||
findY,
|
findY,
|
||||||
findX,
|
findX,
|
||||||
|
convertToNewLength,
|
||||||
mean,
|
mean,
|
||||||
scoreNonMarketCdfCdf,
|
scoreNonMarketCdfCdf,
|
||||||
differentialEntropy,
|
differentialEntropy,
|
||||||
|
|
|
@ -32,9 +32,18 @@ module JS = {
|
||||||
[@bs.module "./CdfLibrary.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external differentialEntropy: (int, distJs) => distJs =
|
external differentialEntropy: (int, distJs) => distJs =
|
||||||
"differentialEntropy";
|
"differentialEntropy";
|
||||||
|
|
||||||
|
[@bs.module "./CdfLibrary.js"]
|
||||||
|
external convertToNewLength: (int, distJs) => distJs = "convertToNewLength";
|
||||||
};
|
};
|
||||||
|
|
||||||
module Distribution = {
|
module Distribution = {
|
||||||
|
let convertToNewLength = (int, {xs, _} as dist: DistTypes.xyShape) =>
|
||||||
|
switch (E.A.length(xs)) {
|
||||||
|
| 0
|
||||||
|
| 1 => dist
|
||||||
|
| _ => dist |> JS.doAsDist(JS.convertToNewLength(int))
|
||||||
|
};
|
||||||
let toPdf = dist => dist |> JS.doAsDist(JS.cdfToPdf);
|
let toPdf = dist => dist |> JS.doAsDist(JS.cdfToPdf);
|
||||||
let toCdf = dist => dist |> JS.doAsDist(JS.pdfToCdf);
|
let toCdf = dist => dist |> JS.doAsDist(JS.pdfToCdf);
|
||||||
let findX = (y, dist) => dist |> JS.distToJs |> JS.findX(y);
|
let findX = (y, dist) => dist |> JS.distToJs |> JS.findX(y);
|
||||||
|
|
|
@ -16,6 +16,7 @@ module Internals = {
|
||||||
discrete,
|
discrete,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// todo: Force to be fewer samples
|
||||||
let toContinous = (r: combined) =>
|
let toContinous = (r: combined) =>
|
||||||
continuousGet(r)
|
continuousGet(r)
|
||||||
|> CdfLibrary.JS.jsToDist
|
|> CdfLibrary.JS.jsToDist
|
||||||
|
@ -25,22 +26,24 @@ module Internals = {
|
||||||
discreteGet(r) |> jsToDistDiscrete;
|
discreteGet(r) |> jsToDistDiscrete;
|
||||||
|
|
||||||
[@bs.module "./GuesstimatorLibrary.js"]
|
[@bs.module "./GuesstimatorLibrary.js"]
|
||||||
external toCombinedFormat: (string, int) => combined = "run";
|
external toCombinedFormat: (string, int, int) => combined = "run";
|
||||||
|
|
||||||
// todo: Format to correct mass, also normalize the pdf.
|
// todo: Format to correct mass, also normalize the pdf.
|
||||||
let toMixedShape = (r: combined): option(DistTypes.mixedShape) => {
|
let toMixedShape = (r: combined): option(DistTypes.shape) => {
|
||||||
let assumptions: MixedShapeBuilder.assumptions = {
|
let continuous =
|
||||||
continuous: ADDS_TO_1,
|
toContinous(r) |> Distributions.Continuous.convertToNewLength(100);
|
||||||
discrete: ADDS_TO_CORRECT_PROBABILITY,
|
let discrete = toDiscrete(r);
|
||||||
discreteProbabilityMass: None,
|
// let continuousProb =
|
||||||
};
|
// cont |> Distributions.Continuous.T.Integral.sum(~cache=None);
|
||||||
MixedShapeBuilder.build(
|
// let discreteProb =
|
||||||
~continuous=toContinous(r),
|
// d |> Distributions.Discrete.T.Integral.sum(~cache=None);
|
||||||
~discrete=toDiscrete(r),
|
|
||||||
~assumptions,
|
let foo = MixedShapeBuilder.buildSimple(~continuous, ~discrete);
|
||||||
);
|
foo;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let stringToMixedShape = (~string, ~sampleCount=1000, ()) =>
|
let stringToMixedShape =
|
||||||
Internals.toCombinedFormat(string, sampleCount) |> Internals.toMixedShape;
|
(~string, ~sampleCount=1000, ~outputXYPoints=1000, ()) =>
|
||||||
|
Internals.toCombinedFormat(string, sampleCount, outputXYPoints)
|
||||||
|
|> Internals.toMixedShape;
|
|
@ -34,7 +34,7 @@ const ratioSize = samples => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const toPdf = (values, sampleCount, min, max) => {
|
const toPdf = (values, outputResolutionCount, min, max) => {
|
||||||
let duplicateSamples = _(values).groupBy().pickBy(x => x.length > 1).keys().value();
|
let duplicateSamples = _(values).groupBy().pickBy(x => x.length > 1).keys().value();
|
||||||
let totalLength = _.size(values);
|
let totalLength = _.size(values);
|
||||||
let frequencies = duplicateSamples.map(s => ({value: parseFloat(s), percentage: _(values).filter(x => x ==s).size()/totalLength}));
|
let frequencies = duplicateSamples.map(s => ({value: parseFloat(s), percentage: _(values).filter(x => x ==s).size()/totalLength}));
|
||||||
|
@ -48,13 +48,13 @@ const toPdf = (values, sampleCount, min, max) => {
|
||||||
const ratioSize$ = ratioSize(samples);
|
const ratioSize$ = ratioSize(samples);
|
||||||
const width = ratioSize$ === 'SMALL' ? 100 : 1;
|
const width = ratioSize$ === 'SMALL' ? 100 : 1;
|
||||||
|
|
||||||
const pdf = samples.toPdf({ size: sampleCount, width, min, max });
|
const pdf = samples.toPdf({ size: outputResolutionCount, width, min, max });
|
||||||
continuous = pdf;
|
continuous = pdf;
|
||||||
}
|
}
|
||||||
return {continuous, discrete};
|
return {continuous, discrete};
|
||||||
};
|
};
|
||||||
|
|
||||||
let run = (text, sampleCount, inputs=[], min=false, max=false) => {
|
let run = (text, sampleCount, outputResolutionCount, inputs=[], min=false, max=false) => {
|
||||||
let [_error, item] = Guesstimator.parse({ text: "=" + text });
|
let [_error, item] = Guesstimator.parse({ text: "=" + text });
|
||||||
const { parsedInput } = item;
|
const { parsedInput } = item;
|
||||||
const { guesstimateType } = parsedInput;
|
const { guesstimateType } = parsedInput;
|
||||||
|
@ -78,7 +78,7 @@ let run = (text, sampleCount, inputs=[], min=false, max=false) => {
|
||||||
} else if (values.length === 1) {
|
} else if (values.length === 1) {
|
||||||
update = blankResponse;
|
update = blankResponse;
|
||||||
} else {
|
} else {
|
||||||
update = toPdf(values, sampleCount, min, max);
|
update = toPdf(values, outputResolutionCount, min, max);
|
||||||
}
|
}
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user