Starting to move functionality into functor
This commit is contained in:
		
							parent
							
								
									7bc62d3934
								
							
						
					
					
						commit
						745cf01317
					
				| 
						 | 
				
			
			@ -1,12 +1,12 @@
 | 
			
		|||
module Shapee = {
 | 
			
		||||
  [@react.component]
 | 
			
		||||
  let make = (~shape: DistributionTypes.pointsType, ~timeScale, ~onHover) => {
 | 
			
		||||
    let discrete = Shape.PointsType.scaledDiscreteComponent(shape);
 | 
			
		||||
    let continuous = Shape.PointsType.scaledContinuousComponent(shape);
 | 
			
		||||
  let make = (~shape: DistributionTypes.shape, ~timeScale, ~onHover) => {
 | 
			
		||||
    let discrete = Shape.T.scaledDiscreteComponent(shape);
 | 
			
		||||
    let continuous = Shape.T.scaledContinuousComponent(shape);
 | 
			
		||||
    <div>
 | 
			
		||||
      <CdfChart__Plain
 | 
			
		||||
        minX={Shape.PointsType.minX(shape)}
 | 
			
		||||
        maxX={Shape.PointsType.maxX(shape)}
 | 
			
		||||
        minX={Shape.T.minX(shape)}
 | 
			
		||||
        maxX={Shape.T.maxX(shape)}
 | 
			
		||||
        ?discrete
 | 
			
		||||
        ?continuous
 | 
			
		||||
        color={`hex("333")}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ module GenericDist = {
 | 
			
		|||
      React.useMemo1(
 | 
			
		||||
        () => {
 | 
			
		||||
          genericDistribution
 | 
			
		||||
          |> DistributionTypes.shape
 | 
			
		||||
          |> DistributionTypes.shapee
 | 
			
		||||
          |> E.O.React.fmapOrNull(shape => {
 | 
			
		||||
               <Shapee shape timeScale onHover={r => setX(_ => r)} />
 | 
			
		||||
             })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										218
									
								
								src/core/DistFunctor.re
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/core/DistFunctor.re
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,218 @@
 | 
			
		|||
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
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
type yPoint =
 | 
			
		||||
  | Mixed({
 | 
			
		||||
      continuous: float,
 | 
			
		||||
      discrete: float,
 | 
			
		||||
    })
 | 
			
		||||
  | Continuous(float)
 | 
			
		||||
  | Discrete(float);
 | 
			
		||||
 | 
			
		||||
module type dist = {
 | 
			
		||||
  type t;
 | 
			
		||||
  type integral;
 | 
			
		||||
  let minX: t => option(float);
 | 
			
		||||
  let maxX: t => option(float);
 | 
			
		||||
  let pointwiseFmap: (float => float, t) => t;
 | 
			
		||||
  let xToY: (float, t) => yPoint;
 | 
			
		||||
  let xToIntegralY: (float, t) => float;
 | 
			
		||||
  let shape: t => DistributionTypes.shape;
 | 
			
		||||
  let integral: t => integral;
 | 
			
		||||
  let integralSum: t => float;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module Dist = (T: dist) => {
 | 
			
		||||
  type t = T.t;
 | 
			
		||||
  type integral = T.integral;
 | 
			
		||||
  let minX = T.minX;
 | 
			
		||||
  let maxX = T.maxX;
 | 
			
		||||
  let pointwiseFmap = T.pointwiseFmap;
 | 
			
		||||
  let xToIntegralY = T.xToIntegralY;
 | 
			
		||||
  let xToY = T.xToY;
 | 
			
		||||
  let shape = T.shape;
 | 
			
		||||
  let integral = T.integral;
 | 
			
		||||
  let integralSum = T.integralSum;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module Continuous =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.continuousShape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let integral = t =>
 | 
			
		||||
      t |> Shape.XYShape.Range.integrateWithTriangles |> E.O.toExt("");
 | 
			
		||||
    let integralSum = t => t |> integral |> Shape.XYShape.ySum;
 | 
			
		||||
    let minX = Shape.XYShape.minX;
 | 
			
		||||
    let maxX = Shape.XYShape.maxX;
 | 
			
		||||
    let pointwiseFmap = Shape.XYShape.pointwiseMap;
 | 
			
		||||
    let shape = (t: t): DistributionTypes.shape => Continuous(t);
 | 
			
		||||
    let xToY = (f, t) =>
 | 
			
		||||
      CdfLibrary.Distribution.findY(f, t) |> (e => Continuous(e));
 | 
			
		||||
    let xToIntegralY = (f, t) =>
 | 
			
		||||
      t |> integral |> CdfLibrary.Distribution.findY(f);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
module Discrete =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.discreteShape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let integral = t => t |> Shape.Discrete.integrate;
 | 
			
		||||
    let integralSum = t => t |> Shape.XYShape.ySum;
 | 
			
		||||
    let minX = Shape.XYShape.minX;
 | 
			
		||||
    let maxX = Shape.XYShape.maxX;
 | 
			
		||||
    let pointwiseFmap = Shape.XYShape.pointwiseMap;
 | 
			
		||||
    let shape = (t: t): DistributionTypes.shape => Discrete(t);
 | 
			
		||||
    let xToY = (f, t) =>
 | 
			
		||||
      CdfLibrary.Distribution.findY(f, t) |> (e => Discrete(e));
 | 
			
		||||
    let xToIntegralY = (f, t) =>
 | 
			
		||||
      t |> Shape.XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
module Mixed =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.mixedShape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let minX = ({continuous, discrete}: t) =>
 | 
			
		||||
      min(Continuous.minX(continuous), Discrete.minX(discrete));
 | 
			
		||||
    let maxX = ({continuous, discrete}: t) =>
 | 
			
		||||
      max(Continuous.maxX(continuous), Discrete.maxX(discrete));
 | 
			
		||||
    let shape = (t: t): DistributionTypes.shape => Mixed(t);
 | 
			
		||||
    let xToY =
 | 
			
		||||
        (f, {discrete, continuous, discreteProbabilityMassFraction}: t) =>
 | 
			
		||||
      Mixed({
 | 
			
		||||
        continuous:
 | 
			
		||||
          CdfLibrary.Distribution.findY(f, continuous)
 | 
			
		||||
          |> (e => e *. (1. -. discreteProbabilityMassFraction)),
 | 
			
		||||
        discrete:
 | 
			
		||||
          Shape.Discrete.findY(f, discrete)
 | 
			
		||||
          |> (e => e *. discreteProbabilityMassFraction),
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    let scaledContinuousComponent =
 | 
			
		||||
        ({continuous, discreteProbabilityMassFraction}: t)
 | 
			
		||||
        : option(DistributionTypes.continuousShape) => {
 | 
			
		||||
      Shape.Continuous.scalePdf(
 | 
			
		||||
        ~scaleTo=1.0 -. discreteProbabilityMassFraction,
 | 
			
		||||
        continuous,
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let scaledDiscreteComponent =
 | 
			
		||||
        ({discrete, discreteProbabilityMassFraction}: t)
 | 
			
		||||
        : DistributionTypes.continuousShape =>
 | 
			
		||||
      Discrete.pointwiseFmap(
 | 
			
		||||
        f => f *. discreteProbabilityMassFraction,
 | 
			
		||||
        discrete,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
    // TODO: Add these two directly, once interpolation is added.
 | 
			
		||||
    let integral = t => {
 | 
			
		||||
      //   let cont = scaledContinuousComponent(t);
 | 
			
		||||
      //   let discrete = scaledDiscreteComponent(t);
 | 
			
		||||
      scaledContinuousComponent(t) |> E.O.toExt("");
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let integralSum =
 | 
			
		||||
        ({discrete, continuous, discreteProbabilityMassFraction}: t) => {
 | 
			
		||||
      Discrete.integralSum(discrete)
 | 
			
		||||
      *. discreteProbabilityMassFraction
 | 
			
		||||
      +. Continuous.integralSum(continuous)
 | 
			
		||||
      *. (1.0 -. discreteProbabilityMassFraction);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let xToIntegralY =
 | 
			
		||||
        (f, {discrete, continuous, discreteProbabilityMassFraction}: t) => {
 | 
			
		||||
      let cont = Continuous.xToIntegralY(f, continuous);
 | 
			
		||||
      let discrete = Discrete.xToIntegralY(f, discrete);
 | 
			
		||||
      discrete
 | 
			
		||||
      *. discreteProbabilityMassFraction
 | 
			
		||||
      +. cont
 | 
			
		||||
      *. (1.0 -. discreteProbabilityMassFraction);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let pointwiseFmap =
 | 
			
		||||
        (fn, {discrete, continuous, discreteProbabilityMassFraction}: t): t => {
 | 
			
		||||
      {
 | 
			
		||||
        discrete: Shape.XYShape.pointwiseMap(fn, discrete),
 | 
			
		||||
        continuous: Shape.XYShape.pointwiseMap(fn, continuous),
 | 
			
		||||
        discreteProbabilityMassFraction,
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
module Shape =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.shape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let xToY = (f, t) =>
 | 
			
		||||
      Shape.T.mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (Mixed.xToY(f), Discrete.xToY(f), Continuous.xToY(f)),
 | 
			
		||||
      );
 | 
			
		||||
    let shape = (t: t) => t;
 | 
			
		||||
    let minX = (t: t) =>
 | 
			
		||||
      Shape.T.mapToAll(t, (Mixed.minX, Discrete.minX, Continuous.minX));
 | 
			
		||||
    let integral = (t: t) =>
 | 
			
		||||
      Shape.T.mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (Mixed.integral, Discrete.integral, Continuous.integral),
 | 
			
		||||
      );
 | 
			
		||||
    let integralSum = (t: t) =>
 | 
			
		||||
      Shape.T.mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (Mixed.integralSum, Discrete.integralSum, Continuous.integralSum),
 | 
			
		||||
      );
 | 
			
		||||
    let xToIntegralY = (f, t) => {
 | 
			
		||||
      Shape.T.mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (
 | 
			
		||||
          Mixed.xToIntegralY(f),
 | 
			
		||||
          Discrete.xToIntegralY(f),
 | 
			
		||||
          Continuous.xToIntegralY(f),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
    let maxX = (t: t) =>
 | 
			
		||||
      Shape.T.mapToAll(t, (Mixed.minX, Discrete.minX, Continuous.minX));
 | 
			
		||||
    let pointwiseFmap = (fn, t: t) =>
 | 
			
		||||
      Shape.T.fmap(
 | 
			
		||||
        t,
 | 
			
		||||
        (
 | 
			
		||||
          Mixed.pointwiseFmap(fn),
 | 
			
		||||
          Discrete.pointwiseFmap(fn),
 | 
			
		||||
          Continuous.pointwiseFmap(fn),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
module WithMetadata =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.complexPower;
 | 
			
		||||
    type integral = DistributionTypes.complexPower;
 | 
			
		||||
    let shape = ({shape, _}: t) => shape;
 | 
			
		||||
    let xToY = (f, t: t) => t |> shape |> Shape.xToY(f);
 | 
			
		||||
    let minX = (t: t) => t |> shape |> Shape.minX;
 | 
			
		||||
    let maxX = (t: t) => t |> shape |> Shape.maxX;
 | 
			
		||||
    let fromShape = (shape, t): t => DistributionTypes.update(~shape, t);
 | 
			
		||||
    let pointwiseFmap = (fn, {shape, _} as t: t): t =>
 | 
			
		||||
      fromShape(Shape.pointwiseFmap(fn, shape), t);
 | 
			
		||||
 | 
			
		||||
    let integral = (t: t) => fromShape(Continuous(t.integralCache), t);
 | 
			
		||||
    let integralSum = (t: t) => t |> shape |> Shape.integralSum;
 | 
			
		||||
    let xToIntegralY = (f, t) => {
 | 
			
		||||
      3.0;
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
| 
						 | 
				
			
			@ -23,14 +23,26 @@ type mixedShape = {
 | 
			
		|||
  discreteProbabilityMassFraction: float,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type pointsType =
 | 
			
		||||
  | Mixed(mixedShape)
 | 
			
		||||
  | Discrete(discreteShape)
 | 
			
		||||
  | Continuous(continuousShape);
 | 
			
		||||
type shapeMonad('a, 'b, 'c) =
 | 
			
		||||
  | Mixed('a)
 | 
			
		||||
  | Discrete('b)
 | 
			
		||||
  | Continuous('c);
 | 
			
		||||
 | 
			
		||||
type shape = shapeMonad(mixedShape, discreteShape, continuousShape);
 | 
			
		||||
 | 
			
		||||
module ShapeMonad = {
 | 
			
		||||
  let fmap =
 | 
			
		||||
      (t: shapeMonad('a, 'b, 'c), (fn1, fn2, fn3)): shapeMonad('d, 'e, 'f) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed(m) => Mixed(fn1(m))
 | 
			
		||||
    | Discrete(m) => Discrete(fn2(m))
 | 
			
		||||
    | Continuous(m) => Continuous(fn3(m))
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type generationSource =
 | 
			
		||||
  | GuesstimatorString(string)
 | 
			
		||||
  | Shape(pointsType);
 | 
			
		||||
  | Shape(shape);
 | 
			
		||||
 | 
			
		||||
type distributionUnit =
 | 
			
		||||
  | UnspecifiedDistribution
 | 
			
		||||
| 
						 | 
				
			
			@ -48,12 +60,31 @@ type genericDistribution = {
 | 
			
		|||
  unit: distributionUnit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let shape = ({generationSource}: genericDistribution) =>
 | 
			
		||||
let shapee = ({generationSource}: genericDistribution) =>
 | 
			
		||||
  switch (generationSource) {
 | 
			
		||||
  | GuesstimatorString(_) => None
 | 
			
		||||
  | Shape(pointsType) => Some(pointsType)
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
type pdfCdfCombo = {
 | 
			
		||||
  pdf: shape,
 | 
			
		||||
  cdf: continuousShape,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type complexPower = {
 | 
			
		||||
  shape,
 | 
			
		||||
  integralCache: continuousShape,
 | 
			
		||||
  domain: domainLimit,
 | 
			
		||||
  unit: distributionUnit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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 = {
 | 
			
		||||
  let toJson = (distributionUnit: distributionUnit) =>
 | 
			
		||||
    switch (distributionUnit) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,36 +43,22 @@ let make =
 | 
			
		|||
  unit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//TODO: The fact that it is a CDF is really something you find later, this can't be chosen until GuesstimatorToString happens.
 | 
			
		||||
let renderIfNeeded =
 | 
			
		||||
    (~sampleCount=1000, t: genericDistribution): option(genericDistribution) => {
 | 
			
		||||
  switch (t.generationSource) {
 | 
			
		||||
  | GuesstimatorString(s) =>
 | 
			
		||||
    let shape = Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ());
 | 
			
		||||
    let newShape =
 | 
			
		||||
      switch (shape) {
 | 
			
		||||
      | Some({
 | 
			
		||||
          continuous: {xs: [||], ys: [||]},
 | 
			
		||||
          discrete: {xs: [||], ys: [||]},
 | 
			
		||||
        }) =>
 | 
			
		||||
        None
 | 
			
		||||
      | Some({continuous, discrete: {xs: [||], ys: [||]}}) =>
 | 
			
		||||
        Some(Continuous(continuous))
 | 
			
		||||
      | Some({continuous: {xs: [||], ys: [||]}, discrete}) =>
 | 
			
		||||
        Some(Discrete(discrete))
 | 
			
		||||
      | Some(shape) => Some(Mixed(shape))
 | 
			
		||||
      | _ => None
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    newShape
 | 
			
		||||
    |> E.O.fmap((shape: DistributionTypes.pointsType) =>
 | 
			
		||||
    Guesstimator.stringToMixedShape(~string=s, ~sampleCount, ())
 | 
			
		||||
    |> E.O.bind(_, Shape.Mixed.clean)
 | 
			
		||||
    |> E.O.fmap((shape: DistributionTypes.shape) =>
 | 
			
		||||
         make(
 | 
			
		||||
           ~generationSource=Shape(shape),
 | 
			
		||||
           ~probabilityType=Cdf,
 | 
			
		||||
           ~probabilityType=Pdf,
 | 
			
		||||
           ~domain=t.domain,
 | 
			
		||||
           ~unit=t.unit,
 | 
			
		||||
           (),
 | 
			
		||||
         )
 | 
			
		||||
       );
 | 
			
		||||
       )
 | 
			
		||||
  | Shape(_) => Some(t)
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +66,7 @@ let renderIfNeeded =
 | 
			
		|||
let normalize = (t: genericDistribution): option(genericDistribution) => {
 | 
			
		||||
  switch (t.generationSource) {
 | 
			
		||||
  | Shape(shape) =>
 | 
			
		||||
    Shape.PointsType.normalizePdf(shape)
 | 
			
		||||
    Shape.T.Pdf.normalize(shape)
 | 
			
		||||
    |> E.O.fmap(shape => {...t, generationSource: Shape(shape)})
 | 
			
		||||
  | GuesstimatorString(_) => Some(t)
 | 
			
		||||
  };
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +77,7 @@ let yIntegral = (t: DistributionTypes.genericDistribution, x) => {
 | 
			
		|||
  let normalize = n => n *. Domain.normalizeProbabilityMass(t.domain);
 | 
			
		||||
  switch (t) {
 | 
			
		||||
  | {generationSource: Shape(shape)} =>
 | 
			
		||||
    Shape.PointsType.yIntegral(shape, x)
 | 
			
		||||
    Shape.T.yIntegral(shape, x)
 | 
			
		||||
    |> E.O.fmap(addInitialMass)
 | 
			
		||||
    |> E.O.fmap(normalize)
 | 
			
		||||
  | _ => None
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,8 @@ module XYShape = {
 | 
			
		|||
 | 
			
		||||
  let fmap = (t: t, y): t => {xs: t.xs, ys: t.ys |> E.A.fmap(y)};
 | 
			
		||||
 | 
			
		||||
  let pointwiseMap = (fn, t: t): t => {xs: t.xs, ys: t.ys |> E.A.fmap(fn)};
 | 
			
		||||
 | 
			
		||||
  let scaleCdfTo = (~scaleTo=1., t: t) =>
 | 
			
		||||
    switch (_lastElement(t.ys)) {
 | 
			
		||||
    | Some(n) =>
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +137,10 @@ module Discrete = {
 | 
			
		|||
  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);
 | 
			
		||||
| 
						 | 
				
			
			@ -214,13 +220,17 @@ module Mixed = {
 | 
			
		|||
  type yPdfPoint = {
 | 
			
		||||
    continuous: option(float),
 | 
			
		||||
    discrete: option(float),
 | 
			
		||||
    discreteProbabilityMassFraction: float,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let findY = (t: DistributionTypes.mixedShape, x: float): yPdfPoint => {
 | 
			
		||||
    continuous: Continuous.findY(x, t.continuous) |> E.O.some,
 | 
			
		||||
    discrete: Discrete.findY(x, t.discrete) |> E.O.some,
 | 
			
		||||
    discreteProbabilityMassFraction: t.discreteProbabilityMassFraction,
 | 
			
		||||
    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 =
 | 
			
		||||
| 
						 | 
				
			
			@ -232,10 +242,36 @@ module Mixed = {
 | 
			
		|||
    | _ => None
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let clean = (t: DistributionTypes.mixedShape) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | {continuous: {xs: [||], ys: [||]}, discrete: {xs: [||], ys: [||]}} =>
 | 
			
		||||
      None
 | 
			
		||||
    | {discrete: {xs: [|_|], ys: [|_|]}} => None
 | 
			
		||||
    | {continuous, discrete: {xs: [||], ys: [||]}} =>
 | 
			
		||||
      Some(Continuous(continuous))
 | 
			
		||||
    | {continuous: {xs: [||], ys: [||]}, discrete} =>
 | 
			
		||||
      Some(Discrete(discrete))
 | 
			
		||||
    | shape => Some(Mixed(shape))
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module PointsType = {
 | 
			
		||||
  type t = DistributionTypes.pointsType;
 | 
			
		||||
module T = {
 | 
			
		||||
  type t = DistributionTypes.shape;
 | 
			
		||||
 | 
			
		||||
  let mapToAll = (t: t, (fn1, fn2, fn3)) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed(m) => fn1(m)
 | 
			
		||||
    | Discrete(m) => fn2(m)
 | 
			
		||||
    | Continuous(m) => fn3(m)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  let fmap = (t: t, (fn1, fn2, fn3)) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed(m) => Mixed(fn1(m))
 | 
			
		||||
    | Discrete(m) => Discrete(fn2(m))
 | 
			
		||||
    | Continuous(m) => Continuous(fn3(m))
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  let y = (t: t, x: float) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
| 
						 | 
				
			
			@ -268,22 +304,6 @@ module PointsType = {
 | 
			
		|||
    | Continuous(continuousShape) => Continuous.maxX(continuousShape)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  // TODO: This is wrong. The discrete component should be made continuous when integrating.
 | 
			
		||||
  let pdfToCdf = (t: t) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
 | 
			
		||||
      Some(
 | 
			
		||||
        Mixed({
 | 
			
		||||
          continuous: Continuous.toCdf(continuous) |> E.O.toExt(""),
 | 
			
		||||
          discrete: discrete |> Discrete.integrate,
 | 
			
		||||
          discreteProbabilityMassFraction,
 | 
			
		||||
        }),
 | 
			
		||||
      )
 | 
			
		||||
    | Discrete(discrete) => Some(Continuous(discrete |> Discrete.integrate))
 | 
			
		||||
    | Continuous(continuous) =>
 | 
			
		||||
      Continuous.toCdf(continuous) |> E.O.fmap(e => Continuous(e))
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
  let discreteComponent = (t: t) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed({discrete}) => Some(discrete)
 | 
			
		||||
| 
						 | 
				
			
			@ -319,37 +339,123 @@ module PointsType = {
 | 
			
		|||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let normalizeCdf = (t: DistributionTypes.pointsType) => {
 | 
			
		||||
  let pointwiseFmap = (fn, t: t): shape =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
 | 
			
		||||
    | Mixed({discrete, continuous, discreteProbabilityMassFraction}) =>
 | 
			
		||||
      Mixed({
 | 
			
		||||
        continuous: continuous |> Continuous.normalizeCdf,
 | 
			
		||||
        discrete: discrete |> Discrete.scaleYToTotal(1.0),
 | 
			
		||||
        continuous: XYShape.pointwiseMap(fn, continuous),
 | 
			
		||||
        discrete: XYShape.pointwiseMap(fn, discrete),
 | 
			
		||||
        discreteProbabilityMassFraction,
 | 
			
		||||
      })
 | 
			
		||||
    | Discrete(d) => Discrete(d |> Discrete.scaleYToTotal(1.0))
 | 
			
		||||
    | Continuous(continuousShape) =>
 | 
			
		||||
      Continuous(Continuous.normalizeCdf(continuousShape))
 | 
			
		||||
    | 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))
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let normalizePdf = (t: DistributionTypes.pointsType) => {
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
 | 
			
		||||
      continuous
 | 
			
		||||
      |> Continuous.scalePdf(~scaleTo=1.0)
 | 
			
		||||
      |> E.O.fmap(r =>
 | 
			
		||||
           Mixed({
 | 
			
		||||
             continuous: r,
 | 
			
		||||
             discrete: discrete |> Discrete.scaleYToTotal(1.0),
 | 
			
		||||
             discreteProbabilityMassFraction,
 | 
			
		||||
           })
 | 
			
		||||
         )
 | 
			
		||||
    | Discrete(d) => Some(Discrete(d |> Discrete.scaleYToTotal(1.0)))
 | 
			
		||||
    | Continuous(continuousShape) =>
 | 
			
		||||
      continuousShape
 | 
			
		||||
      |> Continuous.scalePdf(~scaleTo=1.0)
 | 
			
		||||
      |> E.O.fmap(r => Continuous(r))
 | 
			
		||||
  module Pdf = {
 | 
			
		||||
    // TODO: This is wrong. The discrete component should be made continuous when integrating.
 | 
			
		||||
    let toCdf = (t: t) =>
 | 
			
		||||
      switch (t) {
 | 
			
		||||
      | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
 | 
			
		||||
        Some(
 | 
			
		||||
          Mixed({
 | 
			
		||||
            continuous: Continuous.toCdf(continuous) |> E.O.toExt(""),
 | 
			
		||||
            discrete: discrete |> Discrete.integrate,
 | 
			
		||||
            discreteProbabilityMassFraction,
 | 
			
		||||
          }),
 | 
			
		||||
        )
 | 
			
		||||
      | Discrete(discrete) =>
 | 
			
		||||
        Some(Continuous(discrete |> Discrete.integrate))
 | 
			
		||||
      | Continuous(continuous) =>
 | 
			
		||||
        Continuous.toCdf(continuous) |> E.O.fmap(e => Continuous(e))
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    let normalize = (t: DistributionTypes.shape): option(shape) => {
 | 
			
		||||
      switch (t) {
 | 
			
		||||
      | Mixed({continuous, discrete, discreteProbabilityMassFraction}) =>
 | 
			
		||||
        continuous
 | 
			
		||||
        |> Continuous.scalePdf(~scaleTo=1.0)
 | 
			
		||||
        |> E.O.fmap(r =>
 | 
			
		||||
             Mixed({
 | 
			
		||||
               continuous: r,
 | 
			
		||||
               discrete: discrete |> Discrete.scaleYToTotal(1.0),
 | 
			
		||||
               discreteProbabilityMassFraction,
 | 
			
		||||
             })
 | 
			
		||||
           )
 | 
			
		||||
      | Discrete(d) => Some(Discrete(d |> Discrete.scaleYToTotal(1.0)))
 | 
			
		||||
      | Continuous(continuousShape) =>
 | 
			
		||||
        continuousShape
 | 
			
		||||
        |> Continuous.scalePdf(~scaleTo=1.0)
 | 
			
		||||
        |> E.O.fmap(r => Continuous(r))
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let toPdfCdfCombo = (t: t): option(pdfCdfCombo) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | Mixed({continuous, discrete, discreteProbabilityMassFraction} as tt) =>
 | 
			
		||||
      Some({
 | 
			
		||||
        cdf: continuous |> Continuous.toCdf |> E.O.toExt(""),
 | 
			
		||||
        pdf: Mixed(tt),
 | 
			
		||||
      })
 | 
			
		||||
    | Discrete(d) => Some({cdf: d |> Discrete.integrate, pdf: Discrete(d)})
 | 
			
		||||
    | Continuous(c) =>
 | 
			
		||||
      Some({
 | 
			
		||||
        cdf: c |> Continuous.toCdf |> E.O.toExt(""),
 | 
			
		||||
        pdf: Continuous(c),
 | 
			
		||||
      })
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										5
									
								
								src/core/Try24.re
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/core/Try24.re
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
open DistributionTypes;
 | 
			
		||||
 | 
			
		||||
module Shappe = {
 | 
			
		||||
  type t = shape;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ module Internals = {
 | 
			
		|||
  [@bs.module "./GuesstimatorLibrary.js"]
 | 
			
		||||
  external toCombinedFormat: (string, int) => combined = "run";
 | 
			
		||||
 | 
			
		||||
  // todo: Format to correct mass, also normalize the pdf.
 | 
			
		||||
  let toMixedShape = (r: combined): option(DistributionTypes.mixedShape) => {
 | 
			
		||||
    let assumptions: MixedShapeBuilder.assumptions = {
 | 
			
		||||
      continuous: ADDS_TO_1,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user