2020-02-21 23:42:15 +00:00
module type dist = {
type t ;
2020-03-18 20:50:01 +00:00
type integral ;
2020-03-28 21:29:02 +00:00
let minX : t = > float ;
let maxX : t = > float ;
2020-03-28 14:17:47 +00:00
let mapY : ( float = > float , t ) = > t ;
2020-02-23 13:27:52 +00:00
let xToY : ( float , t ) = > DistTypes . mixedPoint ;
let toShape : t = > DistTypes . shape ;
let toContinuous : t = > option ( DistTypes . continuousShape ) ;
let toDiscrete : t = > option ( DistTypes . discreteShape ) ;
let toScaledContinuous : t = > option ( DistTypes . continuousShape ) ;
let toScaledDiscrete : t = > option ( DistTypes . discreteShape ) ;
2020-02-26 10:08:37 +00:00
let toDiscreteProbabilityMass : t = > float ;
2020-03-18 20:50:01 +00:00
let truncate : ( ~ cache : option ( integral ) = ? , int , t ) = > t ;
2020-02-22 10:17:51 +00:00
2020-02-22 10:10:10 +00:00
let integral : ( ~ cache : option ( integral ) , t ) = > integral ;
2020-02-24 21:01:29 +00:00
let integralEndY : ( ~ cache : option ( integral ) , t ) = > float ;
2020-02-22 10:17:51 +00:00
let integralXtoY : ( ~ cache : option ( integral ) , float , t ) = > float ;
2020-03-14 18:33:39 +00:00
let integralYtoX : ( ~ cache : option ( integral ) , float , t ) = > float ;
2020-04-18 21:20:59 +00:00
let getMean : t = > float ;
let getVariance : t = > float ;
2020-02-21 23:42:15 +00:00
} ;
module Dist = ( T : dist ) = > {
type t = T . t ;
type integral = T . integral ;
let minX = T . minX ;
let maxX = T . maxX ;
2020-04-11 13:22:13 +00:00
let integral = T . integral ;
2020-03-28 21:29:02 +00:00
let xTotalRange = ( t : t ) = > maxX ( t ) -. minX ( t ) ;
2020-03-28 14:17:47 +00:00
let mapY = T . mapY ;
2020-02-21 23:42:15 +00:00
let xToY = T . xToY ;
2020-03-15 00:30:18 +00:00
let truncate = T . truncate ;
2020-02-22 16:24:54 +00:00
let toShape = T . toShape ;
2020-02-26 10:08:37 +00:00
let toDiscreteProbabilityMass = T . toDiscreteProbabilityMass ;
2020-02-22 16:24:54 +00:00
let toContinuous = T . toContinuous ;
let toDiscrete = T . toDiscrete ;
2020-02-22 21:46:49 +00:00
let toScaledContinuous = T . toScaledContinuous ;
let toScaledDiscrete = T . toScaledDiscrete ;
2020-04-18 21:20:59 +00:00
let getMean = T . getMean ;
let getVariance = T . getVariance ;
2020-03-18 21:46:43 +00:00
// TODO: Move this to each class, have use integral to produce integral in DistPlus class.
2020-03-28 14:17:47 +00:00
let scaleBy = ( ~ scale = 1 . 0 , t : t ) = > t | > mapY ( ( r : float ) = > r * . scale ) ;
2020-02-22 10:17:51 +00:00
module Integral = {
type t = T . integral ;
let get = T . integral ;
let xToY = T . integralXtoY ;
2020-03-14 18:33:39 +00:00
let yToX = T . integralYtoX ;
2020-02-24 21:01:29 +00:00
let sum = T . integralEndY ;
2020-02-22 10:17:51 +00:00
} ;
2020-02-22 19:21:04 +00:00
2020-02-23 20:50:27 +00:00
// This is suboptimal because it could get the cache but doesn't here.
2020-03-18 21:46:43 +00:00
let scaleToIntegralSum =
( ~ cache : option ( integral ) = None , ~ intendedSum = 1 . 0 , t : t ) = > {
let scale = intendedSum /. Integral . sum ( ~ cache , t ) ;
2020-02-22 19:21:04 +00:00
scaleBy ( ~ scale , t ) ;
} ;
2020-02-21 23:42:15 +00:00
} ;
2020-02-22 16:24:54 +00:00
module Continuous = {
2020-02-23 13:27:52 +00:00
type t = DistTypes . continuousShape ;
2020-02-22 16:24:54 +00:00
let getShape = ( t : t ) = > t . xyShape ;
let interpolation = ( t : t ) = > t . interpolation ;
2020-03-28 21:46:17 +00:00
let make = ( interpolation , xyShape ) : t = > { xyShape , interpolation } ;
2020-02-22 16:24:54 +00:00
let shapeMap = ( fn , { xyShape , interpolation } : t ) : t = > {
xyShape : fn ( xyShape ) ,
interpolation ,
} ;
2020-03-28 21:29:02 +00:00
let lastY = ( t : t ) = > t | > getShape | > XYShape . T . lastY ;
2020-02-22 16:24:54 +00:00
let oShapeMap =
2020-02-23 13:27:52 +00:00
( fn , { xyShape , interpolation } : t ) : option ( DistTypes . continuousShape ) = >
2020-03-28 21:46:17 +00:00
fn ( xyShape ) | > E . O . fmap ( make ( interpolation ) ) ;
2020-02-21 23:42:15 +00:00
2020-02-24 21:01:29 +00:00
let toLinear = ( t : t ) : option ( t ) = > {
2020-02-22 23:55:43 +00:00
switch ( t ) {
2020-02-24 21:01:29 +00:00
| { interpolation : ` Stepwise , xyShape } = >
2020-03-28 21:46:17 +00:00
xyShape | > XYShape . Range . stepsToContinuous | > E . O . fmap ( make ( ` Linear ) )
2020-02-24 21:01:29 +00:00
| { interpolation : ` Linear , _ } = > Some ( t )
2020-02-22 23:55:43 +00:00
} ;
2020-02-24 21:01:29 +00:00
} ;
2020-03-28 21:29:02 +00:00
let shapeFn = ( fn , t : t ) = > t | > getShape | > fn ;
2020-02-24 21:01:29 +00:00
2020-02-22 16:24:54 +00:00
module T =
Dist ( {
2020-02-23 13:27:52 +00:00
type t = DistTypes . continuousShape ;
type integral = DistTypes . continuousShape ;
2020-03-28 21:46:17 +00:00
let minX = shapeFn ( XYShape . T . minX ) ;
let maxX = shapeFn ( XYShape . T . maxX ) ;
2020-03-14 18:33:39 +00:00
let toDiscreteProbabilityMass = _ = > 0 . 0 ;
2020-03-28 21:46:17 +00:00
let mapY = fn = > shapeMap ( XYShape . T . mapY ( fn ) ) ;
2020-02-23 13:27:52 +00:00
let toShape = ( t : t ) : DistTypes . shape = > Continuous ( t ) ;
2020-03-28 21:46:17 +00:00
let xToY = ( f , { interpolation , xyShape } : t ) = > {
(
switch ( interpolation ) {
| ` Stepwise = >
xyShape
| > XYShape . XtoY . stepwiseIncremental ( f )
| > E . O . default ( 0 . 0 )
| ` Linear = > xyShape | > XYShape . XtoY . linear ( f )
}
)
| > DistTypes . MixedPoint . makeContinuous ;
} ;
2020-04-18 21:27:24 +00:00
2020-02-24 16:39:55 +00:00
// let combineWithFn = (t1: t, t2: t, fn: (float, float) => float) => {
// switch(t1, t2){
// | ({interpolation: `Stepwise}, {interpolation: `Stepwise}) => 3.0
// | ({interpolation: `Linear}, {interpolation: `Linear}) => 3.0
// }
// };
2020-03-28 21:46:17 +00:00
// TODO: This should work with stepwise plots.
2020-02-24 11:11:03 +00:00
let integral = ( ~ cache , t ) = >
2020-02-25 12:28:26 +00:00
switch ( cache ) {
| Some ( cache ) = > cache
| None = >
t
2020-03-28 21:29:02 +00:00
| > getShape
2020-02-25 12:28:26 +00:00
| > XYShape . Range . integrateWithTriangles
| > E . O . toExt ( " This should not have happened " )
2020-03-28 21:46:17 +00:00
| > make ( ` Linear )
2020-02-25 12:28:26 +00:00
} ;
2020-03-28 21:46:17 +00:00
let truncate = ( ~ cache = None , length , t ) = >
2020-03-18 20:50:01 +00:00
t
| > shapeMap (
2020-03-28 14:17:47 +00:00
XYShape . XsConversion . proportionByProbabilityMass (
2020-03-28 21:46:17 +00:00
length ,
2020-03-18 20:50:01 +00:00
integral ( ~ cache , t ) . xyShape ,
) ,
) ;
2020-02-24 21:01:29 +00:00
let integralEndY = ( ~ cache , t ) = > t | > integral ( ~ cache ) | > lastY ;
2020-02-22 16:24:54 +00:00
let integralXtoY = ( ~ cache , f , t ) = >
2020-03-28 14:17:47 +00:00
t | > integral ( ~ cache ) | > shapeFn ( XYShape . XtoY . linear ( f ) ) ;
2020-03-14 18:33:39 +00:00
let integralYtoX = ( ~ cache , f , t ) = >
2020-03-28 14:17:47 +00:00
t | > integral ( ~ cache ) | > shapeFn ( XYShape . YtoX . linear ( f ) ) ;
2020-02-22 16:24:54 +00:00
let toContinuous = t = > Some ( t ) ;
let toDiscrete = _ = > None ;
2020-02-22 21:46:49 +00:00
let toScaledContinuous = t = > Some ( t ) ;
let toScaledDiscrete = _ = > None ;
2020-04-18 21:20:59 +00:00
2020-04-18 21:27:24 +00:00
let getMean = ( t : t ) = > {
let indefiniteIntegralStepwise = ( p , h1 ) = > h1 * . p * * 2 . 0 /. 2 . 0 ;
let indefiniteIntegralLinear = ( p , a , b ) = >
a * . p * * 2 . 0 /. 2 . 0 + . b * . p * * 3 . 0 /. 3 . 0 ;
XYShape . Analysis . integrateContinuousShape (
~ indefiniteIntegralStepwise ,
~ indefiniteIntegralLinear ,
t ,
) ;
} ;
let getVariance = ( t : t ) : float = >
XYShape . Analysis . getVarianceDangerously (
t ,
getMean ,
XYShape . Analysis . getMeanOfSquaresContinuousShape ,
) ;
2020-02-22 16:24:54 +00:00
} ) ;
} ;
2020-02-21 23:42:15 +00:00
2020-02-22 16:24:54 +00:00
module Discrete = {
2020-03-15 00:30:18 +00:00
let sortedByY = ( t : DistTypes . discreteShape ) = >
2020-03-28 22:51:53 +00:00
t | > XYShape . T . zip | > XYShape . Zipped . sortByY ;
2020-03-15 00:30:18 +00:00
let sortedByX = ( t : DistTypes . discreteShape ) = >
2020-03-28 22:51:53 +00:00
t | > XYShape . T . zip | > XYShape . Zipped . sortByX ;
2020-04-01 13:52:13 +00:00
let empty = XYShape . T . empty ;
2020-04-18 21:20:59 +00:00
let combine =
( fn , t1 : DistTypes . discreteShape , t2 : DistTypes . discreteShape )
: DistTypes . discreteShape = > {
XYShape . Combine . combine (
~ xsSelection = ALL_XS ,
~ xToYSelection = XYShape . XtoY . stepwiseIfAtX ,
~ fn ,
t1 ,
t2 ,
) ;
} ;
let _ default0 = ( fn , a , b ) = >
fn ( E . O . default ( 0 . 0 , a ) , E . O . default ( 0 . 0 , b ) ) ;
let reduce = ( fn , items ) = >
items | > E . A . fold_left ( combine ( _ default0 ( fn ) ) , empty ) ;
2020-02-22 16:24:54 +00:00
module T =
Dist ( {
2020-02-23 13:27:52 +00:00
type t = DistTypes . discreteShape ;
type integral = DistTypes . continuousShape ;
2020-02-22 16:24:54 +00:00
let integral = ( ~ cache , t ) = >
2020-02-25 12:28:26 +00:00
switch ( cache ) {
| Some ( c ) = > c
2020-03-28 21:46:17 +00:00
| None = > Continuous . make ( ` Stepwise , XYShape . T . accumulateYs ( ( + . ) , t ) )
2020-02-25 12:28:26 +00:00
} ;
2020-02-24 21:01:29 +00:00
let integralEndY = ( ~ cache , t ) = >
2020-02-24 11:11:03 +00:00
t | > integral ( ~ cache ) | > Continuous . lastY ;
2020-03-14 21:18:34 +00:00
let minX = XYShape . T . minX ;
let maxX = XYShape . T . maxX ;
2020-03-28 22:51:53 +00:00
let toDiscreteProbabilityMass = _ = > 1 . 0 ;
2020-03-28 14:17:47 +00:00
let mapY = XYShape . T . mapY ;
2020-02-23 13:27:52 +00:00
let toShape = ( t : t ) : DistTypes . shape = > Discrete ( t ) ;
2020-02-22 16:24:54 +00:00
let toContinuous = _ = > None ;
let toDiscrete = t = > Some ( t ) ;
2020-02-23 18:34:34 +00:00
let toScaledContinuous = _ = > None ;
2020-02-22 21:46:49 +00:00
let toScaledDiscrete = t = > Some ( t ) ;
2020-03-18 20:50:01 +00:00
let truncate = ( ~ cache = None , i , t : t ) : DistTypes . discreteShape = >
2020-03-15 00:30:18 +00:00
t
| > XYShape . T . zip
2020-03-28 14:17:47 +00:00
| > XYShape . Zipped . sortByY
2020-03-18 19:13:12 +00:00
| > Belt . Array . reverse
2020-03-15 00:30:18 +00:00
| > Belt . Array . slice ( _ , ~ offset = 0 , ~ len = i )
2020-03-28 14:17:47 +00:00
| > XYShape . Zipped . sortByX
2020-03-15 00:30:18 +00:00
| > XYShape . T . fromZippedArray ;
2020-02-23 19:40:38 +00:00
let xToY = ( f , t ) = > {
2020-03-28 14:17:47 +00:00
XYShape . XtoY . stepwiseIfAtX ( f , t )
2020-02-23 19:40:38 +00:00
| > E . O . default ( 0 . 0 )
2020-02-23 13:27:52 +00:00
| > DistTypes . MixedPoint . makeDiscrete ;
2020-02-23 19:40:38 +00:00
} ;
2020-03-14 18:33:39 +00:00
2020-02-22 16:24:54 +00:00
let integralXtoY = ( ~ cache , f , t ) = >
2020-03-26 23:18:19 +00:00
t
| > integral ( ~ cache )
| > Continuous . getShape
2020-03-28 14:17:47 +00:00
| > XYShape . XtoY . linear ( f ) ;
2020-03-14 18:33:39 +00:00
let integralYtoX = ( ~ cache , f , t ) = >
2020-03-26 23:18:19 +00:00
t
| > integral ( ~ cache )
| > Continuous . getShape
2020-03-28 14:17:47 +00:00
| > XYShape . YtoX . linear ( f ) ;
2020-04-18 21:20:59 +00:00
2020-04-18 21:27:24 +00:00
let getMean = ( t : t ) : float = >
E . A . reducei ( t . xs , 0 . 0 , ( acc , x , i ) = > acc + . x * . t . ys [ i ] ) ;
2020-04-18 21:20:59 +00:00
let getVariance = ( t : t ) : float = > {
2020-04-18 21:27:24 +00:00
let getMeanOfSquares = t = >
getMean ( XYShape . Analysis . squareXYShape ( t ) ) ;
2020-04-18 21:20:59 +00:00
XYShape . Analysis . getVarianceDangerously ( t , getMean , getMeanOfSquares ) ;
} ;
2020-02-22 16:24:54 +00:00
} ) ;
} ;
2020-02-21 23:42:15 +00:00
2020-03-28 22:51:53 +00:00
// TODO: I think this shouldn't assume continuous/discrete are normalized to 1.0, and thus should not need the discreteProbabilityMassFraction being separate.
2020-02-22 16:24:54 +00:00
module Mixed = {
2020-02-23 18:34:34 +00:00
type t = DistTypes . mixedShape ;
2020-02-22 19:21:04 +00:00
let make =
( ~ continuous , ~ discrete , ~ discreteProbabilityMassFraction )
2020-02-23 13:27:52 +00:00
: DistTypes . mixedShape = > {
2020-02-22 19:21:04 +00:00
continuous ,
discrete ,
discreteProbabilityMassFraction ,
} ;
2020-02-23 18:34:34 +00:00
// todo: Put into scaling module
2020-02-23 12:40:18 +00:00
let scaleDiscreteFn =
2020-02-23 13:27:52 +00:00
( { discreteProbabilityMassFraction } : DistTypes . mixedShape , f ) = >
2020-02-22 21:46:49 +00:00
f * . discreteProbabilityMassFraction ;
2020-03-18 21:46:43 +00:00
//TODO: Warning: This currently computes the integral, which is expensive.
2020-02-23 12:40:18 +00:00
let scaleContinuousFn =
2020-02-23 13:27:52 +00:00
( { discreteProbabilityMassFraction } : DistTypes . mixedShape , f ) = >
2020-02-22 21:46:49 +00:00
f * . ( 1 . 0 -. discreteProbabilityMassFraction ) ;
2020-03-18 21:46:43 +00:00
//TODO: Warning: This currently computes the integral, which is expensive.
2020-02-23 18:34:34 +00:00
let scaleContinuous = ( { discreteProbabilityMassFraction } : t , continuous ) = >
continuous
2020-02-25 19:27:30 +00:00
| > Continuous . T . scaleToIntegralSum (
~ intendedSum = 1 . 0 -. discreteProbabilityMassFraction ,
) ;
2020-02-23 18:34:34 +00:00
let scaleDiscrete = ( { discreteProbabilityMassFraction } : t , disrete ) = >
2020-02-25 19:27:30 +00:00
disrete
| > Discrete . T . scaleToIntegralSum (
~ intendedSum = discreteProbabilityMassFraction ,
) ;
2020-02-23 18:34:34 +00:00
2020-02-22 16:24:54 +00:00
module T =
Dist ( {
2020-02-23 13:27:52 +00:00
type t = DistTypes . mixedShape ;
type integral = DistTypes . continuousShape ;
2020-02-25 19:55:01 +00:00
let minX = ( { continuous , discrete } : t ) = > {
2020-02-22 16:24:54 +00:00
min ( Continuous . T . minX ( continuous ) , Discrete . T . minX ( discrete ) ) ;
2020-02-25 19:55:01 +00:00
} ;
2020-02-22 16:24:54 +00:00
let maxX = ( { continuous , discrete } : t ) = >
max ( Continuous . T . maxX ( continuous ) , Discrete . T . maxX ( discrete ) ) ;
2020-02-23 13:27:52 +00:00
let toShape = ( t : t ) : DistTypes . shape = > Mixed ( t ) ;
2020-02-22 16:24:54 +00:00
let toContinuous = ( { continuous } : t ) = > Some ( continuous ) ;
let toDiscrete = ( { discrete } : t ) = > Some ( discrete ) ;
2020-02-26 10:08:37 +00:00
let toDiscreteProbabilityMass = ( { discreteProbabilityMassFraction } : t ) = > discreteProbabilityMassFraction ;
2020-04-11 13:22:13 +00:00
2020-02-23 12:40:18 +00:00
let xToY = ( f , { discrete , continuous } as t : t ) = > {
2020-02-22 16:24:54 +00:00
let c =
continuous
| > Continuous . T . xToY ( f )
2020-02-23 13:27:52 +00:00
| > DistTypes . MixedPoint . fmap ( scaleContinuousFn ( t ) ) ;
2020-02-22 16:24:54 +00:00
let d =
discrete
| > Discrete . T . xToY ( f )
2020-02-23 13:27:52 +00:00
| > DistTypes . MixedPoint . fmap ( scaleDiscreteFn ( t ) ) ;
DistTypes . MixedPoint . add ( c , d ) ;
2020-02-22 16:24:54 +00:00
} ;
2020-03-28 22:51:53 +00:00
// Warning: It's not clear how to update the discreteProbabilityMassFraction, so this may create small errors.
2020-03-15 00:30:18 +00:00
let truncate =
(
2020-03-18 20:50:01 +00:00
~ cache = None ,
2020-03-15 00:30:18 +00:00
count ,
2020-03-28 22:51:53 +00:00
{ discrete , continuous , discreteProbabilityMassFraction } : t ,
2020-03-15 00:30:18 +00:00
)
: t = > {
{
discrete :
Discrete . T . truncate (
int_of_float (
float_of_int ( count ) * . discreteProbabilityMassFraction ,
) ,
discrete ,
) ,
continuous :
Continuous . T . truncate (
int_of_float (
float_of_int ( count )
* . ( 1 . 0 -. discreteProbabilityMassFraction ) ,
) ,
continuous ,
) ,
discreteProbabilityMassFraction ,
} ;
} ;
2020-02-22 23:55:43 +00:00
let toScaledContinuous = ( { continuous } as t : t ) = >
Some ( scaleContinuous ( t , continuous ) ) ;
let toScaledDiscrete = ( { discrete } as t : t ) = >
Some ( scaleDiscrete ( t , discrete ) ) ;
2020-02-21 23:42:15 +00:00
2020-02-22 23:55:43 +00:00
let integral =
(
~ cache ,
2020-02-25 19:27:30 +00:00
{ continuous , discrete , discreteProbabilityMassFraction } : t ,
2020-02-22 23:55:43 +00:00
) = > {
2020-02-25 12:28:26 +00:00
switch ( cache ) {
| Some ( cache ) = > cache
| None = >
2020-02-25 19:27:30 +00:00
let scaleContinuousBy =
( 1 . 0 -. discreteProbabilityMassFraction )
/. ( continuous | > Continuous . T . Integral . sum ( ~ cache = None ) ) ;
let scaleDiscreteBy =
discreteProbabilityMassFraction
/. (
discrete
| > Discrete . T . Integral . get ( ~ cache = None )
| > Continuous . toLinear
| > E . O . fmap ( Continuous . lastY )
| > E . O . toExn ( " " )
) ;
2020-02-25 12:28:26 +00:00
let cont =
continuous
| > Continuous . T . Integral . get ( ~ cache = None )
2020-02-25 19:27:30 +00:00
| > Continuous . T . scaleBy ( ~ scale = scaleContinuousBy ) ;
2020-02-25 12:28:26 +00:00
let dist =
discrete
| > Discrete . T . Integral . get ( ~ cache = None )
| > Continuous . toLinear
| > E . O . toExn ( " " )
2020-02-25 19:27:30 +00:00
| > Continuous . T . scaleBy ( ~ scale = scaleDiscreteBy ) ;
let result =
Continuous . make (
2020-03-28 21:46:17 +00:00
` Linear ,
2020-03-28 14:17:47 +00:00
XYShape . Combine . combineLinear (
2020-03-28 22:51:53 +00:00
~ fn = ( + . ) ,
2020-03-28 14:17:47 +00:00
Continuous . getShape ( cont ) ,
Continuous . getShape ( dist ) ,
2020-02-25 19:27:30 +00:00
) ,
) ;
result ;
2020-02-25 12:28:26 +00:00
} ;
2020-02-22 10:10:10 +00:00
} ;
2020-02-21 23:42:15 +00:00
2020-02-24 21:01:29 +00:00
let integralEndY = ( ~ cache , t : t ) = > {
integral ( ~ cache , t ) | > Continuous . lastY ;
2020-02-22 10:10:10 +00:00
} ;
2020-02-21 23:42:15 +00:00
2020-03-14 18:33:39 +00:00
let integralXtoY = ( ~ cache , f , t ) = > {
2020-03-26 23:18:19 +00:00
t
| > integral ( ~ cache )
| > Continuous . getShape
2020-03-28 14:17:47 +00:00
| > XYShape . XtoY . linear ( f ) ;
2020-03-14 18:33:39 +00:00
} ;
let integralYtoX = ( ~ cache , f , t ) = > {
2020-03-26 23:18:19 +00:00
t
| > integral ( ~ cache )
| > Continuous . getShape
2020-03-28 14:17:47 +00:00
| > XYShape . YtoX . linear ( f ) ;
2020-02-22 16:24:54 +00:00
} ;
2020-02-21 23:42:15 +00:00
2020-03-28 22:51:53 +00:00
// TODO: This part really needs to be rethought, I'm quite sure this is just broken. Mapping Ys would change the desired discreteProbabilityMassFraction.
2020-03-28 14:17:47 +00:00
let mapY =
2020-02-22 16:24:54 +00:00
( fn , { discrete , continuous , discreteProbabilityMassFraction } : t ) : t = > {
{
2020-03-28 14:17:47 +00:00
discrete : Discrete . T . mapY ( fn , discrete ) ,
continuous : Continuous . T . mapY ( fn , continuous ) ,
2020-02-22 16:24:54 +00:00
discreteProbabilityMassFraction ,
} ;
2020-02-21 23:42:15 +00:00
} ;
2020-04-18 21:20:59 +00:00
2020-04-18 21:27:24 +00:00
let getMean = ( t : t ) : float = > {
let discreteProbabilityMassFraction =
t . discreteProbabilityMassFraction ;
switch ( discreteProbabilityMassFraction ) {
| 1 . 0 = > Discrete . T . getMean ( t . discrete )
| 0 . 0 = > Continuous . T . getMean ( t . continuous )
| _ = >
Discrete . T . getMean ( t . discrete )
* . discreteProbabilityMassFraction
+ . Continuous . T . getMean ( t . continuous )
* . ( 1 . 0 -. discreteProbabilityMassFraction )
2020-04-18 21:20:59 +00:00
} ;
} ;
2020-04-18 21:27:24 +00:00
let getVariance = ( t : t ) : float = > {
let discreteProbabilityMassFraction =
t . discreteProbabilityMassFraction ;
2020-04-18 21:20:59 +00:00
let getMeanOfSquares = ( t : t ) = > {
2020-04-18 21:27:24 +00:00
Discrete . T . getMean ( XYShape . Analysis . squareXYShape ( t . discrete ) )
* . t . discreteProbabilityMassFraction
+ . XYShape . Analysis . getMeanOfSquaresContinuousShape ( t . continuous )
* . ( 1 . 0 -. t . discreteProbabilityMassFraction ) ;
2020-04-18 21:20:59 +00:00
} ;
2020-04-18 21:27:24 +00:00
switch ( discreteProbabilityMassFraction ) {
| 1 . 0 = > Discrete . T . getVariance ( t . discrete )
| 0 . 0 = > Continuous . T . getVariance ( t . continuous )
| _ = >
XYShape . Analysis . getVarianceDangerously (
t ,
getMean ,
getMeanOfSquares ,
)
2020-04-18 21:20:59 +00:00
} ;
} ;
2020-02-22 16:24:54 +00:00
} ) ;
} ;
2020-02-21 23:42:15 +00:00
2020-02-22 16:24:54 +00:00
module Shape = {
module T =
Dist ( {
2020-02-23 13:27:52 +00:00
type t = DistTypes . shape ;
type integral = DistTypes . continuousShape ;
2020-02-22 12:51:25 +00:00
2020-03-28 22:51:53 +00:00
let mapToAll = ( ( fn1 , fn2 , fn3 ) , t : t ) = >
2020-02-22 16:24:54 +00:00
switch ( t ) {
| Mixed ( m ) = > fn1 ( m )
| Discrete ( m ) = > fn2 ( m )
| Continuous ( m ) = > fn3 ( m )
} ;
2020-02-22 12:51:25 +00:00
2020-03-28 22:51:53 +00:00
let fmap = ( ( fn1 , fn2 , fn3 ) , t : t ) : t = >
2020-02-22 16:24:54 +00:00
switch ( t ) {
| Mixed ( m ) = > Mixed ( fn1 ( m ) )
| Discrete ( m ) = > Discrete ( fn2 ( m ) )
| Continuous ( m ) = > Continuous ( fn3 ( m ) )
} ;
2020-02-22 12:51:25 +00:00
2020-03-28 22:51:53 +00:00
let xToY = f = >
mapToAll ( (
Mixed . T . xToY ( f ) ,
Discrete . T . xToY ( f ) ,
Continuous . T . xToY ( f ) ,
) ) ;
2020-02-22 16:24:54 +00:00
let toShape = ( t : t ) = > t ;
2020-03-28 22:51:53 +00:00
let toContinuous =
mapToAll ( (
Mixed . T . toContinuous ,
Discrete . T . toContinuous ,
Continuous . T . toContinuous ,
) ) ;
let toDiscrete =
mapToAll ( (
Mixed . T . toDiscrete ,
Discrete . T . toDiscrete ,
Continuous . T . toDiscrete ,
) ) ;
let truncate = ( ~ cache = None , i ) = >
fmap ( (
Mixed . T . truncate ( i ) ,
Discrete . T . truncate ( i ) ,
Continuous . T . truncate ( i ) ,
) ) ;
let toDiscreteProbabilityMass =
mapToAll ( (
Mixed . T . toDiscreteProbabilityMass ,
Discrete . T . toDiscreteProbabilityMass ,
Continuous . T . toDiscreteProbabilityMass ,
) ) ;
let toScaledDiscrete =
mapToAll ( (
Mixed . T . toScaledDiscrete ,
Discrete . T . toScaledDiscrete ,
Continuous . T . toScaledDiscrete ,
) ) ;
let toScaledContinuous =
mapToAll ( (
Mixed . T . toScaledContinuous ,
Discrete . T . toScaledContinuous ,
Continuous . T . toScaledContinuous ,
) ) ;
let minX = mapToAll ( ( Mixed . T . minX , Discrete . T . minX , Continuous . T . minX ) ) ;
let integral = ( ~ cache ) = > {
mapToAll ( (
Mixed . T . Integral . get ( ~ cache ) ,
Discrete . T . Integral . get ( ~ cache ) ,
Continuous . T . Integral . get ( ~ cache ) ,
) ) ;
2020-02-22 23:55:43 +00:00
} ;
2020-03-28 22:51:53 +00:00
let integralEndY = ( ~ cache ) = >
mapToAll ( (
Mixed . T . Integral . sum ( ~ cache ) ,
Discrete . T . Integral . sum ( ~ cache ) ,
Continuous . T . Integral . sum ( ~ cache ) ,
) ) ;
let integralXtoY = ( ~ cache , f ) = > {
mapToAll ( (
Mixed . T . Integral . xToY ( ~ cache , f ) ,
Discrete . T . Integral . xToY ( ~ cache , f ) ,
Continuous . T . Integral . xToY ( ~ cache , f ) ,
) ) ;
2020-02-22 16:24:54 +00:00
} ;
2020-03-28 22:51:53 +00:00
let integralYtoX = ( ~ cache , f ) = > {
mapToAll ( (
Mixed . T . Integral . yToX ( ~ cache , f ) ,
Discrete . T . Integral . yToX ( ~ cache , f ) ,
Continuous . T . Integral . yToX ( ~ cache , f ) ,
) ) ;
2020-03-14 18:33:39 +00:00
} ;
2020-03-28 22:51:53 +00:00
let maxX = mapToAll ( ( Mixed . T . maxX , Discrete . T . maxX , Continuous . T . maxX ) ) ;
let mapY = fn = >
fmap ( (
Mixed . T . mapY ( fn ) ,
Discrete . T . mapY ( fn ) ,
Continuous . T . mapY ( fn ) ,
) ) ;
2020-04-18 21:20:59 +00:00
2020-04-18 21:27:24 +00:00
let getMean = ( t : t ) : float = >
switch ( t ) {
| Mixed ( m ) = > Mixed . T . getMean ( m )
| Discrete ( m ) = > Discrete . T . getMean ( m )
| Continuous ( m ) = > Continuous . T . getMean ( m )
} ;
let getVariance = ( t : t ) : float = >
switch ( t ) {
| Mixed ( m ) = > Mixed . T . getVariance ( m )
| Discrete ( m ) = > Discrete . T . getVariance ( m )
| Continuous ( m ) = > Continuous . T . getVariance ( m )
} ;
2020-02-22 16:24:54 +00:00
} ) ;
} ;
2020-02-21 23:42:15 +00:00
2020-02-23 12:49:33 +00:00
module DistPlus = {
2020-02-23 13:27:52 +00:00
open DistTypes ;
2020-02-23 18:34:34 +00:00
type t = DistTypes . distPlus ;
2020-02-24 21:01:29 +00:00
let shapeIntegral = shape = > Shape . T . Integral . get ( ~ cache = None , shape ) ;
2020-02-22 20:36:22 +00:00
let make =
(
~ shape ,
~ guesstimatorString ,
~ domain = Complete ,
~ unit = UnspecifiedDistribution ,
() ,
)
2020-02-23 18:34:34 +00:00
: t = > {
2020-02-24 21:01:29 +00:00
let integral = shapeIntegral ( shape ) ;
2020-02-22 20:36:22 +00:00
{ shape , domain , integralCache : integral , unit , guesstimatorString } ;
} ;
2020-02-23 18:34:34 +00:00
2020-02-22 20:36:22 +00:00
let update =
(
~ shape = ? ,
~ integralCache = ? ,
~ domain = ? ,
~ unit = ? ,
~ guesstimatorString = ? ,
2020-02-23 18:34:34 +00:00
t : t ,
2020-02-22 20:36:22 +00:00
) = > {
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 ) ,
} ;
2020-02-24 21:01:29 +00:00
let updateShape = ( shape , t ) = > {
let integralCache = shapeIntegral ( shape ) ;
update ( ~ shape , ~ integralCache , t ) ;
} ;
2020-02-23 18:34:34 +00:00
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 ) ;
2020-02-22 16:24:54 +00:00
module T =
Dist ( {
2020-02-23 13:27:52 +00:00
type t = DistTypes . distPlus ;
type integral = DistTypes . distPlus ;
2020-02-23 18:34:34 +00:00
let toShape = toShape ;
2020-02-22 19:21:04 +00:00
let toContinuous = shapeFn ( Shape . T . toContinuous ) ;
let toDiscrete = shapeFn ( Shape . T . toDiscrete ) ;
2020-02-22 21:46:49 +00:00
// todo: Adjust for total mass.
2020-02-23 12:40:18 +00:00
let toScaledContinuous = ( t : t ) = > {
t
| > toShape
| > Shape . T . toScaledContinuous
| > E . O . fmap (
2020-03-28 14:17:47 +00:00
Continuous . T . mapY ( domainIncludedProbabilityMassAdjustment ( t ) ) ,
2020-02-23 12:40:18 +00:00
) ;
} ;
let toScaledDiscrete = ( t : t ) = > {
t
| > toShape
| > Shape . T . toScaledDiscrete
| > E . O . fmap (
2020-03-28 14:17:47 +00:00
Discrete . T . mapY ( domainIncludedProbabilityMassAdjustment ( t ) ) ,
2020-02-23 12:40:18 +00:00
) ;
} ;
let xToY = ( f , t : t ) = >
t
| > toShape
| > Shape . T . xToY ( f )
| > MixedPoint . fmap ( domainIncludedProbabilityMassAdjustment ( t ) ) ;
2020-02-22 19:21:04 +00:00
let minX = shapeFn ( Shape . T . minX ) ;
let maxX = shapeFn ( Shape . T . maxX ) ;
2020-02-26 10:08:37 +00:00
let toDiscreteProbabilityMass =
shapeFn ( Shape . T . toDiscreteProbabilityMass ) ;
2020-02-23 12:40:18 +00:00
2020-03-18 21:46:43 +00:00
// This bit is kind of awkward, could probably use rethinking.
2020-02-24 22:04:39 +00:00
let integral = ( ~ cache , t : t ) = >
2020-02-24 21:01:29 +00:00
updateShape ( Continuous ( t . integralCache ) , t ) ;
2020-03-18 20:50:01 +00:00
let truncate = ( ~ cache = None , i , t ) = >
2020-03-15 00:30:18 +00:00
updateShape ( t | > toShape | > Shape . T . truncate ( i ) , t ) ;
2020-02-24 21:01:29 +00:00
// todo: adjust for limit, maybe?
2020-03-28 14:17:47 +00:00
let mapY = ( fn , { shape , _ } as t : t ) : t = >
Shape . T . mapY ( fn , shape ) | > updateShape ( _ , t ) ;
2020-02-23 12:40:18 +00:00
2020-02-24 21:01:29 +00:00
let integralEndY = ( ~ cache as _ , t : t ) = >
2020-02-22 19:21:04 +00:00
Shape . T . Integral . sum ( ~ cache = Some ( t . integralCache ) , toShape ( t ) ) ;
2020-02-23 12:40:18 +00:00
2020-02-23 18:34:34 +00:00
// TODO: Fix this below, obviously. Adjust for limits
2020-02-22 19:21:04 +00:00
let integralXtoY = ( ~ cache as _ , f , t : t ) = > {
2020-02-25 19:27:30 +00:00
Shape . T . Integral . xToY ( ~ cache = Some ( t . integralCache ) , f , toShape ( t ) )
| > domainIncludedProbabilityMassAdjustment ( t ) ;
2020-02-22 16:24:54 +00:00
} ;
2020-03-14 18:33:39 +00:00
// TODO: This part is broken when there is a limit, if this is supposed to be taken into account.
let integralYtoX = ( ~ cache as _ , f , t : t ) = > {
Shape . T . Integral . yToX ( ~ cache = Some ( t . integralCache ) , f , toShape ( t ) ) ;
} ;
2020-04-18 21:20:59 +00:00
let getMean = ( t : t ) = > Shape . T . getMean ( t . shape ) ;
let getVariance = ( t : t ) = > Shape . T . getVariance ( t . shape ) ;
2020-02-22 16:24:54 +00:00
} ) ;
2020-02-23 18:34:34 +00:00
} ;
module DistPlusTime = {
open DistTypes ;
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 ;
2020-02-25 19:27:30 +00:00
let xToY = ( f : TimeTypes . timeInVector , t : t ) = > {
2020-02-23 18:34:34 +00:00
timeInVectorToX ( f , t )
| > E . O . fmap ( x = > DistPlus . T . Integral . xToY ( ~ cache = None , x , t ) ) ;
} ;
} ;
2020-02-22 16:24:54 +00:00
} ;