diff --git a/showcase/entries/Continuous.re b/showcase/entries/Continuous.re index 16a377b3..6ec0ba41 100644 --- a/showcase/entries/Continuous.re +++ b/showcase/entries/Continuous.re @@ -3,7 +3,6 @@ let timeDist = GenericDistribution.make( ~generationSource= GuesstimatorString("mm(floor(normal(30,2)), normal(39,1), [.5,.5])"), - ~probabilityType=Pdf, ~domain=Complete, ~unit=TimeDistribution({zero: MomentRe.momentNow(), unit: `days}), (), diff --git a/src/components/charts/ComplexPowerChart.re b/src/components/charts/ComplexPowerChart.re index 191847ff..8969aa34 100644 --- a/src/components/charts/ComplexPowerChart.re +++ b/src/components/charts/ComplexPowerChart.re @@ -23,11 +23,6 @@ module ComplexPowerChart = { }; }; -let bar: DistributionTypes.xyShape = { - ys: [|0.5, 0.8, 0.4, 1.0, 2.0|], - xs: [|0.0, 1., 2., 5., 8.|], -}; - module IntegralChart = { [@react.component] let make = (~complexPower: DistributionTypes.complexPower, ~onHover) => { diff --git a/src/core/DistFunctor.re b/src/core/DistFunctor.re index 7a1fe17a..8cd0ddf8 100644 --- a/src/core/DistFunctor.re +++ b/src/core/DistFunctor.re @@ -109,6 +109,7 @@ module Continuous = { let pointwiseFmap = (fn, t: t) => t |> xyShape |> XYShape.pointwiseMap(fn) |> fromShape; let toShape = (t: t): DistributionTypes.shape => Continuous(t); + // TODO: When Roman's PR comes in, fix this bit. let xToY = (f, t) => shapeFn(CdfLibrary.Distribution.findY(f), t) |> DistributionTypes.MixedPoint.makeContinuous; @@ -181,11 +182,11 @@ module Mixed = { }; }; - let scaleDiscrete = + let scaleDiscreteFn = ({discreteProbabilityMassFraction}: DistributionTypes.mixedShape, f) => f *. discreteProbabilityMassFraction; - let scaleContinuous = + let scaleContinuousFn = ({discreteProbabilityMassFraction}: DistributionTypes.mixedShape, f) => f *. (1.0 -. discreteProbabilityMassFraction); @@ -200,19 +201,15 @@ module Mixed = { let toShape = (t: t): DistributionTypes.shape => Mixed(t); let toContinuous = ({continuous}: t) => Some(continuous); let toDiscrete = ({discrete}: t) => Some(discrete); - let xToY = - ( - f, - {discrete, continuous, discreteProbabilityMassFraction} as t: t, - ) => { + let xToY = (f, {discrete, continuous} as t: t) => { let c = continuous |> Continuous.T.xToY(f) - |> DistributionTypes.MixedPoint.fmap(scaleContinuous(t)); + |> DistributionTypes.MixedPoint.fmap(scaleContinuousFn(t)); let d = discrete |> Discrete.T.xToY(f) - |> DistributionTypes.MixedPoint.fmap(scaleDiscrete(t)); + |> DistributionTypes.MixedPoint.fmap(scaleDiscreteFn(t)); DistributionTypes.MixedPoint.add(c, d); }; @@ -254,33 +251,23 @@ module Mixed = { ); }; - let integralSum = - ( - ~cache, - {discrete, continuous, discreteProbabilityMassFraction}: t, - ) => { + // todo: Get last element of actual sum. + let integralSum = (~cache, {discrete, continuous} as t: t) => { switch (cache) { | Some(cache) => 3.0 | None => - Discrete.T.Integral.sum(~cache=None, discrete) - *. discreteProbabilityMassFraction - +. Continuous.T.Integral.sum(~cache=None, continuous) - *. (1.0 -. discreteProbabilityMassFraction) + scaleDiscreteFn(t, Discrete.T.Integral.sum(~cache=None, discrete)) + +. scaleContinuousFn( + t, + Continuous.T.Integral.sum(~cache=None, continuous), + ) }; }; - let integralXtoY = - ( - ~cache, - f, - {discrete, continuous, discreteProbabilityMassFraction}: t, - ) => { + let integralXtoY = (~cache, f, {discrete, continuous} as t: t) => { let cont = Continuous.T.Integral.xToY(~cache, f, continuous); let discrete = Discrete.T.Integral.xToY(~cache, f, discrete); - discrete - *. discreteProbabilityMassFraction - +. cont - *. (1.0 -. discreteProbabilityMassFraction); + scaleDiscreteFn(t, discrete) +. scaleContinuousFn(t, cont); }; let pointwiseFmap = @@ -440,20 +427,57 @@ module ComplexPower = { let toContinuous = shapeFn(Shape.T.toContinuous); let toDiscrete = shapeFn(Shape.T.toDiscrete); // todo: Adjust for total mass. - let toScaledContinuous = shapeFn(Shape.T.toContinuous); - let toScaledDiscrete = shapeFn(Shape.T.toScaledDiscrete); + + 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) + ), + ); + }; + + let toScaledDiscrete = (t: t) => { + t + |> toShape + |> Shape.T.toScaledDiscrete + |> E.O.fmap( + Discrete.T.pointwiseFmap( + domainIncludedProbabilityMassAdjustment(t), + ), + ); + }; + // todo: adjust for limit, and the fact that total mass is lower. - let xToY = f => shapeFn(Shape.T.xToY(f)); + 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 fromShape = (shape, t): t => update(~shape, t); - // todo: adjust for limit + let fromShape = (t, shape): t => update(~shape, t); + + // todo: adjust for limit, maybe? let pointwiseFmap = (fn, {shape, _} as t: t): t => - fromShape(Shape.T.pointwiseFmap(fn, shape), t); + Shape.T.pointwiseFmap(fn, shape) |> fromShape(t); + + // This bit is kind of akward, could probably use rethinking. let integral = (~cache as _, t: t) => - fromShape(Continuous(t.integralCache), t); + fromShape(t, Continuous(t.integralCache)); + let integralSum = (~cache as _, t: t) => Shape.T.Integral.sum(~cache=Some(t.integralCache), toShape(t)); + // TODO: Fix this below, obviously. Adjust for limit. let integralXtoY = (~cache as _, f, t: t) => { Shape.T.Integral.xToY(~cache=Some(t.integralCache), f, toShape(t)); diff --git a/src/core/DistributionTypes.re b/src/core/DistributionTypes.re index 6eda94ee..5b7b702a 100644 --- a/src/core/DistributionTypes.re +++ b/src/core/DistributionTypes.re @@ -14,16 +14,9 @@ type xyShape = { ys: array(float), }; -let foo = {xs: [|1., 2., 5.|], ys: [|1., 2., 3.|]}; -let answer = {xs: [|1., 2., 2., 5., 5.|], ys: [|1., 1., 2., 2., 3.|]}; - -let toStepwise = (xyShape: xyShape) => {}; - -type interpolationMethod = [ | `Stepwise | `Linear]; - type continuousShape = { xyShape, - interpolation: interpolationMethod, + interpolation: [ | `Stepwise | `Linear], }; type discreteShape = xyShape; @@ -59,14 +52,8 @@ type distributionUnit = | UnspecifiedDistribution | TimeDistribution(TimeTypes.timeVector); -type probabilityType = - | Cdf - | Pdf - | Arbitrary; - type genericDistribution = { generationSource, - probabilityType, domain, unit: distributionUnit, }; @@ -104,6 +91,9 @@ module Domain = { }; }; + let includedProbabilityMass = (t: domain) => + 1.0 -. excludedProbabilityMass(t); + let initialProbabilityMass = (t: domain) => { switch (t) { | Complete diff --git a/src/core/GenericDistribution.re b/src/core/GenericDistribution.re index 2603a1cf..7cde2e66 100644 --- a/src/core/GenericDistribution.re +++ b/src/core/GenericDistribution.re @@ -1,16 +1,9 @@ open DistributionTypes; let make = - ( - ~generationSource, - ~probabilityType=Pdf, - ~domain=Complete, - ~unit=UnspecifiedDistribution, - (), - ) + (~generationSource, ~domain=Complete, ~unit=UnspecifiedDistribution, ()) : genericDistribution => { generationSource, - probabilityType, domain, unit, }; diff --git a/src/models/EAFunds.re b/src/models/EAFunds.re index 26f0beb1..b549ee37 100644 --- a/src/models/EAFunds.re +++ b/src/models/EAFunds.re @@ -158,7 +158,6 @@ module Model = { let genericDistribution = GenericDistribution.make( ~generationSource=GuesstimatorString(str), - ~probabilityType=Cdf, ~domain=Complete, ~unit=UnspecifiedDistribution, (), @@ -175,7 +174,6 @@ module Model = { GuesstimatorDist.logNormal(40., 4.), ), ), - ~probabilityType=Cdf, ~domain=RightLimited({xPoint: 100., excludingProbabilityMass: 0.3}), ~unit=TimeDistribution({zero: currentDateTime, unit: `years}), (), diff --git a/src/models/GlobalCatastrophe.re b/src/models/GlobalCatastrophe.re index 5be38fd7..072a4944 100644 --- a/src/models/GlobalCatastrophe.re +++ b/src/models/GlobalCatastrophe.re @@ -5,7 +5,6 @@ module Model = { let genericDistribution = GenericDistribution.make( ~generationSource=GuesstimatorString(guesstimatorString), - ~probabilityType=Cdf, ~unit=TimeDistribution({zero: currentDateTime, unit: `years}), (), );