diff --git a/showcase/entries/Continuous.re b/showcase/entries/Continuous.re
index 8448d044..7357d5b6 100644
--- a/showcase/entries/Continuous.re
+++ b/showcase/entries/Continuous.re
@@ -12,7 +12,7 @@ let distributions = () =>
{"Basic Mixed Distribution" |> ReasonReact.string}
- {timeDist |> E.O.React.fmapOrNull(distPlus => )}
+ {timeDist |> E.O.React.fmapOrNull(distPlus => )}
{"Simple Continuous" |> ReasonReact.string}
;
diff --git a/src/components/charts/DistPlusChart.re b/src/components/charts/DistPlusPlot.re
similarity index 95%
rename from src/components/charts/DistPlusChart.re
rename to src/components/charts/DistPlusPlot.re
index 4f914699..587901af 100644
--- a/src/components/charts/DistPlusChart.re
+++ b/src/components/charts/DistPlusPlot.re
@@ -10,7 +10,7 @@ module DistPlusChart = {
let minX = T.minX(distPlus);
let maxX = T.maxX(distPlus);
let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson;
- T.toContinuous
- |> E.O.fmap(Distributions.Continuous.toLinear)
|> E.O.fmap(Distributions.Continuous.getShape);
let minX = T.minX(integral);
let maxX = T.maxX(integral);
let timeScale = distPlus.unit |> DistTypes.DistributionUnit.toJson;
-
ReasonReact.wrapJsForReason(
- ~reactClass=cdfChart,
+ ~reactClass=plot,
~props=
makeProps(
~height?,
@@ -102,7 +102,7 @@ let make =
~timeScale=?,
) => {
-
{
+let toDistPlus = (~sampleCount, t: distPlusIngredients): option(distPlus) => {
let shape =
Guesstimator.stringToMixedShape(
~string=t.guesstimatorString,
diff --git a/src/distributions/Distributions.re b/src/distributions/Distributions.re
index dcd4f395..5373254e 100644
--- a/src/distributions/Distributions.re
+++ b/src/distributions/Distributions.re
@@ -74,7 +74,7 @@ module Continuous = {
};
let oShapeMap =
(fn, {xyShape, interpolation}: t): option(DistTypes.continuousShape) =>
- fn(xyShape) |> E.O.fmap(xyShape => make(xyShape, interpolation));
+ fn(xyShape) |> E.O.fmap(make(_, interpolation));
let toLinear = (t: t): t =>
switch (t) {
@@ -90,7 +90,8 @@ module Continuous = {
type t = DistTypes.continuousShape;
type integral = DistTypes.continuousShape;
let shapeFn = (fn, t: t) => t |> xyShape |> fn;
- // TODO: Obviously fix this, it's terrible
+ // TODO: Obviously fix this, it's terrible. Use interpolation method here.
+ // TODO: Steps could be 1 value, interpolation needs at least 2.
let integral = (~cache, t) =>
cache
|> E.O.default(
@@ -108,7 +109,7 @@ module Continuous = {
let pointwiseFmap = (fn, t: t) =>
t |> xyShape |> XYShape.pointwiseMap(fn) |> fromShape;
let toShape = (t: t): DistTypes.shape => Continuous(t);
- // TODO: When Roman's PR comes in, fix this bit.
+ // TODO: When Roman's PR comes in, fix this bit. This depends on interpolation, obviously.
let xToY = (f, t) =>
shapeFn(CdfLibrary.Distribution.findY(f), t)
|> DistTypes.MixedPoint.makeContinuous;
@@ -126,6 +127,8 @@ module Discrete = {
Dist({
type t = DistTypes.discreteShape;
type integral = DistTypes.continuousShape;
+ // todo: test this. Remove "stepstoContinuos-move elsewhere"
+ // todo: Make sure this works fine with one value. This is important for step functionality.
let integral = (~cache, t) =>
cache
|> E.O.default(
@@ -138,6 +141,7 @@ module Discrete = {
);
},
);
+ // todo: Fix this with last element
let integralSum = (~cache, t) => t |> XYShape.ySum;
let minX = XYShape.minX;
let maxX = XYShape.maxX;
@@ -145,17 +149,20 @@ module Discrete = {
let toShape = (t: t): DistTypes.shape => Discrete(t);
let toContinuous = _ => None;
let toDiscrete = t => Some(t);
- let toScaledContinuous = t => None;
+ let toScaledContinuous = _ => None;
let toScaledDiscrete = t => Some(t);
+ // todo: Fix this with code that work find recent value and use that instead.
let xToY = (f, t) =>
CdfLibrary.Distribution.findY(f, t)
|> DistTypes.MixedPoint.makeDiscrete;
+ // todo: This should use cache and/or same code as above. FindingY is more complex, should use interpolationType.
let integralXtoY = (~cache, f, t) =>
t |> XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
});
};
module Mixed = {
+ type t = DistTypes.mixedShape;
let make =
(~continuous, ~discrete, ~discreteProbabilityMassFraction)
: DistTypes.mixedShape => {
@@ -171,7 +178,8 @@ module Mixed = {
discrete: {xs: [||], ys: [||]},
} =>
None
- | {discrete: {xs: [|_|], ys: [|_|]}} => None
+ | {continuous, discrete: {xs: [|_|], ys: [|_|]}} =>
+ Some(Continuous(continuous))
| {continuous, discrete: {xs: [||], ys: [||]}} =>
Some(Continuous(continuous))
| {continuous: {xyShape: {xs: [||], ys: [||]}}, discrete} =>
@@ -180,6 +188,7 @@ module Mixed = {
};
};
+ // todo: Put into scaling module
let scaleDiscreteFn =
({discreteProbabilityMassFraction}: DistTypes.mixedShape, f) =>
f *. discreteProbabilityMassFraction;
@@ -188,6 +197,13 @@ module Mixed = {
({discreteProbabilityMassFraction}: DistTypes.mixedShape, f) =>
f *. (1.0 -. discreteProbabilityMassFraction);
+ let scaleContinuous = ({discreteProbabilityMassFraction}: t, continuous) =>
+ continuous
+ |> Continuous.T.scaleBy(~scale=1.0 -. discreteProbabilityMassFraction);
+
+ let scaleDiscrete = ({discreteProbabilityMassFraction}: t, disrete) =>
+ disrete |> Discrete.T.scaleBy(~scale=discreteProbabilityMassFraction);
+
module T =
Dist({
type t = DistTypes.mixedShape;
@@ -211,14 +227,6 @@ module Mixed = {
DistTypes.MixedPoint.add(c, d);
};
- let scaleContinuous =
- ({discreteProbabilityMassFraction}: t, continuous) =>
- continuous
- |> Continuous.T.scaleBy(~scale=1.0 -. discreteProbabilityMassFraction);
-
- let scaleDiscrete = ({discreteProbabilityMassFraction}: t, disrete) =>
- disrete |> Discrete.T.scaleBy(~scale=discreteProbabilityMassFraction);
-
let toScaledContinuous = ({continuous} as t: t) =>
Some(scaleContinuous(t, continuous));
@@ -241,10 +249,17 @@ module Mixed = {
let dist =
discrete
|> Discrete.T.Integral.get(~cache=None)
+ |> Continuous.toLinear
|> Continuous.T.scaleBy(
~scale=discreteProbabilityMassFraction,
);
- dist;
+ Continuous.make(
+ XYShape.combine(
+ Continuous.getShape(cont),
+ Continuous.getShape(dist),
+ ),
+ `Linear,
+ );
},
);
};
@@ -268,6 +283,7 @@ module Mixed = {
scaleDiscreteFn(t, discrete) +. scaleContinuousFn(t, cont);
};
+ // TODO: This functionality is kinda weird, because it seems to assume the cdf adds to 1.0 elsewhere, which wouldn't happen here.
let pointwiseFmap =
(fn, {discrete, continuous, discreteProbabilityMassFraction}: t): t => {
{
@@ -285,6 +301,8 @@ module Shape = {
type t = DistTypes.shape;
type integral = DistTypes.continuousShape;
+ // todo: change order of arguments so t goes last.
+ // todo: Think of other name here?
let mapToAll = (t: t, (fn1, fn2, fn3)) =>
switch (t) {
| Mixed(m) => fn1(m)
@@ -388,6 +406,9 @@ module Shape = {
module DistPlus = {
open DistTypes;
+
+ type t = DistTypes.distPlus;
+
let make =
(
~shape,
@@ -396,10 +417,11 @@ module DistPlus = {
~unit=UnspecifiedDistribution,
(),
)
- : distPlus => {
+ : t => {
let integral = Shape.T.Integral.get(~cache=None, shape);
{shape, domain, integralCache: integral, unit, guesstimatorString};
};
+
let update =
(
~shape=?,
@@ -407,7 +429,7 @@ module DistPlus = {
~domain=?,
~unit=?,
~guesstimatorString=?,
- t: distPlus,
+ t: t,
) => {
shape: E.O.default(t.shape, shape),
integralCache: E.O.default(t.integralCache, integralCache),
@@ -416,29 +438,32 @@ module DistPlus = {
guesstimatorString: E.O.default(t.guesstimatorString, guesstimatorString),
};
+ 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 = ({shape, _}: t) => shape;
- let shapeFn = (fn, t: t) => t |> toShape |> fn;
+ let toShape = toShape;
let toContinuous = shapeFn(Shape.T.toContinuous);
let toDiscrete = shapeFn(Shape.T.toDiscrete);
// todo: Adjust for total mass.
- let domainIncludedProbabilityMass = (t: t) =>
- Domain.includedProbabilityMass(t.domain);
-
- let domainIncludedProbabilityMassAdjustment = (t: t, f) =>
- f *. Domain.includedProbabilityMass(t.domain);
-
let toScaledContinuous = (t: t) => {
t
|> toShape
|> Shape.T.toScaledContinuous
|> E.O.fmap(
- Continuous.T.pointwiseFmap(r =>
- r *. domainIncludedProbabilityMass(t)
+ Continuous.T.pointwiseFmap(
+ domainIncludedProbabilityMassAdjustment(t),
),
);
};
@@ -475,9 +500,41 @@ module DistPlus = {
let integralSum = (~cache as _, t: t) =>
Shape.T.Integral.sum(~cache=Some(t.integralCache), toShape(t));
- // TODO: Fix this below, obviously. Adjust for limit.
+ // 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));
};
});
+};
+
+module DistPlusTime = {
+ open DistTypes;
+ open DistPlus;
+
+ 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 = (~cache as _, f: TimeTypes.timeInVector, t: t) => {
+ timeInVectorToX(f, t)
+ |> E.O.fmap(x => DistPlus.T.Integral.xToY(~cache=None, x, t));
+ };
+ };
};
\ No newline at end of file
diff --git a/src/distributions/TimeTypes.re b/src/distributions/TimeTypes.re
index 75e158e2..355e8ba5 100644
--- a/src/distributions/TimeTypes.re
+++ b/src/distributions/TimeTypes.re
@@ -50,11 +50,11 @@ module TimePoint = {
MomentRe.diff(timeVector.zero, moment, timeVector.unit);
};
-module RelativeTimePoint = {
- type timeInVector =
- | Time(MomentRe.Moment.t)
- | XValue(float);
+type timeInVector =
+ | Time(MomentRe.Moment.t)
+ | XValue(float);
+module RelativeTimePoint = {
let toTime = (timeVector: timeVector, timeInVector: timeInVector) =>
switch (timeInVector) {
| Time(r) => r
diff --git a/src/distributions/XYShape.re b/src/distributions/XYShape.re
index 531282d4..a0e55724 100644
--- a/src/distributions/XYShape.re
+++ b/src/distributions/XYShape.re
@@ -23,6 +23,22 @@ let fromArray = ((xs, ys)): t => {xs, ys};
let fromArrays = (xs, ys): t => {xs, ys};
let pointwiseMap = (fn, t: t): t => {xs: t.xs, ys: t.ys |> E.A.fmap(fn)};
+let compare = (a: float, b: float) => a > b ? 1 : (-1);
+
+let comparePoints = ((x1: float, y1: float), (x2: float, y2: float)) =>
+ switch (x1 == x2, y1 == y2) {
+ | (false, _) => compare(x1, x2)
+ | (true, false) => compare(y1, y2)
+ | (true, true) => (-1)
+ };
+
+let combine = (t1: t, t2: t) => {
+ let totalLength = E.A.length(t1.xs) + E.A.length(t2.xs);
+ let array = Belt.Array.concat(zip(t1), zip(t2));
+ Array.sort(comparePoints, array);
+ array |> Belt.Array.unzip |> fromArray;
+};
+
let intersperce = (t1: t, t2: t) => {
let items: ref(array((float, float))) = ref([||]);
let t1 = zip(t1);
diff --git a/src/interface/FormBuilder.re b/src/interface/FormBuilder.re
index 8849019a..55f1bf23 100644
--- a/src/interface/FormBuilder.re
+++ b/src/interface/FormBuilder.re
@@ -22,7 +22,7 @@ let propValue = (t: Prop.Value.t) => {
DistPlusIngredients.toDistPlus(~sampleCount=1000, r);
switch (newDistribution) {
| Some(distribution) =>
-
+
| None => "Something went wrong" |> ReasonReact.string
};
| FloatCdf(_) =>
diff --git a/src/models/EAFunds.re b/src/models/EAFunds.re
index e1d6bbf4..d21e6d01 100644
--- a/src/models/EAFunds.re
+++ b/src/models/EAFunds.re
@@ -109,14 +109,20 @@ module Model = {
// TODO: Fixe number that integral is calculated for
let getGlobalCatastropheChance = dateTime => {
- let model = GlobalCatastrophe.Model.make(dateTime);
- switch (model) {
- | Prop.Value.DistPlusIngredients(distPlusIngredients) =>
- distPlusIngredients
- |> DistPlusIngredients.toDistPlus(~sampleCount=1000)
- |> E.O.fmap(Distributions.DistPlus.T.Integral.xToY(~cache=None, 18.0))
- | _ => None
- };
+ GlobalCatastrophe.makeI(MomentRe.momentNow())
+ |> DistPlusIngredients.toDistPlus(~sampleCount=1000)
+ |> E.O.bind(
+ _,
+ t => {
+ let foo =
+ Distributions.DistPlusTime.Integral.xToY(
+ ~cache=None,
+ Time(dateTime),
+ t,
+ );
+ Some(0.5);
+ },
+ );
};
let make =
diff --git a/src/models/GlobalCatastrophe.re b/src/models/GlobalCatastrophe.re
index d7002f73..82cbfc56 100644
--- a/src/models/GlobalCatastrophe.re
+++ b/src/models/GlobalCatastrophe.re
@@ -1,5 +1,12 @@
-let guesstimatorString = "20 to 80";
+let guesstimatorString = "floor(10 to 20)";
+let makeI = (currentDateTime: MomentRe.Moment.t) => {
+ DistPlusIngredients.make(
+ ~guesstimatorString,
+ ~unit=TimeDistribution({zero: currentDateTime, unit: `years}),
+ (),
+ );
+};
module Model = {
let make = (currentDateTime: MomentRe.Moment.t) => {
let distPlusIngredients =
diff --git a/src/lib/E.re b/src/utility/E.re
similarity index 100%
rename from src/lib/E.re
rename to src/utility/E.re
diff --git a/src/lib/GuesstimatorDist.re b/src/utility/GuesstimatorDist.re
similarity index 100%
rename from src/lib/GuesstimatorDist.re
rename to src/utility/GuesstimatorDist.re