Replaced GenericDistributionChart with ComplexPowerChart
This commit is contained in:
parent
cd1b114295
commit
0d32942110
|
@ -8,15 +8,16 @@ let timeDist =
|
||||||
~unit=TimeDistribution({zero: MomentRe.momentNow(), unit: `days}),
|
~unit=TimeDistribution({zero: MomentRe.momentNow(), unit: `days}),
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
|> GenericDistribution.renderIfNeeded(~sampleCount=1000);
|
|> GenericDistribution.toComplexPower(~sampleCount=1000);
|
||||||
|
|
||||||
let distributions = () =>
|
let distributions = () =>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
|
<h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
|
||||||
{timeDist
|
{timeDist
|
||||||
|> E.O.bind(_, GenericDistribution.normalize)
|
|> E.O.React.fmapOrNull(complexPower =>
|
||||||
|> E.O.React.fmapOrNull(dist => <GenericDistributionChart dist />)}
|
<ComplexPowerChart complexPower />
|
||||||
|
)}
|
||||||
<h2> {"Simple Continuous" |> ReasonReact.string} </h2>
|
<h2> {"Simple Continuous" |> ReasonReact.string} </h2>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
61
src/components/charts/ComplexPowerChart.re
Normal file
61
src/components/charts/ComplexPowerChart.re
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
module ComplexPowerChart = {
|
||||||
|
[@react.component]
|
||||||
|
let make = (~complexPower: DistributionTypes.complexPower, ~onHover) => {
|
||||||
|
open DistFunctor.ComplexPower;
|
||||||
|
let discrete = complexPower |> T.toDiscrete;
|
||||||
|
let continuous =
|
||||||
|
complexPower
|
||||||
|
|> T.toContinuous
|
||||||
|
|> E.O.fmap(DistFunctor.Continuous.getShape);
|
||||||
|
let minX = T.minX(complexPower);
|
||||||
|
let maxX = T.maxX(complexPower);
|
||||||
|
let timeScale =
|
||||||
|
complexPower.unit |> DistributionTypes.DistributionUnit.toJson;
|
||||||
|
<CdfChart__Plain
|
||||||
|
minX
|
||||||
|
maxX
|
||||||
|
?discrete
|
||||||
|
?continuous
|
||||||
|
color={`hex("333")}
|
||||||
|
onHover
|
||||||
|
timeScale
|
||||||
|
/>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
[@react.component]
|
||||||
|
let make = (~complexPower: DistributionTypes.complexPower) => {
|
||||||
|
let (x, setX) = React.useState(() => 0.);
|
||||||
|
let chart =
|
||||||
|
React.useMemo1(
|
||||||
|
() => {<ComplexPowerChart complexPower onHover={r => {setX(_ => r)}} />},
|
||||||
|
[|complexPower|],
|
||||||
|
);
|
||||||
|
<div>
|
||||||
|
chart
|
||||||
|
<table className="table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="px-4 py-2"> {"X Point" |> ReasonReact.string} </th>
|
||||||
|
<th className="px-4 py-2">
|
||||||
|
{"Y Integral to Point" |> ReasonReact.string}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th className="px-4 py-2 border ">
|
||||||
|
{x |> E.Float.toString |> ReasonReact.string}
|
||||||
|
</th>
|
||||||
|
<th className="px-4 py-2 border ">
|
||||||
|
{complexPower
|
||||||
|
|> DistFunctor.ComplexPower.T.Integral.xToY(~cache=None, x)
|
||||||
|
|> E.Float.with2DigitsPrecision
|
||||||
|
|> ReasonReact.string}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div />
|
||||||
|
</div>;
|
||||||
|
};
|
|
@ -1,77 +0,0 @@
|
||||||
module Shapee = {
|
|
||||||
[@react.component]
|
|
||||||
let make = (~shape: DistributionTypes.shape, ~timeScale, ~onHover) => {
|
|
||||||
<div
|
|
||||||
// let discrete = Shape.T.scaledDiscreteComponent(shape);
|
|
||||||
// let continuous = Shape.T.scaledContinuousComponent(shape);
|
|
||||||
// <div>
|
|
||||||
// <CdfChart__Plain
|
|
||||||
// minX={Shape.T.minX(shape)}
|
|
||||||
// maxX={Shape.T.maxX(shape)}
|
|
||||||
// ?discrete
|
|
||||||
// ?continuous
|
|
||||||
// color={`hex("333")}
|
|
||||||
// onHover
|
|
||||||
// timeScale
|
|
||||||
// />
|
|
||||||
// {discrete |> E.O.React.fmapOrNull(Shape.Discrete.render)}
|
|
||||||
// </div>;
|
|
||||||
/>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module GenericDist = {
|
|
||||||
[@react.component]
|
|
||||||
let make = (~genericDistribution: DistributionTypes.genericDistribution) => {
|
|
||||||
let (x, setX) = React.useState(() => 0.);
|
|
||||||
let timeScale =
|
|
||||||
genericDistribution.unit |> DistributionTypes.DistributionUnit.toJson;
|
|
||||||
let chart =
|
|
||||||
React.useMemo1(
|
|
||||||
() => {
|
|
||||||
genericDistribution
|
|
||||||
|> DistributionTypes.shapee
|
|
||||||
|> E.O.React.fmapOrNull(shape => {
|
|
||||||
<Shapee shape timeScale onHover={r => setX(_ => r)} />
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[|genericDistribution|],
|
|
||||||
);
|
|
||||||
<div>
|
|
||||||
chart
|
|
||||||
<table className="table-auto">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="px-4 py-2"> {"X Point" |> ReasonReact.string} </th>
|
|
||||||
<th className="px-4 py-2">
|
|
||||||
{"Y Integral to Point" |> ReasonReact.string}
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th className="px-4 py-2 border ">
|
|
||||||
{x |> E.Float.toString |> ReasonReact.string}
|
|
||||||
</th>
|
|
||||||
<th className="px-4 py-2 border ">
|
|
||||||
{genericDistribution->GenericDistribution.yIntegral(x)
|
|
||||||
|> E.O.fmap(E.Float.with2DigitsPrecision)
|
|
||||||
|> E.O.default("")
|
|
||||||
|> ReasonReact.string}
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div />
|
|
||||||
</div>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
[@react.component]
|
|
||||||
let make = (~dist) => {
|
|
||||||
switch ((dist: DistributionTypes.genericDistribution)) {
|
|
||||||
| {generationSource: Shape(_)} =>
|
|
||||||
<div> <GenericDist genericDistribution=dist /> </div>
|
|
||||||
| _ => <div />
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -324,7 +324,7 @@ module Shape = {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let maxX = (t: t) =>
|
let maxX = (t: t) =>
|
||||||
mapToAll(t, (Mixed.T.minX, Discrete.T.minX, Continuous.T.minX));
|
mapToAll(t, (Mixed.T.maxX, Discrete.T.maxX, Continuous.T.maxX));
|
||||||
let pointwiseFmap = (fn, t: t) =>
|
let pointwiseFmap = (fn, t: t) =>
|
||||||
fmap(
|
fmap(
|
||||||
t,
|
t,
|
||||||
|
@ -337,7 +337,36 @@ module Shape = {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module WithMetadata = {
|
module ComplexPower = {
|
||||||
|
open DistributionTypes;
|
||||||
|
let make =
|
||||||
|
(
|
||||||
|
~shape,
|
||||||
|
~guesstimatorString,
|
||||||
|
~domain=Complete,
|
||||||
|
~unit=UnspecifiedDistribution,
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
: complexPower => {
|
||||||
|
let integral = Shape.T.Integral.get(~cache=None, shape);
|
||||||
|
{shape, domain, integralCache: integral, unit, guesstimatorString};
|
||||||
|
};
|
||||||
|
let update =
|
||||||
|
(
|
||||||
|
~shape=?,
|
||||||
|
~integralCache=?,
|
||||||
|
~domain=?,
|
||||||
|
~unit=?,
|
||||||
|
~guesstimatorString=?,
|
||||||
|
t: complexPower,
|
||||||
|
) => {
|
||||||
|
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),
|
||||||
|
};
|
||||||
|
|
||||||
module T =
|
module T =
|
||||||
Dist({
|
Dist({
|
||||||
type t = DistributionTypes.complexPower;
|
type t = DistributionTypes.complexPower;
|
||||||
|
@ -350,7 +379,7 @@ module WithMetadata = {
|
||||||
let xToY = f => shapeFn(Shape.T.xToY(f));
|
let xToY = f => shapeFn(Shape.T.xToY(f));
|
||||||
let minX = shapeFn(Shape.T.minX);
|
let minX = shapeFn(Shape.T.minX);
|
||||||
let maxX = shapeFn(Shape.T.maxX);
|
let maxX = shapeFn(Shape.T.maxX);
|
||||||
let fromShape = (shape, t): t => DistributionTypes.update(~shape, t);
|
let fromShape = (shape, t): t => update(~shape, t);
|
||||||
// todo: adjust for limit
|
// todo: adjust for limit
|
||||||
let pointwiseFmap = (fn, {shape, _} as t: t): t =>
|
let pointwiseFmap = (fn, {shape, _} as t: t): t =>
|
||||||
fromShape(Shape.T.pointwiseFmap(fn, shape), t);
|
fromShape(Shape.T.pointwiseFmap(fn, shape), t);
|
||||||
|
|
|
@ -66,29 +66,12 @@ type genericDistribution = {
|
||||||
unit: distributionUnit,
|
unit: distributionUnit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let shapee = ({generationSource}: genericDistribution) =>
|
|
||||||
switch (generationSource) {
|
|
||||||
| GuesstimatorString(_) => None
|
|
||||||
| Shape(pointsType) => Some(pointsType)
|
|
||||||
};
|
|
||||||
|
|
||||||
type pdfCdfCombo = {
|
|
||||||
pdf: shape,
|
|
||||||
cdf: continuousShape,
|
|
||||||
};
|
|
||||||
|
|
||||||
type complexPower = {
|
type complexPower = {
|
||||||
shape,
|
shape,
|
||||||
|
domain,
|
||||||
integralCache: continuousShape,
|
integralCache: continuousShape,
|
||||||
domain: domainLimit,
|
|
||||||
unit: distributionUnit,
|
unit: distributionUnit,
|
||||||
};
|
guesstimatorString: option(string),
|
||||||
|
|
||||||
let update = (~shape=?, ~integralCache=?, ~domain=?, ~unit=?, t: complexPower) => {
|
|
||||||
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),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module DistributionUnit = {
|
module DistributionUnit = {
|
||||||
|
@ -102,6 +85,34 @@ module DistributionUnit = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module Domain = {
|
||||||
|
let excludedProbabilityMass = (t: domain) => {
|
||||||
|
switch (t) {
|
||||||
|
| Complete => 1.0
|
||||||
|
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
||||||
|
| RightLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
||||||
|
| LeftAndRightLimited(
|
||||||
|
{excludingProbabilityMass: l},
|
||||||
|
{excludingProbabilityMass: r},
|
||||||
|
) =>
|
||||||
|
l +. r
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let initialProbabilityMass = (t: domain) => {
|
||||||
|
switch (t) {
|
||||||
|
| Complete
|
||||||
|
| RightLimited(_) => 0.0
|
||||||
|
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
||||||
|
| LeftAndRightLimited({excludingProbabilityMass}, _) => excludingProbabilityMass
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let normalizeProbabilityMass = (t: domain) => {
|
||||||
|
1. /. excludedProbabilityMass(t);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
type mixedPoint = {
|
type mixedPoint = {
|
||||||
continuous: float,
|
continuous: float,
|
||||||
discrete: float,
|
discrete: float,
|
||||||
|
|
|
@ -1,33 +1,5 @@
|
||||||
open DistributionTypes;
|
open DistributionTypes;
|
||||||
|
|
||||||
module Domain = {
|
|
||||||
let excludedProbabilityMass = (t: DistributionTypes.domain) => {
|
|
||||||
switch (t) {
|
|
||||||
| Complete => 1.0
|
|
||||||
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
|
||||||
| RightLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
|
||||||
| LeftAndRightLimited(
|
|
||||||
{excludingProbabilityMass: l},
|
|
||||||
{excludingProbabilityMass: r},
|
|
||||||
) =>
|
|
||||||
l +. r
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let initialProbabilityMass = (t: DistributionTypes.domain) => {
|
|
||||||
switch (t) {
|
|
||||||
| Complete
|
|
||||||
| RightLimited(_) => 0.0
|
|
||||||
| LeftLimited({excludingProbabilityMass}) => excludingProbabilityMass
|
|
||||||
| LeftAndRightLimited({excludingProbabilityMass}, _) => excludingProbabilityMass
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let normalizeProbabilityMass = (t: DistributionTypes.domain) => {
|
|
||||||
1. /. excludedProbabilityMass(t);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let make =
|
let make =
|
||||||
(
|
(
|
||||||
~generationSource,
|
~generationSource,
|
||||||
|
@ -43,51 +15,23 @@ let make =
|
||||||
unit,
|
unit,
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: The fact that it is a CDF is really something you find later, this can't be chosen until GuesstimatorToString happens.
|
let toComplexPower =
|
||||||
let renderIfNeeded =
|
(~sampleCount, t: genericDistribution): option(complexPower) => {
|
||||||
(~sampleCount=1000, t: genericDistribution): option(genericDistribution) => {
|
let shape =
|
||||||
switch (t.generationSource) {
|
switch (t.generationSource) {
|
||||||
| GuesstimatorString(s) =>
|
| GuesstimatorString(s) =>
|
||||||
Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ())
|
Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ())
|
||||||
|> E.O.bind(_, DistFunctor.Mixed.clean)
|
|> E.O.bind(_, DistFunctor.Mixed.clean)
|
||||||
|> E.O.fmap((shape: DistributionTypes.shape) =>
|
| Shape(shape) => Some(shape)
|
||||||
make(
|
};
|
||||||
~generationSource=Shape(shape),
|
shape
|
||||||
~probabilityType=Pdf,
|
|> E.O.fmap(shape =>
|
||||||
~domain=t.domain,
|
DistFunctor.ComplexPower.make(
|
||||||
~unit=t.unit,
|
~shape,
|
||||||
(),
|
~domain=t.domain,
|
||||||
)
|
~unit=t.unit,
|
||||||
|
~guesstimatorString=None,
|
||||||
|
(),
|
||||||
)
|
)
|
||||||
| Shape(_) => Some(t)
|
);
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let normalize = (t: genericDistribution): option(genericDistribution) => {
|
|
||||||
switch (t.generationSource) {
|
|
||||||
| Shape(shape) => Some({...t, generationSource: Shape(shape)})
|
|
||||||
| GuesstimatorString(_) => Some(t)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let yIntegral = (t: DistributionTypes.genericDistribution, x) => {
|
|
||||||
switch (t) {
|
|
||||||
| {generationSource: Shape(shape)} =>
|
|
||||||
Some(DistFunctor.Shape.T.Integral.xToY(~cache=None, x, shape))
|
|
||||||
| _ => None
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: This obviously needs to be fleshed out a lot.
|
|
||||||
let integrate = (t: DistributionTypes.genericDistribution) => {
|
|
||||||
switch (t) {
|
|
||||||
| {probabilityType: Pdf, generationSource: Shape(shape), domain, unit} =>
|
|
||||||
Some({
|
|
||||||
generationSource: Shape(shape),
|
|
||||||
probabilityType: Pdf,
|
|
||||||
domain,
|
|
||||||
unit,
|
|
||||||
})
|
|
||||||
| _ => None
|
|
||||||
};
|
|
||||||
};
|
};
|
|
@ -1,297 +0,0 @@
|
||||||
open DistributionTypes;
|
|
||||||
|
|
||||||
type pointInRange =
|
|
||||||
| Unbounded
|
|
||||||
| X(float);
|
|
||||||
|
|
||||||
module Continuous = {
|
|
||||||
type t = continuousShape;
|
|
||||||
let xyShape = (t: t) => t.xyShape;
|
|
||||||
let getShape = (t: t) => t.xyShape;
|
|
||||||
let interpolation = (t: t) => t.interpolation;
|
|
||||||
let make = (xyShape, interpolation): t => {xyShape, interpolation};
|
|
||||||
let fromShape = xyShape => make(xyShape, `Linear);
|
|
||||||
let shapeMap = (fn, {xyShape, interpolation}: t): t => {
|
|
||||||
xyShape: fn(xyShape),
|
|
||||||
interpolation,
|
|
||||||
};
|
|
||||||
let oShapeMap =
|
|
||||||
(fn, {xyShape, interpolation}: t)
|
|
||||||
: option(DistributionTypes.continuousShape) =>
|
|
||||||
fn(xyShape) |> E.O.fmap(xyShape => make(xyShape, interpolation));
|
|
||||||
let shapeFn = (fn, t: t) => t |> xyShape |> fn;
|
|
||||||
let minX = shapeFn(XYShape.minX);
|
|
||||||
let maxX = shapeFn(XYShape.maxX);
|
|
||||||
let findX = y => shapeFn(CdfLibrary.Distribution.findX(y));
|
|
||||||
let findY = x => shapeFn(CdfLibrary.Distribution.findY(x));
|
|
||||||
let toJs = shapeFn(XYShape.toJs);
|
|
||||||
let fromArrays = (a, b) => make(XYShape.fromArrays(a, b), `Linear);
|
|
||||||
let toPdf = (t: t) => t |> oShapeMap(XYShape.Range.derivative);
|
|
||||||
let toCdf = (t: t) => t |> oShapeMap(XYShape.Range.integrateWithTriangles);
|
|
||||||
let findIntegralY = (f, t) => {
|
|
||||||
t
|
|
||||||
|> toCdf
|
|
||||||
|> E.O.fmap(xyShape)
|
|
||||||
|> E.O.fmap(CdfLibrary.Distribution.findY(f));
|
|
||||||
};
|
|
||||||
let normalizeCdf = (continuousShape: continuousShape) =>
|
|
||||||
continuousShape
|
|
||||||
|> xyShape
|
|
||||||
|> XYShape.scaleCdfTo(~scaleTo=1.0)
|
|
||||||
|> fromShape;
|
|
||||||
let scalePdf = (~scaleTo=1.0, continuousShape: continuousShape) => {
|
|
||||||
switch (toCdf(continuousShape)) {
|
|
||||||
| Some({xyShape}) =>
|
|
||||||
XYShape.scaleCdfTo(~scaleTo, xyShape)
|
|
||||||
|> XYShape.Range.derivative
|
|
||||||
|> E.O.fmap(fromShape)
|
|
||||||
| _ => None
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module Discrete = {
|
|
||||||
let minX = XYShape.minX;
|
|
||||||
let maxX = XYShape.maxX;
|
|
||||||
type t = discreteShape;
|
|
||||||
let fromArrays = XYShape.fromArrays;
|
|
||||||
let toJs = XYShape.toJs;
|
|
||||||
let ySum = XYShape.ySum;
|
|
||||||
let zip = t => Belt.Array.zip(t.xs, t.ys);
|
|
||||||
let pointwiseMap = (t: discreteShape, fn): discreteShape => {
|
|
||||||
xs: t.xs,
|
|
||||||
ys: t.ys |> E.A.fmap(fn),
|
|
||||||
};
|
|
||||||
|
|
||||||
let scaleYToTotal = (totalDesired, t: t): t => {
|
|
||||||
let difference = totalDesired /. ySum(t);
|
|
||||||
XYShape.fmap(t, y => y *. difference);
|
|
||||||
};
|
|
||||||
|
|
||||||
let render = (t: t) =>
|
|
||||||
Belt.Array.zip(t.xs, t.ys)
|
|
||||||
|> E.A.fmap(((x, y)) =>
|
|
||||||
<div>
|
|
||||||
{E.Float.toFixed(x)
|
|
||||||
++ "---"
|
|
||||||
++ E.Float.with3DigitsPrecision(y *. 100.)
|
|
||||||
|> ReasonReact.string}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|> ReasonReact.array;
|
|
||||||
|
|
||||||
let integrate = t => t |> XYShape.accumulateYs |> Continuous.fromShape;
|
|
||||||
let derivative = XYShape.subtractYs;
|
|
||||||
|
|
||||||
// TODO: This has a clear bug where it returns the Y value of the first item,
|
|
||||||
// even if X is less than the X of the first item.
|
|
||||||
// It has a second bug that it assumes things are triangular, instead of interpolating via steps.
|
|
||||||
let findIntegralY = (f, t: t) => {
|
|
||||||
t |> XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
|
|
||||||
};
|
|
||||||
|
|
||||||
let findY = (f, t: t) => {
|
|
||||||
Belt.Array.zip(t.xs, t.ys)
|
|
||||||
|> E.A.getBy(_, ((x, _)) => x == f)
|
|
||||||
|> E.O.fmap(((_, y)) => y)
|
|
||||||
|> E.O.default(0.);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let min = (f1: option(float), f2: option(float)) =>
|
|
||||||
switch (f1, f2) {
|
|
||||||
| (Some(f1), Some(f2)) => Some(f1 < f2 ? f1 : f2)
|
|
||||||
| (Some(f1), None) => Some(f1)
|
|
||||||
| (None, Some(f2)) => Some(f2)
|
|
||||||
| (None, None) => None
|
|
||||||
};
|
|
||||||
|
|
||||||
let max = (f1: option(float), f2: option(float)) =>
|
|
||||||
switch (f1, f2) {
|
|
||||||
| (Some(f1), Some(f2)) => Some(f1 > f2 ? f1 : f2)
|
|
||||||
| (Some(f1), None) => Some(f1)
|
|
||||||
| (None, Some(f2)) => Some(f2)
|
|
||||||
| (None, None) => None
|
|
||||||
};
|
|
||||||
|
|
||||||
module Mixed = {
|
|
||||||
// let make = (~continuous, ~discrete, ~discreteProbabilityMassFraction) => {
|
|
||||||
// continuous,
|
|
||||||
// discrete,
|
|
||||||
// discreteProbabilityMassFraction,
|
|
||||||
// };
|
|
||||||
|
|
||||||
let minX = (t: DistributionTypes.mixedShape) =>
|
|
||||||
min(t.continuous |> Continuous.minX, t.discrete |> Discrete.minX);
|
|
||||||
|
|
||||||
let maxX = (t: DistributionTypes.mixedShape) => {
|
|
||||||
max(t.continuous |> Continuous.maxX, t.discrete |> Discrete.maxX);
|
|
||||||
};
|
|
||||||
|
|
||||||
let mixedMultiply =
|
|
||||||
(
|
|
||||||
t: DistributionTypes.mixedShape,
|
|
||||||
continuousComponent,
|
|
||||||
discreteComponent,
|
|
||||||
) => {
|
|
||||||
let diffFn = t.discreteProbabilityMassFraction;
|
|
||||||
continuousComponent *. (1.0 -. diffFn) +. discreteComponent *. diffFn;
|
|
||||||
};
|
|
||||||
|
|
||||||
type yPdfPoint = {
|
|
||||||
continuous: option(float),
|
|
||||||
discrete: option(float),
|
|
||||||
};
|
|
||||||
|
|
||||||
let findY = (t: DistributionTypes.mixedShape, x: float): yPdfPoint => {
|
|
||||||
continuous:
|
|
||||||
Continuous.findY(x, t.continuous)
|
|
||||||
|> (e => e *. (1. -. t.discreteProbabilityMassFraction))
|
|
||||||
|> E.O.some,
|
|
||||||
discrete:
|
|
||||||
Discrete.findY(x, t.discrete)
|
|
||||||
|> (e => e *. t.discreteProbabilityMassFraction)
|
|
||||||
|> E.O.some,
|
|
||||||
};
|
|
||||||
|
|
||||||
let findYIntegral =
|
|
||||||
(x: float, t: DistributionTypes.mixedShape): option(float) => {
|
|
||||||
let c = t.continuous |> Continuous.findIntegralY(x);
|
|
||||||
let d = Discrete.findIntegralY(x, t.discrete);
|
|
||||||
switch (c, d) {
|
|
||||||
| (Some(c), d) => Some(mixedMultiply(t, c, d))
|
|
||||||
| _ => None
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} /* }*/;
|
|
||||||
|
|
||||||
// module T = {
|
|
||||||
// type t = DistributionTypes.shape;
|
|
||||||
|
|
||||||
// let y = (t: t, x: float) =>
|
|
||||||
// switch (t) {
|
|
||||||
// | Mixed(m) => `mixed(Mixed.findY(m, x))
|
|
||||||
// | Discrete(discreteShape) => `discrete(Discrete.findY(x, discreteShape))
|
|
||||||
// | Continuous(continuousShape) =>
|
|
||||||
// `continuous(Continuous.findY(x, continuousShape))
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let yIntegral = (t: t, x: float) =>
|
|
||||||
// switch (t) {
|
|
||||||
// | Mixed(m) => Mixed.findYIntegral(x, m)
|
|
||||||
// | Discrete(discreteShape) =>
|
|
||||||
// Discrete.findIntegralY(x, discreteShape) |> E.O.some
|
|
||||||
// | Continuous(continuousShape) =>
|
|
||||||
// Continuous.findIntegralY(x, continuousShape)
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let minX = (t: t) =>
|
|
||||||
// switch (t) {
|
|
||||||
// | Mixed(m) => Mixed.minX(m)
|
|
||||||
// | Discrete(discreteShape) => Discrete.minX(discreteShape)
|
|
||||||
// | Continuous(continuousShape) => Continuous.minX(continuousShape)
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let maxX = (t: t) =>
|
|
||||||
// switch (t) {
|
|
||||||
// | Mixed(m) => Mixed.maxX(m)
|
|
||||||
// | Discrete(discreteShape) => Discrete.maxX(discreteShape)
|
|
||||||
// | Continuous(continuousShape) => Continuous.maxX(continuousShape)
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let discreteComponent = (t: t) =>
|
|
||||||
// switch (t) {
|
|
||||||
// | Mixed({discrete}) => Some(discrete)
|
|
||||||
// | Discrete(d) => Some(d)
|
|
||||||
// | Continuous(_) => None
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let continuousComponent = (t: t) =>
|
|
||||||
// switch (t) {
|
|
||||||
// | Mixed({continuous}) => Some(continuous)
|
|
||||||
// | Continuous(c) => Some(c)
|
|
||||||
// | Discrete(_) => None
|
|
||||||
// };
|
|
||||||
// // let scaledContinuousComponent = (t: t): option(continuousShape) => {
|
|
||||||
// // switch (t) {
|
|
||||||
// // | Mixed({continuous, discreteProbabilityMassFraction}) =>
|
|
||||||
// // Continuous.scalePdf(
|
|
||||||
// // ~scaleTo=1.0 -. discreteProbabilityMassFraction,
|
|
||||||
// // continuous,
|
|
||||||
// // )
|
|
||||||
// // | Discrete(_) => None
|
|
||||||
// // | Continuous(c) => Some(c)
|
|
||||||
// // };
|
|
||||||
// // };
|
|
||||||
// // let scaledDiscreteComponent = (t: t): option(discreteShape) => {
|
|
||||||
// // switch (t) {
|
|
||||||
// // | Mixed({discrete, discreteProbabilityMassFraction}) =>
|
|
||||||
// // Some(Discrete.scaleYToTotal(discreteProbabilityMassFraction, discrete))
|
|
||||||
// // | Discrete(d) => Some(d)
|
|
||||||
// // | Continuous(_) => None
|
|
||||||
// // };
|
|
||||||
// // };
|
|
||||||
// // let pointwiseFmap = (fn, t: t): shape =>
|
|
||||||
// // switch (t) {
|
|
||||||
// // | Mixed({discrete, continuous, discreteProbabilityMassFraction}) =>
|
|
||||||
// // Mixed({
|
|
||||||
// // continuous: XYShape.pointwiseMap(fn, continuous),
|
|
||||||
// // discrete: XYShape.pointwiseMap(fn, discrete),
|
|
||||||
// // discreteProbabilityMassFraction,
|
|
||||||
// // })
|
|
||||||
// // | Discrete(x) => Discrete(XYShape.pointwiseMap(fn, x))
|
|
||||||
// // | Continuous(x) => Continuous(XYShape.pointwiseMap(fn, x))
|
|
||||||
// // };
|
|
||||||
// // module Cdf = {
|
|
||||||
// // let normalizeCdf = (t: DistributionTypes.shape) => {
|
|
||||||
// // switch (t) {
|
|
||||||
// // | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
|
|
||||||
// // Mixed({
|
|
||||||
// // continuous: continuous |> Continuous.normalizeCdf,
|
|
||||||
// // discrete: discrete |> Discrete.scaleYToTotal(1.0),
|
|
||||||
// // discreteProbabilityMassFraction,
|
|
||||||
// // })
|
|
||||||
// // | Discrete(d) => Discrete(d |> Discrete.scaleYToTotal(1.0))
|
|
||||||
// // | Continuous(continuousShape) =>
|
|
||||||
// // Continuous(Continuous.normalizeCdf(continuousShape))
|
|
||||||
// // };
|
|
||||||
// // };
|
|
||||||
// // };
|
|
||||||
// };
|
|
||||||
|
|
||||||
// module PdfCdfShape = {
|
|
||||||
// type t = pdfCdfCombo;
|
|
||||||
// let pdf = (t: t) =>
|
|
||||||
// switch (t.pdf) {
|
|
||||||
// | Mixed(pdf) => Mixed(pdf)
|
|
||||||
// | Discrete(pdf) => Discrete(pdf)
|
|
||||||
// | Continuous(pdf) => Continuous(pdf)
|
|
||||||
// };
|
|
||||||
// let cdf = (t: t) => t.cdf;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// type distributionUnit =
|
|
||||||
// | UnspecifiedDistribution
|
|
||||||
// | TimeDistribution(TimeTypes.timeVector);
|
|
||||||
|
|
||||||
// type withLimitedDomain = {
|
|
||||||
// domain,
|
|
||||||
// dist: pdfCdfCombo,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// module WithLimitedDomain = {
|
|
||||||
// type t = withLimitedDomain;
|
|
||||||
// let dist = (t: t) => t.dist;
|
|
||||||
// let pdf = (t: t) => PdfCdfShape.pdf(t.dist);
|
|
||||||
// let cdf = (t: t) => PdfCdfShape.cdf(t.dist);
|
|
||||||
// // TODO: This is bad, obviously needs to be fixed.
|
|
||||||
// let distScaleFactor = (t: t) => 3.0;
|
|
||||||
// // let scaledPdfShape = (scaleFactor, t: t) =>
|
|
||||||
// // t |> pdf |> T.pointwiseFmap(r => r *. scaleFactor);
|
|
||||||
// // let scaledCdfShape = (scaleFactor, t: t) =>
|
|
||||||
// // t |> cdf |> XYShape.pointwiseMap(r => r *. scaleFactor);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// type withTimeVector = {
|
|
||||||
// timeVector: TimeTypes.timeVector,
|
|
||||||
// dist: withLimitedDomain,
|
|
|
@ -19,15 +19,11 @@ let propValue = (t: Prop.Value.t) => {
|
||||||
| ConditionalArray(r) => "Array" |> ReasonReact.string
|
| ConditionalArray(r) => "Array" |> ReasonReact.string
|
||||||
| GenericDistribution(r) =>
|
| GenericDistribution(r) =>
|
||||||
let newDistribution =
|
let newDistribution =
|
||||||
GenericDistribution.renderIfNeeded(~sampleCount=2000, r);
|
GenericDistribution.toComplexPower(~sampleCount=1000, r);
|
||||||
switch (newDistribution) {
|
switch (newDistribution) {
|
||||||
| Some(distribution) =>
|
| Some(distribution) =>
|
||||||
<div>
|
<div> <ComplexPowerChart complexPower=distribution /> </div>
|
||||||
{GenericDistribution.normalize(distribution)
|
|
||||||
|> E.O.React.fmapOrNull(dist => <GenericDistributionChart dist />)}
|
|
||||||
</div>
|
|
||||||
| None => "Something went wrong" |> ReasonReact.string
|
| None => "Something went wrong" |> ReasonReact.string
|
||||||
| _ => <div />
|
|
||||||
};
|
};
|
||||||
| FloatCdf(_) => <div />
|
| FloatCdf(_) => <div />
|
||||||
| Probability(r) =>
|
| Probability(r) =>
|
||||||
|
|
|
@ -112,12 +112,11 @@ module Model = {
|
||||||
let model = GlobalCatastrophe.Model.make(dateTime);
|
let model = GlobalCatastrophe.Model.make(dateTime);
|
||||||
switch (model) {
|
switch (model) {
|
||||||
| Prop.Value.GenericDistribution(genericDistribution) =>
|
| Prop.Value.GenericDistribution(genericDistribution) =>
|
||||||
GenericDistribution.renderIfNeeded(
|
genericDistribution
|
||||||
~sampleCount=1000,
|
|> GenericDistribution.toComplexPower(~sampleCount=1000)
|
||||||
genericDistribution,
|
|> E.O.fmap(
|
||||||
)
|
DistFunctor.ComplexPower.T.Integral.xToY(~cache=None, 18.0),
|
||||||
|> E.O.bind(_, GenericDistribution.normalize)
|
)
|
||||||
|> E.O.bind(_, GenericDistribution.yIntegral(_, 18.0))
|
|
||||||
| _ => None
|
| _ => None
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,9 @@ module Internals = {
|
||||||
};
|
};
|
||||||
|
|
||||||
let toContinous = (r: combined) =>
|
let toContinous = (r: combined) =>
|
||||||
continuousGet(r) |> CdfLibrary.JS.jsToDist |> Shape.Continuous.fromShape;
|
continuousGet(r)
|
||||||
|
|> CdfLibrary.JS.jsToDist
|
||||||
|
|> DistFunctor.Continuous.fromShape;
|
||||||
|
|
||||||
let toDiscrete = (r: combined): DistributionTypes.xyShape =>
|
let toDiscrete = (r: combined): DistributionTypes.xyShape =>
|
||||||
discreteGet(r) |> jsToDistDiscrete;
|
discreteGet(r) |> jsToDistDiscrete;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user