From 320ed0d47735018ed15bb309117723693f051e3d Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 14 Feb 2020 21:53:47 +0000 Subject: [PATCH] Show graph of TimeLimitedDomainCdf --- src/LimitedDomainCdf.re | 2 + src/TimeLimitedDomainCdf.re | 121 ++++++++++++++++++++------------ src/lib/Prop.re | 5 ++ src/models/GlobalCatastrophe.re | 49 ++++--------- 4 files changed, 96 insertions(+), 81 deletions(-) diff --git a/src/LimitedDomainCdf.re b/src/LimitedDomainCdf.re index fad1d421..9cf7d18f 100644 --- a/src/LimitedDomainCdf.re +++ b/src/LimitedDomainCdf.re @@ -3,6 +3,8 @@ type t = { domainMaxX: float, }; +let make = (~distribution, ~domainMaxX): t => {distribution, domainMaxX}; + let fromCdf = (cdf: Types.cdf, domainMaxX: float, probabilityAtMaxX: float) => { let distribution: Types.distribution = { xs: cdf.xs, diff --git a/src/TimeLimitedDomainCdf.re b/src/TimeLimitedDomainCdf.re index 152497a9..78aee494 100644 --- a/src/TimeLimitedDomainCdf.re +++ b/src/TimeLimitedDomainCdf.re @@ -10,45 +10,75 @@ type timeUnit = [ | `years ]; +type timeVector = { + zero: MomentRe.Moment.t, + unit: timeUnit, +}; + +type timePoint = { + timeVector, + value: float, +}; + +module TimePoint = { + let fromTimeVector = (timeVector, value): timePoint => {timeVector, value}; + + let toMoment = (timePoint: timePoint) => { + timePoint.timeVector.zero + |> MomentRe.Moment.add( + ~duration= + MomentRe.duration(timePoint.value, timePoint.timeVector.unit), + ); + }; + + let fromMoment = (timeVector: timeVector, moment: MomentRe.Moment.t) => + MomentRe.diff(timeVector.zero, moment, timeVector.unit); +}; + +module RelativeTimePoint = { + type timeInVector = + | Time(MomentRe.Moment.t) + | XValue(float); + + let toTime = (timeVector: timeVector, timeInVector: timeInVector) => + switch (timeInVector) { + | Time(r) => r + | XValue(r) => + timeVector.zero + |> MomentRe.Moment.add(~duration=MomentRe.duration(r, timeVector.unit)) + }; + + let _timeToX = (time, timeStart, timeUnit) => + MomentRe.diff(timeStart, time, timeUnit); + + let toXValue = (timeVector: timeVector, timeInVector: timeInVector) => + switch (timeInVector) { + | Time(r) => _timeToX(r, timeVector.zero, timeVector.unit) + | XValue(r) => r + }; +}; + type t = { - timeUnit, - timeStart: MomentRe.Moment.t, + timeVector, limitedDomainCdf: LimitedDomainCdf.t, }; -module XSpecification = { - type xSpecification = - | Time(MomentRe.Moment.t) - | DifferenceFromStart(float, timeUnit) - | CdfXCoordinate(float); - - let toTime = (t: t, xSpecification: xSpecification) => - switch (xSpecification) { - | Time(r) => r - | DifferenceFromStart(r, unit) => - t.timeStart - |> MomentRe.Moment.add(~duration=MomentRe.duration(r, unit)) - | CdfXCoordinate(r) => - t.timeStart - |> MomentRe.Moment.add(~duration=MomentRe.duration(r, t.timeUnit)) +let make = + ( + ~timeVector: timeVector, + ~distribution: Types.distribution, + ~probabilityAtMaxX: float, + ~maxX: [ | `time(MomentRe.Moment.t) | `x(float)], + ) + : t => { + let domainMaxX = + switch (maxX) { + | `time(m) => TimePoint.fromMoment(timeVector, m) + | `x(r) => r }; - - let rec toCdfXCoordinate = (t: t, xSpecification: xSpecification) => - switch (xSpecification) { - | Time(r) => MomentRe.diff(t.timeStart, r, t.timeUnit) - | DifferenceFromStart(r, unit) => - let newTime = toTime(t, DifferenceFromStart(r, unit)); - toCdfXCoordinate(t, Time(newTime)); - | CdfXCoordinate(r) => r - }; - - let fromDifference = (~t: t, ~duration: float, ~unit=t.timeUnit, ()) => - Time( - MomentRe.Moment.add( - ~duration=MomentRe.duration(duration, unit), - t.timeStart, - ), - ); + let limitedDomainCdf = + LimitedDomainCdf.fromCdf(distribution, domainMaxX, probabilityAtMaxX); + {timeVector, limitedDomainCdf}; }; let probabilityBeforeDomainMax = (t: t) => @@ -57,18 +87,19 @@ let probabilityBeforeDomainMax = (t: t) => let domainMaxX = (t: t) => LimitedDomainCdf.probabilityBeforeDomainMax(t.limitedDomainCdf); -let probability = (t: t, x: XSpecification.xSpecification) => - LimitedDomainCdf.probability( - t.limitedDomainCdf, - XSpecification.toCdfXCoordinate(t, x), - ); +let probability = (t: t, m: MomentRe.Moment.t) => { + RelativeTimePoint.toXValue(t.timeVector, Time(m)) + |> LimitedDomainCdf.probability(t.limitedDomainCdf); +}; let probabilityInverse = (t: t, y: float) => - XSpecification.CdfXCoordinate( - LimitedDomainCdf.probabilityInverse(t.limitedDomainCdf, y), - ); + LimitedDomainCdf.probabilityInverse(t.limitedDomainCdf, y) + |> (r => RelativeTimePoint.toTime(t.timeVector, XValue(r))); + +let cumulativeProbability = (t: t, m: MomentRe.Moment.t) => + RelativeTimePoint.toXValue(t.timeVector, Time(m)) + |> LimitedDomainCdf.cumulativeProbability(t.limitedDomainCdf); let cumulativeProbabilityInverse = (t: t, y: float) => - XSpecification.CdfXCoordinate( - LimitedDomainCdf.cumulativeProbabilityInverse(t.limitedDomainCdf, y), - ); \ No newline at end of file + LimitedDomainCdf.cumulativeProbabilityInverse(t.limitedDomainCdf, y) + |> (r => RelativeTimePoint.toTime(t.timeVector, XValue(r))); \ No newline at end of file diff --git a/src/lib/Prop.re b/src/lib/Prop.re index 9e0929f4..187511e0 100644 --- a/src/lib/Prop.re +++ b/src/lib/Prop.re @@ -15,6 +15,7 @@ module Value = { | FloatPoint(float) | Probability(float) | Conditional(conditional) + | TimeLimitedDomainCdf(TimeLimitedDomainCdf.t) | ConditionalArray(array(conditional)) | FloatCdf(string); @@ -27,6 +28,7 @@ module Value = { } | SelectSingle(r) => r | FloatCdf(r) => r + | TimeLimitedDomainCdf(_) => "" | Probability(r) => (r *. 100. |> Js.Float.toFixed) ++ "%" | DateTime(r) => r |> MomentRe.Moment.defaultFormat | FloatPoint(r) => r |> Js.Float.toFixed @@ -49,6 +51,9 @@ module Value = { | SelectSingle(r) => r |> ReasonReact.string | ConditionalArray(r) => "Array" |> ReasonReact.string | Conditional(r) => r.name |> ReasonReact.string + | TimeLimitedDomainCdf(r) => + let cdf: Types.distribution = r.limitedDomainCdf.distribution; + <> Types.toJs} /> ; | FloatCdf(r) => let cdf: Types.distribution = CdfLibrary.Distribution.fromString(r, 2000); diff --git a/src/models/GlobalCatastrophe.re b/src/models/GlobalCatastrophe.re index 6c843644..7d901424 100644 --- a/src/models/GlobalCatastrophe.re +++ b/src/models/GlobalCatastrophe.re @@ -1,7 +1,15 @@ module Model = { - let make = (dateTime: MomentRe.Moment.t, currentDateTime: MomentRe.Moment.t) => { - let yearDiff = MomentRe.diff(dateTime, currentDateTime, `days) /. 365.; - Prop.Value.Probability(0.001 *. yearDiff); + let make = (currentDateTime: MomentRe.Moment.t) => { + let yearsFromNow = "normal(50,30)"; + let dist = CdfLibrary.Distribution.fromString(yearsFromNow, 1000); + let timeLimitedDomain = + TimeLimitedDomainCdf.make( + ~timeVector={zero: currentDateTime, unit: `years}, + ~distribution=dist, + ~probabilityAtMaxX=0.7, + ~maxX=`x(200.), + ); + Prop.Value.TimeLimitedDomainCdf(timeLimitedDomain); }; }; @@ -10,8 +18,7 @@ module Interface = { let run = (p: Prop.Combo.t) => { switch (Prop.Combo.InputValues.toValueArray(p)) { - | [|Some(DateTime(intendedYear)), Some(DateTime(currentYear))|] => - Some(Model.make(intendedYear, currentYear)) + | [|Some(DateTime(currentYear))|] => Some(Model.make(currentYear)) | _ => None }; }; @@ -22,37 +29,7 @@ module Interface = { description: "The chances of having at least one catastrophe per year in the future, assuming no other catastrophe until then.", version: "1.0.0", author: "Ozzie Gooen", - inputTypes: [| - TypeWithMetadata.make( - ~name=dayKey, - ~type_= - DateTime({ - default: - Some( - MomentRe.Moment.add( - ~duration=MomentRe.duration(5., `years), - MomentRe.momentNow(), - ), - ), - min: - Some( - MomentRe.Moment.subtract( - ~duration=MomentRe.duration(20., `years), - MomentRe.momentNow(), - ), - ), - max: - Some( - MomentRe.Moment.add( - ~duration=MomentRe.duration(20., `years), - MomentRe.momentNow(), - ), - ), - }), - (), - ), - TypeWithMetadata.currentYear, - |], + inputTypes: [|TypeWithMetadata.currentYear|], outputTypes: [||], run, };