Merge pull request #2 from foretold-app/Shape-manipulations
Shape manipulations
This commit is contained in:
		
						commit
						a40bd21eb9
					
				
							
								
								
									
										26
									
								
								__tests__/Foo/Foo__Test.re
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								__tests__/Foo/Foo__Test.re
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					open Jest;
 | 
				
			||||||
 | 
					open Expect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let shape: DistributionTypes.xyShape = {
 | 
				
			||||||
 | 
					  xs: [|1., 4., 8.|],
 | 
				
			||||||
 | 
					  ys: [|8., 9., 2.|],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					open Shape;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe("Shape", () =>
 | 
				
			||||||
 | 
					  describe("XYShape", () =>
 | 
				
			||||||
 | 
					    test("#ySum", ()
 | 
				
			||||||
 | 
					      =>
 | 
				
			||||||
 | 
					        expect(XYShape.ySum(shape)) |> toEqual(19.0)
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      // test("#both", () => {
 | 
				
			||||||
 | 
					      //   let expected: DistributionTypes.xyShape = {
 | 
				
			||||||
 | 
					      //     xs: [|1., 4., 8.|],
 | 
				
			||||||
 | 
					      //     ys: [|8., 1., 1.|],
 | 
				
			||||||
 | 
					      //   };
 | 
				
			||||||
 | 
					      //   expect(shape |> XYShape.derivative |> XYShape.integral)
 | 
				
			||||||
 | 
					      //   |> toEqual(shape);
 | 
				
			||||||
 | 
					      // });
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,11 @@
 | 
				
			||||||
      "dir": "showcase",
 | 
					      "dir": "showcase",
 | 
				
			||||||
      "type": "dev",
 | 
					      "type": "dev",
 | 
				
			||||||
      "subdirs": true
 | 
					      "subdirs": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "dir": "__tests__",
 | 
				
			||||||
 | 
					      "type": "dev",
 | 
				
			||||||
 | 
					      "subdirs": true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "bsc-flags": ["-bs-super-errors", "-bs-no-version-header"],
 | 
					  "bsc-flags": ["-bs-super-errors", "-bs-no-version-header"],
 | 
				
			||||||
| 
						 | 
					@ -21,6 +26,7 @@
 | 
				
			||||||
  "suffix": ".bs.js",
 | 
					  "suffix": ".bs.js",
 | 
				
			||||||
  "namespace": true,
 | 
					  "namespace": true,
 | 
				
			||||||
  "bs-dependencies": [
 | 
					  "bs-dependencies": [
 | 
				
			||||||
 | 
					    "@glennsl/bs-jest",
 | 
				
			||||||
    "@foretold/components",
 | 
					    "@foretold/components",
 | 
				
			||||||
    "bs-ant-design-alt",
 | 
					    "bs-ant-design-alt",
 | 
				
			||||||
    "reason-react",
 | 
					    "reason-react",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,10 @@
 | 
				
			||||||
    "server": "moduleserve ./ --port 8000",
 | 
					    "server": "moduleserve ./ --port 8000",
 | 
				
			||||||
    "predeploy": "parcel build ./src/index.html --no-source-maps --no-autoinstall",
 | 
					    "predeploy": "parcel build ./src/index.html --no-source-maps --no-autoinstall",
 | 
				
			||||||
    "deploy": "gh-pages -d dist",
 | 
					    "deploy": "gh-pages -d dist",
 | 
				
			||||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
					    "test": "jest",
 | 
				
			||||||
 | 
					    "test:ci": "yarn jest",
 | 
				
			||||||
 | 
					    "watch:test": "jest --watchAll",
 | 
				
			||||||
 | 
					    "watch:s": "yarn jest -- Converter_test --watch"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "keywords": [
 | 
					  "keywords": [
 | 
				
			||||||
    "BuckleScript",
 | 
					    "BuckleScript",
 | 
				
			||||||
| 
						 | 
					@ -26,13 +29,16 @@
 | 
				
			||||||
    "@foretold/cdf": "^1.0.15",
 | 
					    "@foretold/cdf": "^1.0.15",
 | 
				
			||||||
    "@foretold/components": "^0.0.3",
 | 
					    "@foretold/components": "^0.0.3",
 | 
				
			||||||
    "@foretold/guesstimator": "^1.0.10",
 | 
					    "@foretold/guesstimator": "^1.0.10",
 | 
				
			||||||
 | 
					    "@glennsl/bs-jest": "^0.4.9",
 | 
				
			||||||
    "antd": "3.17.0",
 | 
					    "antd": "3.17.0",
 | 
				
			||||||
    "autoprefixer": "^9.7.4",
 | 
					    "autoprefixer": "^9.7.4",
 | 
				
			||||||
 | 
					    "babel-jest": "^25.1.0",
 | 
				
			||||||
    "bs-ant-design-alt": "2.0.0-alpha.31",
 | 
					    "bs-ant-design-alt": "2.0.0-alpha.31",
 | 
				
			||||||
    "bs-css": "^11.0.0",
 | 
					    "bs-css": "^11.0.0",
 | 
				
			||||||
    "bs-moment": "0.4.4",
 | 
					    "bs-moment": "0.4.4",
 | 
				
			||||||
    "bs-reform": "9.7.1",
 | 
					    "bs-reform": "9.7.1",
 | 
				
			||||||
    "d3": "^5.15.0",
 | 
					    "d3": "^5.15.0",
 | 
				
			||||||
 | 
					    "jest": "^25.1.0",
 | 
				
			||||||
    "lenses-ppx": "4.0.0",
 | 
					    "lenses-ppx": "4.0.0",
 | 
				
			||||||
    "less": "^3.10.3",
 | 
					    "less": "^3.10.3",
 | 
				
			||||||
    "lodash": "^4.17.15",
 | 
					    "lodash": "^4.17.15",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,9 @@ let data: DistributionTypes.xyShape = {
 | 
				
			||||||
let mixedDist =
 | 
					let mixedDist =
 | 
				
			||||||
  GenericDistribution.make(
 | 
					  GenericDistribution.make(
 | 
				
			||||||
    ~generationSource=
 | 
					    ~generationSource=
 | 
				
			||||||
      GuesstimatorString("mm(uniform(10,12), normal(5,1), [.5,.5])"),
 | 
					      GuesstimatorString(
 | 
				
			||||||
 | 
					        "mm(floor(uniform(20, 30)), normal(50,10), [.5,.5])",
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
    ~probabilityType=Pdf,
 | 
					    ~probabilityType=Pdf,
 | 
				
			||||||
    ~domain=Complete,
 | 
					    ~domain=Complete,
 | 
				
			||||||
    ~unit=Unspecified,
 | 
					    ~unit=Unspecified,
 | 
				
			||||||
| 
						 | 
					@ -42,14 +44,14 @@ let distributions = () =>
 | 
				
			||||||
      <h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
 | 
					      <h2> {"Basic Mixed Distribution" |> ReasonReact.string} </h2>
 | 
				
			||||||
      <GenericDistributionChart dist=mixedDist />
 | 
					      <GenericDistributionChart dist=mixedDist />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div>
 | 
					 | 
				
			||||||
      <h2> {"Time Distribution" |> ReasonReact.string} </h2>
 | 
					 | 
				
			||||||
      <GenericDistributionChart dist=timeDist />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <div>
 | 
					 | 
				
			||||||
      <h2> {"Domain Limited Distribution" |> ReasonReact.string} </h2>
 | 
					 | 
				
			||||||
      <GenericDistributionChart dist=domainLimitedDist />
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </div>;
 | 
					  </div>;
 | 
				
			||||||
 | 
					// <div>
 | 
				
			||||||
 | 
					//   <h2> {"Time Distribution" |> ReasonReact.string} </h2>
 | 
				
			||||||
 | 
					//   <GenericDistributionChart dist=timeDist />
 | 
				
			||||||
 | 
					// </div>
 | 
				
			||||||
 | 
					// <div>
 | 
				
			||||||
 | 
					//   <h2> {"Domain Limited Distribution" |> ReasonReact.string} </h2>
 | 
				
			||||||
 | 
					//   <GenericDistributionChart dist=domainLimitedDist />
 | 
				
			||||||
 | 
					// </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let entry = EntryTypes.(entry(~title="Pdf", ~render=distributions));
 | 
					let entry = EntryTypes.(entry(~title="Pdf", ~render=distributions));
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,11 @@ module Continuous = {
 | 
				
			||||||
               |> ReasonReact.string}
 | 
					               |> ReasonReact.string}
 | 
				
			||||||
            </th>
 | 
					            </th>
 | 
				
			||||||
            <th className="px-4 py-2 border ">
 | 
					            <th className="px-4 py-2 border ">
 | 
				
			||||||
              {Shape.Continuous.findY(x, Shape.XYShape.integral(data))
 | 
					              {Shape.Continuous.findY(
 | 
				
			||||||
 | 
					                 x,
 | 
				
			||||||
 | 
					                 Shape.XYShape.Range.integrateWithTriangles(data)
 | 
				
			||||||
 | 
					                 |> E.O.toExt(""),
 | 
				
			||||||
 | 
					               )
 | 
				
			||||||
               |> E.Float.with2DigitsPrecision
 | 
					               |> E.Float.with2DigitsPrecision
 | 
				
			||||||
               |> ReasonReact.string}
 | 
					               |> ReasonReact.string}
 | 
				
			||||||
            </th>
 | 
					            </th>
 | 
				
			||||||
| 
						 | 
					@ -47,6 +51,51 @@ module Continuous = {
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module Mixed = {
 | 
				
			||||||
 | 
					  [@react.component]
 | 
				
			||||||
 | 
					  let make = (~data: DistributionTypes.mixedShape) => {
 | 
				
			||||||
 | 
					    let (x, setX) = React.useState(() => 0.);
 | 
				
			||||||
 | 
					    let chart =
 | 
				
			||||||
 | 
					      React.useMemo1(
 | 
				
			||||||
 | 
					        () =>
 | 
				
			||||||
 | 
					          <CdfChart__Plain
 | 
				
			||||||
 | 
					            data={data.continuous}
 | 
				
			||||||
 | 
					            color={`hex("333")}
 | 
				
			||||||
 | 
					            onHover={r => setX(_ => r)}
 | 
				
			||||||
 | 
					          />,
 | 
				
			||||||
 | 
					        [|data|],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    <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 Pount" |> 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 ">
 | 
				
			||||||
 | 
					              {Shape.Mixed.getYIntegral(x, data)
 | 
				
			||||||
 | 
					               |> E.O.fmap(E.Float.with2DigitsPrecision)
 | 
				
			||||||
 | 
					               |> E.O.default("")
 | 
				
			||||||
 | 
					               |> ReasonReact.string}
 | 
				
			||||||
 | 
					            </th>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
 | 
					      </table>
 | 
				
			||||||
 | 
					      <div />
 | 
				
			||||||
 | 
					    </div>;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[@react.component]
 | 
					[@react.component]
 | 
				
			||||||
let make = (~dist) => {
 | 
					let make = (~dist) => {
 | 
				
			||||||
  switch ((dist: option(DistributionTypes.genericDistribution))) {
 | 
					  switch ((dist: option(DistributionTypes.genericDistribution))) {
 | 
				
			||||||
| 
						 | 
					@ -62,7 +111,38 @@ let make = (~dist) => {
 | 
				
			||||||
    }) =>
 | 
					    }) =>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
      <Continuous data=n />
 | 
					      <Continuous data=n />
 | 
				
			||||||
      <Continuous data={n |> Shape.XYShape.integral} />
 | 
					      <Continuous
 | 
				
			||||||
 | 
					        data={
 | 
				
			||||||
 | 
					          n
 | 
				
			||||||
 | 
					          |> Shape.XYShape.Range.integrateWithTriangles
 | 
				
			||||||
 | 
					          |> E.O.toExt("")
 | 
				
			||||||
 | 
					          |> Shape.XYShape.scaleCdfTo
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <Mixed
 | 
				
			||||||
 | 
					        data={
 | 
				
			||||||
 | 
					          continuous:
 | 
				
			||||||
 | 
					            n
 | 
				
			||||||
 | 
					            |> Shape.Continuous.toCdf
 | 
				
			||||||
 | 
					            |> E.O.toExt("")
 | 
				
			||||||
 | 
					            |> Shape.XYShape.scaleCdfTo
 | 
				
			||||||
 | 
					            |> Shape.Continuous.toPdf
 | 
				
			||||||
 | 
					            |> E.O.toExt(""),
 | 
				
			||||||
 | 
					          discrete: d,
 | 
				
			||||||
 | 
					          discreteProbabilityMassFraction: f,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <Continuous
 | 
				
			||||||
 | 
					        data={
 | 
				
			||||||
 | 
					          n
 | 
				
			||||||
 | 
					          |> Shape.XYShape.Range.integrateWithTriangles
 | 
				
			||||||
 | 
					          |> E.O.toExt("")
 | 
				
			||||||
 | 
					          |> Shape.XYShape.Range.derivative
 | 
				
			||||||
 | 
					          |> E.O.toExt("")
 | 
				
			||||||
 | 
					          |> Shape.XYShape.Range.integrateWithTriangles
 | 
				
			||||||
 | 
					          |> E.O.toExt("")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
      {d |> Shape.Discrete.scaleYToTotal(f) |> Shape.Discrete.render}
 | 
					      {d |> Shape.Discrete.scaleYToTotal(f) |> Shape.Discrete.render}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  | _ => <div />
 | 
					  | _ => <div />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,50 +19,103 @@ module XYShape = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let fmap = (t: t, y): t => {xs: t.xs, ys: t.ys |> E.A.fmap(y)};
 | 
					  let fmap = (t: t, y): t => {xs: t.xs, ys: t.ys |> E.A.fmap(y)};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let scaleCdfTo = (~scaleTo=1., t: t) =>
 | 
				
			||||||
 | 
					    switch (_lastElement(t.ys)) {
 | 
				
			||||||
 | 
					    | Some(n) =>
 | 
				
			||||||
 | 
					      let scaleBy = scaleTo /. n;
 | 
				
			||||||
 | 
					      fmap(t, r => r *. scaleBy);
 | 
				
			||||||
 | 
					    | None => t
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let yFold = (fn, t: t) => {
 | 
					  let yFold = (fn, t: t) => {
 | 
				
			||||||
    E.A.fold_left(fn, 0., t.ys);
 | 
					    E.A.fold_left(fn, 0., t.ys);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let ySum = yFold((a, b) => a +. b);
 | 
					  let ySum = yFold((a, b) => a +. b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let fromArray = ((xs, ys)): t => {xs, ys};
 | 
				
			||||||
  let fromArrays = (xs, ys): t => {xs, ys};
 | 
					  let fromArrays = (xs, ys): t => {xs, ys};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let transverse = (fn, p: t) => {
 | 
					  let _transverse = fn =>
 | 
				
			||||||
    let (xs, ys) =
 | 
					    Belt.Array.reduce(_, [||], (items, (x, y)) =>
 | 
				
			||||||
      Belt.Array.zip(p.xs, p.ys)
 | 
					 | 
				
			||||||
      ->Belt.Array.reduce([||], (items, (x, y)) =>
 | 
					 | 
				
			||||||
      switch (_lastElement(items)) {
 | 
					      switch (_lastElement(items)) {
 | 
				
			||||||
          | Some((_, yLast)) =>
 | 
					      | Some((xLast, yLast)) =>
 | 
				
			||||||
        Belt.Array.concat(items, [|(x, fn(y, yLast))|])
 | 
					        Belt.Array.concat(items, [|(x, fn(y, yLast))|])
 | 
				
			||||||
      | None => [|(x, y)|]
 | 
					      | None => [|(x, y)|]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
        )
 | 
					    );
 | 
				
			||||||
      |> Belt.Array.unzip;
 | 
					
 | 
				
			||||||
    fromArrays(xs, ys);
 | 
					  let _transverseShape = (fn, p: t) => {
 | 
				
			||||||
 | 
					    Belt.Array.zip(p.xs, p.ys)
 | 
				
			||||||
 | 
					    |> _transverse(fn)
 | 
				
			||||||
 | 
					    |> Belt.Array.unzip
 | 
				
			||||||
 | 
					    |> fromArray;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let getY = (t: t, x: float) => x;
 | 
					  let accumulateYs = _transverseShape((aCurrent, aLast) => aCurrent +. aLast);
 | 
				
			||||||
 | 
					  let subtractYs = _transverseShape((aCurrent, aLast) => aCurrent -. aLast);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let integral = transverse((aCurrent, aLast) => aCurrent +. aLast);
 | 
					  module Range = {
 | 
				
			||||||
  let derivative = transverse((aCurrent, aLast) => aCurrent -. aLast);
 | 
					    // ((lastX, lastY), (nextX, nextY))
 | 
				
			||||||
 | 
					    type zippedRange = ((float, float), (float, float));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let massWithin = (t: t, left: pointInRange, right: pointInRange) => {
 | 
					    let floatSum = Belt.Array.reduce(_, 0., (a, b) => a +. b);
 | 
				
			||||||
    switch (left, right) {
 | 
					    let toT = r => r |> Belt.Array.unzip |> fromArray;
 | 
				
			||||||
    | (Unbounded, Unbounded) => t |> ySum
 | 
					    let nextX = ((_, (nextX, _)): zippedRange) => nextX;
 | 
				
			||||||
    | (Unbounded, X(f)) => t |> integral |> getY(_, f)
 | 
					
 | 
				
			||||||
    | (X(f), Unbounded) => ySum(t) -. getY(integral(t), f)
 | 
					    let rangeAreaAssumingSteps =
 | 
				
			||||||
    | (X(l), X(r)) => getY(integral(t), r) -. getY(integral(t), l)
 | 
					        (((lastX, lastY), (nextX, _)): zippedRange) =>
 | 
				
			||||||
 | 
					      (nextX -. lastX) *. lastY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let rangeAreaAssumingTriangles =
 | 
				
			||||||
 | 
					        (((lastX, lastY), (nextX, nextY)): zippedRange) =>
 | 
				
			||||||
 | 
					      (nextX -. lastX) *. (lastY +. nextY) /. 2.;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let delta_y_over_delta_x =
 | 
				
			||||||
 | 
					        (((lastX, lastY), (nextX, nextY)): zippedRange) =>
 | 
				
			||||||
 | 
					      (nextY -. lastY) /. (nextX -. lastX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let inRanges = (mapper, reducer, t: t) => {
 | 
				
			||||||
 | 
					      Belt.Array.zip(t.xs, t.ys)
 | 
				
			||||||
 | 
					      |> E.A.toRanges
 | 
				
			||||||
 | 
					      |> E.R.toOption
 | 
				
			||||||
 | 
					      |> E.O.fmap(r => r |> Belt.Array.map(_, mapper) |> reducer);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mapYsBasedOnRanges = fn => inRanges(r => (nextX(r), fn(r)), toT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let toStepFn = z => mapYsBasedOnRanges(rangeAreaAssumingSteps, z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let integrateWithSteps = z =>
 | 
				
			||||||
 | 
					      mapYsBasedOnRanges(rangeAreaAssumingSteps, z) |> E.O.fmap(accumulateYs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let integrateWithTriangles = z =>
 | 
				
			||||||
 | 
					      mapYsBasedOnRanges(rangeAreaAssumingTriangles, z)
 | 
				
			||||||
 | 
					      |> E.O.fmap(accumulateYs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let derivative = mapYsBasedOnRanges(delta_y_over_delta_x);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let findY = CdfLibrary.Distribution.findY;
 | 
				
			||||||
 | 
					  let findX = CdfLibrary.Distribution.findX;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					// let massWithin = (t: t, left: pointInRange, right: pointInRange) => {
 | 
				
			||||||
 | 
					//   switch (left, right) {
 | 
				
			||||||
 | 
					//   | (Unbounded, Unbounded) => t |> ySum
 | 
				
			||||||
 | 
					//   | (Unbounded, X(f)) => t |> integral |> getY(t, 3.0)
 | 
				
			||||||
 | 
					//   | (X(f), Unbounded) => ySum(t) -. getY(integral(t), f)
 | 
				
			||||||
 | 
					//   | (X(l), X(r)) => getY(integral(t), r) -. getY(integral(t), l)
 | 
				
			||||||
 | 
					//   };
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Continuous = {
 | 
					module Continuous = {
 | 
				
			||||||
  let fromArrays = XYShape.fromArrays;
 | 
					  let fromArrays = XYShape.fromArrays;
 | 
				
			||||||
  let toJs = XYShape.toJs;
 | 
					  let toJs = XYShape.toJs;
 | 
				
			||||||
  let toPdf = CdfLibrary.Distribution.toPdf;
 | 
					  let toPdf = XYShape.Range.derivative;
 | 
				
			||||||
  let toCdf = CdfLibrary.Distribution.toCdf;
 | 
					  let toCdf = XYShape.Range.integrateWithTriangles;
 | 
				
			||||||
  let findX = CdfLibrary.Distribution.findX;
 | 
					  let findX = CdfLibrary.Distribution.findX;
 | 
				
			||||||
  let findY = CdfLibrary.Distribution.findY;
 | 
					  let findY = CdfLibrary.Distribution.findY;
 | 
				
			||||||
 | 
					  let findIntegralY = (f, r) => r |> toCdf |> E.O.fmap(findY(f));
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Discrete = {
 | 
					module Discrete = {
 | 
				
			||||||
| 
						 | 
					@ -94,6 +147,18 @@ module Discrete = {
 | 
				
			||||||
    | Some((_, y)) => y
 | 
					    | Some((_, y)) => y
 | 
				
			||||||
    | None => 0.
 | 
					    | None => 0.
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let integrate = XYShape.accumulateYs;
 | 
				
			||||||
 | 
					  let derivative = XYShape.subtractYs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let findIntegralY = (f, t: t) =>
 | 
				
			||||||
 | 
					    t
 | 
				
			||||||
 | 
					    |> XYShape.Range.toStepFn
 | 
				
			||||||
 | 
					    |> E.O.fmap(XYShape.accumulateYs)
 | 
				
			||||||
 | 
					    |> E.O.fmap(CdfLibrary.Distribution.findY(f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let findX = (f, t: t) =>
 | 
				
			||||||
 | 
					    t |> XYShape.Range.toStepFn |> E.O.fmap(CdfLibrary.Distribution.findX(f));
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Mixed = {
 | 
					module Mixed = {
 | 
				
			||||||
| 
						 | 
					@ -103,15 +168,41 @@ module Mixed = {
 | 
				
			||||||
    discreteProbabilityMassFraction,
 | 
					    discreteProbabilityMassFraction,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let mixedMultiply =
 | 
				
			||||||
 | 
					      (
 | 
				
			||||||
 | 
					        t: DistributionTypes.mixedShape,
 | 
				
			||||||
 | 
					        continuousComponent,
 | 
				
			||||||
 | 
					        discreteComponent,
 | 
				
			||||||
 | 
					      ) => {
 | 
				
			||||||
 | 
					    let diffFn = t.discreteProbabilityMassFraction;
 | 
				
			||||||
 | 
					    continuousComponent *. (1.0 -. diffFn) +. discreteComponent *. diffFn;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  type yPdfPoint = {
 | 
					  type yPdfPoint = {
 | 
				
			||||||
    continuous: float,
 | 
					    continuous: option(float),
 | 
				
			||||||
    discrete: float,
 | 
					    discrete: option(float),
 | 
				
			||||||
 | 
					    discreteProbabilityMassFraction: float,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let getY = (t: DistributionTypes.mixedShape, x: float): yPdfPoint => {
 | 
					  let getY = (t: DistributionTypes.mixedShape, x: float): yPdfPoint => {
 | 
				
			||||||
    continuous: Continuous.findY(x, t.continuous),
 | 
					    continuous: Continuous.findY(x, t.continuous) |> E.O.some,
 | 
				
			||||||
    discrete: Discrete.findY(x, t.discrete),
 | 
					    discrete: Discrete.findY(x, t.discrete) |> E.O.some,
 | 
				
			||||||
 | 
					    discreteProbabilityMassFraction: t.discreteProbabilityMassFraction,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let getYIntegral =
 | 
				
			||||||
 | 
					      (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), Some(d)) => Some(mixedMultiply(t, c, d))
 | 
				
			||||||
 | 
					    | _ => None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  //Do the math to add these distributions together
 | 
				
			||||||
 | 
					  // let integral =
 | 
				
			||||||
 | 
					  //     (x: float, t: DistributionTypes.mixedShape): option(XYShape.t) => {
 | 
				
			||||||
 | 
					  // };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Any = {
 | 
					module Any = {
 | 
				
			||||||
| 
						 | 
					@ -124,13 +215,6 @@ module Any = {
 | 
				
			||||||
    | Continuous(continuousShape) =>
 | 
					    | Continuous(continuousShape) =>
 | 
				
			||||||
      `continuous(Continuous.findY(x, continuousShape))
 | 
					      `continuous(Continuous.findY(x, continuousShape))
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
  let massInRange = (t: t, left: pointInRange, right: pointInRange) =>
 | 
					 | 
				
			||||||
    switch (t) {
 | 
					 | 
				
			||||||
    | Mixed(m) => 3.0
 | 
					 | 
				
			||||||
    | Discrete(discreteShape) => 2.0
 | 
					 | 
				
			||||||
    | Continuous(continuousShape) => 3.0
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module DomainMixed = {
 | 
					module DomainMixed = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/lib/E.re
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/lib/E.re
									
									
									
									
									
								
							| 
						 | 
					@ -114,6 +114,11 @@ module R = {
 | 
				
			||||||
  let id = e => e |> result(U.id, U.id);
 | 
					  let id = e => e |> result(U.id, U.id);
 | 
				
			||||||
  let fmap = Rationale.Result.fmap;
 | 
					  let fmap = Rationale.Result.fmap;
 | 
				
			||||||
  let bind = Rationale.Result.bind;
 | 
					  let bind = Rationale.Result.bind;
 | 
				
			||||||
 | 
					  let toOption = (e: Belt.Result.t('a, 'b)) =>
 | 
				
			||||||
 | 
					    switch (e) {
 | 
				
			||||||
 | 
					    | Ok(r) => Some(r)
 | 
				
			||||||
 | 
					    | Error(_) => None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let safe_fn_of_string = (fn, s: string): option('a) =>
 | 
					let safe_fn_of_string = (fn, s: string): option('a) =>
 | 
				
			||||||
| 
						 | 
					@ -217,6 +222,20 @@ module A = {
 | 
				
			||||||
  let concatMany = Belt.Array.concatMany;
 | 
					  let concatMany = Belt.Array.concatMany;
 | 
				
			||||||
  let keepMap = Belt.Array.keepMap;
 | 
					  let keepMap = Belt.Array.keepMap;
 | 
				
			||||||
  let stableSortBy = Belt.SortArray.stableSortBy;
 | 
					  let stableSortBy = Belt.SortArray.stableSortBy;
 | 
				
			||||||
 | 
					  let toRanges = (a: array('a)) =>
 | 
				
			||||||
 | 
					    switch (a |> Belt.Array.length) {
 | 
				
			||||||
 | 
					    | 0
 | 
				
			||||||
 | 
					    | 1 => Belt.Result.Error("Must be at least 2 elements")
 | 
				
			||||||
 | 
					    | n =>
 | 
				
			||||||
 | 
					      Belt.Array.makeBy(n - 1, r => r)
 | 
				
			||||||
 | 
					      |> Belt.Array.map(_, index =>
 | 
				
			||||||
 | 
					           (
 | 
				
			||||||
 | 
					             Belt.Array.getUnsafe(a, index),
 | 
				
			||||||
 | 
					             Belt.Array.getUnsafe(a, index + 1),
 | 
				
			||||||
 | 
					           )
 | 
				
			||||||
 | 
					         )
 | 
				
			||||||
 | 
					      |> Rationale.Result.return
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let asList = (f: list('a) => list('a), r: array('a)) =>
 | 
					  let asList = (f: list('a) => list('a), r: array('a)) =>
 | 
				
			||||||
    r |> to_list |> f |> of_list;
 | 
					    r |> to_list |> f |> of_list;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user