Continuous integration should include first item
This commit is contained in:
parent
8d7a6f7f6c
commit
24dc4e657e
|
@ -11,7 +11,7 @@ let makeTest = (str, item1, item2) =>
|
|||
describe("Shape", () => {
|
||||
describe("Continuous", () => {
|
||||
open Distributions.Continuous;
|
||||
let continuous = make(shape, `Stepwise);
|
||||
let continuous = make(shape, `Linear);
|
||||
makeTest("minX", T.minX(continuous), Some(1.0));
|
||||
makeTest("maxX", T.maxX(continuous), Some(8.0));
|
||||
makeTest(
|
||||
|
@ -19,32 +19,75 @@ describe("Shape", () => {
|
|||
T.pointwiseFmap(r => r *. 2.0, continuous) |> getShape |> (r => r.ys),
|
||||
[|16., 18.0, 4.0|],
|
||||
);
|
||||
makeTest(
|
||||
"xToY at 4.0",
|
||||
T.xToY(4., continuous),
|
||||
{continuous: 9.0, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"xToY at 0.0",
|
||||
T.xToY(0., continuous),
|
||||
{continuous: 8.0, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"xToY at 5.0",
|
||||
T.xToY(5., continuous),
|
||||
{continuous: 7.25, discrete: 0.0},
|
||||
);
|
||||
describe("xToY", () => {
|
||||
describe("when Linear", () => {
|
||||
makeTest(
|
||||
"at 4.0",
|
||||
T.xToY(4., continuous),
|
||||
{continuous: 9.0, discrete: 0.0},
|
||||
);
|
||||
// Note: This below is weird to me, I'm not sure if it's what we want really.
|
||||
makeTest(
|
||||
"at 0.0",
|
||||
T.xToY(0., continuous),
|
||||
{continuous: 8.0, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"at 5.0",
|
||||
T.xToY(5., continuous),
|
||||
{continuous: 7.25, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"at 10.0",
|
||||
T.xToY(10., continuous),
|
||||
{continuous: 2.0, discrete: 0.0},
|
||||
);
|
||||
});
|
||||
describe("when Stepwise", () => {
|
||||
let continuous = make(shape, `Stepwise);
|
||||
makeTest(
|
||||
"at 4.0",
|
||||
T.xToY(4., continuous),
|
||||
{continuous: 9.0, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"at 0.0",
|
||||
T.xToY(0., continuous),
|
||||
{continuous: 0.0, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"at 5.0",
|
||||
T.xToY(5., continuous),
|
||||
{continuous: 9.0, discrete: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"at 10.0",
|
||||
T.xToY(10., continuous),
|
||||
{continuous: 2.0, discrete: 0.0},
|
||||
);
|
||||
});
|
||||
});
|
||||
makeTest(
|
||||
"integral",
|
||||
T.Integral.get(~cache=None, continuous) |> getShape,
|
||||
{xs: [|4.0, 8.0|], ys: [|25.5, 47.5|]},
|
||||
{xs: [|1.0, 4.0, 8.0|], ys: [|0.0, 25.5, 47.5|]},
|
||||
);
|
||||
makeTest(
|
||||
"integralXToY",
|
||||
T.Integral.xToY(~cache=None, 0.0, continuous),
|
||||
0.0,
|
||||
);
|
||||
makeTest(
|
||||
"integralXToY",
|
||||
T.Integral.xToY(~cache=None, 2.0, continuous),
|
||||
25.5,
|
||||
8.5,
|
||||
);
|
||||
makeTest("integralSum", T.Integral.sum(~cache=None, continuous), 73.0);
|
||||
makeTest(
|
||||
"integralXToY",
|
||||
T.Integral.xToY(~cache=None, 100.0, continuous),
|
||||
47.5,
|
||||
);
|
||||
makeTest("integralSum", T.Integral.sum(~cache=None, continuous), 47.5);
|
||||
});
|
||||
|
||||
describe("Discrete", () => {
|
||||
|
@ -76,6 +119,23 @@ describe("Shape", () => {
|
|||
T.xToY(5., discrete),
|
||||
{discrete: 0.0, continuous: 0.0},
|
||||
);
|
||||
makeTest(
|
||||
"scaleBy",
|
||||
T.scaleBy(~scale=4.0, discrete),
|
||||
{xs: [|1., 4., 8.|], ys: [|1.2, 2.0, 0.8|]},
|
||||
);
|
||||
makeTest(
|
||||
"scaleToIntegralSum",
|
||||
T.scaleToIntegralSum(~intendedSum=4.0, discrete),
|
||||
{xs: [|1., 4., 8.|], ys: [|1.2, 2.0, 0.8|]},
|
||||
);
|
||||
makeTest(
|
||||
"scaleToIntegralSum: back and forth",
|
||||
discrete
|
||||
|> T.scaleToIntegralSum(~intendedSum=4.0)
|
||||
|> T.scaleToIntegralSum(~intendedSum=1.0),
|
||||
discrete,
|
||||
);
|
||||
makeTest(
|
||||
"integral",
|
||||
T.Integral.get(~cache=None, discrete),
|
||||
|
@ -84,6 +144,11 @@ describe("Shape", () => {
|
|||
`Stepwise,
|
||||
),
|
||||
);
|
||||
makeTest(
|
||||
"integral with 1 element",
|
||||
T.Integral.get(~cache=None, {xs: [|0.0|], ys: [|1.0|]}),
|
||||
Distributions.Continuous.make({xs: [|0.0|], ys: [|1.0|]}, `Stepwise),
|
||||
);
|
||||
makeTest(
|
||||
"integralXToY",
|
||||
T.Integral.xToY(~cache=None, 6.0, discrete),
|
||||
|
|
|
@ -60,6 +60,12 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
|||
() => {<IntegralChart distPlus onHover={r => {setX(_ => r)}} />},
|
||||
[|distPlus|],
|
||||
);
|
||||
// Js.log4(
|
||||
// "distPlus",
|
||||
// x,
|
||||
// distPlus,
|
||||
// distPlus |> Distributions.DistPlus.T.xToY(x),
|
||||
// );
|
||||
<div>
|
||||
chart
|
||||
chart2
|
||||
|
@ -67,6 +73,12 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
|||
<thead>
|
||||
<tr>
|
||||
<th className="px-4 py-2"> {"X Point" |> ReasonReact.string} </th>
|
||||
<th className="px-4 py-2">
|
||||
{"Discrete Value" |> ReasonReact.string}
|
||||
</th>
|
||||
<th className="px-4 py-2">
|
||||
{"Continuous Value" |> ReasonReact.string}
|
||||
</th>
|
||||
<th className="px-4 py-2">
|
||||
{"Y Integral to Point" |> ReasonReact.string}
|
||||
</th>
|
||||
|
@ -77,6 +89,20 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
|||
<th className="px-4 py-2 border ">
|
||||
{x |> E.Float.toString |> ReasonReact.string}
|
||||
</th>
|
||||
<th className="px-4 py-2 border ">
|
||||
{distPlus
|
||||
|> Distributions.DistPlus.T.xToY(x)
|
||||
|> DistTypes.MixedPoint.toDiscreteValue
|
||||
|> E.Float.with2DigitsPrecision
|
||||
|> ReasonReact.string}
|
||||
</th>
|
||||
<th className="px-4 py-2 border ">
|
||||
{distPlus
|
||||
|> Distributions.DistPlus.T.xToY(x)
|
||||
|> DistTypes.MixedPoint.toContinuousValue
|
||||
|> E.Float.with2DigitsPrecision
|
||||
|> ReasonReact.string}
|
||||
</th>
|
||||
<th className="px-4 py-2 border ">
|
||||
{distPlus
|
||||
|> Distributions.DistPlus.T.Integral.xToY(~cache=None, x)
|
||||
|
|
|
@ -54,7 +54,7 @@ module Dist = (T: dist) => {
|
|||
let sum = T.integralSum;
|
||||
};
|
||||
|
||||
// This is suboptimal because it could get the cache but doesn't here.
|
||||
// This is suboptimal because it could get the cache but doesn't here.
|
||||
let scaleToIntegralSum = (~intendedSum=1.0, t: t) => {
|
||||
let scale = intendedSum /. Integral.sum(~cache=None, t);
|
||||
scaleBy(~scale, t);
|
||||
|
@ -90,8 +90,9 @@ module Continuous = {
|
|||
type t = DistTypes.continuousShape;
|
||||
type integral = DistTypes.continuousShape;
|
||||
let shapeFn = (fn, t: t) => t |> xyShape |> fn;
|
||||
// TODO: Obviously fix this, it's terrible. Use interpolation method here.
|
||||
// TODO: Obviously fix this, it's terrible. Use interpolation param to do appropriate interpolation.
|
||||
// TODO: Steps could be 1 value, interpolation needs at least 2.
|
||||
// TODO: integrateWithTriangles should return (x0, 0.0) as the first item.
|
||||
let integral = (~cache, t) =>
|
||||
cache
|
||||
|> E.O.default(
|
||||
|
@ -103,16 +104,28 @@ module Continuous = {
|
|||
);
|
||||
// This seems wrong, we really want the ending bit, I'd assume
|
||||
let integralSum = (~cache, t) =>
|
||||
t |> integral(~cache) |> xyShape |> XYShape.ySum;
|
||||
t
|
||||
|> integral(~cache)
|
||||
|> xyShape
|
||||
|> XYShape.unsafeLast
|
||||
|> (((_, y)) => y);
|
||||
let minX = shapeFn(XYShape.minX);
|
||||
let maxX = shapeFn(XYShape.maxX);
|
||||
let pointwiseFmap = (fn, t: t) =>
|
||||
t |> xyShape |> XYShape.pointwiseMap(fn) |> fromShape;
|
||||
let toShape = (t: t): DistTypes.shape => Continuous(t);
|
||||
// TODO: When Roman's PR comes in, fix this bit. This depends on interpolation, obviously.
|
||||
let xToY = (f, t) =>
|
||||
shapeFn(CdfLibrary.Distribution.findY(f), t)
|
||||
|> DistTypes.MixedPoint.makeContinuous;
|
||||
let xToY = (f, {interpolation, xyShape}: t) =>
|
||||
switch (interpolation) {
|
||||
| `Stepwise =>
|
||||
xyShape
|
||||
|> XYShape.XtoY.stepwise(f)
|
||||
|> E.O.default(0.0)
|
||||
|> DistTypes.MixedPoint.makeContinuous
|
||||
| `Linear =>
|
||||
xyShape
|
||||
|> XYShape.XtoY.linear(f)
|
||||
|> DistTypes.MixedPoint.makeContinuous
|
||||
};
|
||||
let integralXtoY = (~cache, f, t) =>
|
||||
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
|
||||
let toContinuous = t => Some(t);
|
||||
|
@ -138,7 +151,6 @@ module Discrete = {
|
|||
Continuous.make(XYShape.accumulateYs(t), `Stepwise);
|
||||
},
|
||||
);
|
||||
// todo: Fix this with last element
|
||||
let integralSum = (~cache, t) => t |> XYShape.ySum;
|
||||
let minX = XYShape.minX;
|
||||
let maxX = XYShape.maxX;
|
||||
|
@ -150,8 +162,7 @@ module Discrete = {
|
|||
let toScaledDiscrete = t => Some(t);
|
||||
|
||||
let xToY = (f, t) => {
|
||||
XYShape.getBy(t, ((x, _)) => x == f)
|
||||
|> E.O.fmap(((_, y)) => y)
|
||||
XYShape.XtoY.ifAtX(f, t)
|
||||
|> E.O.default(0.0)
|
||||
|> DistTypes.MixedPoint.makeDiscrete;
|
||||
};
|
||||
|
|
|
@ -18,8 +18,36 @@ let last = (t: t) =>
|
|||
| _ => None
|
||||
};
|
||||
|
||||
let unsafeFirst = (t: t) => first(t) |> E.O.toExn("Unsafe operation");
|
||||
let unsafeLast = (t: t) => last(t) |> E.O.toExn("Unsafe operation");
|
||||
|
||||
let zip = t => Belt.Array.zip(t.xs, t.ys);
|
||||
let getBy = (t: t, fn) => t |> zip |> Belt.Array.getBy(_, fn);
|
||||
|
||||
let firstPairAtOrBeforeValue = (xValue, t: t) => {
|
||||
let zipped = zip(t);
|
||||
let firstIndex =
|
||||
zipped |> Belt.Array.getIndexBy(_, ((x, y)) => x > xValue);
|
||||
let previousIndex =
|
||||
switch (firstIndex) {
|
||||
| None => Some(Array.length(zipped) - 1)
|
||||
| Some(0) => None
|
||||
| Some(n) => Some(n - 1)
|
||||
};
|
||||
previousIndex |> Belt.Option.flatMap(_, Belt.Array.get(zipped));
|
||||
};
|
||||
|
||||
module XtoY = {
|
||||
let ifAtX = (f, t: t) =>
|
||||
getBy(t, ((x, _)) => x == f) |> E.O.fmap(((_, y)) => y);
|
||||
|
||||
let stepwise = (f, t: t) =>
|
||||
firstPairAtOrBeforeValue(f, t) |> E.O.fmap(((_, y)) => y);
|
||||
|
||||
// TODO: When Roman's PR comes in, fix this bit. This depends on interpolation, obviously.
|
||||
let linear = (f, t: t) => t |> CdfLibrary.Distribution.findY(f);
|
||||
};
|
||||
|
||||
let pointwiseMap = (fn, t: t): t => {xs: t.xs, ys: t.ys |> E.A.fmap(fn)};
|
||||
let fromArray = ((xs, ys)): t => {xs, ys};
|
||||
let fromArrays = (xs, ys): t => {xs, ys};
|
||||
|
@ -109,21 +137,24 @@ module Range = {
|
|||
(((lastX, lastY), (nextX, nextY)): zippedRange) =>
|
||||
(nextY -. lastY) /. (nextX -. lastX);
|
||||
|
||||
let inRanges = (mapper, reducer, t: t) => {
|
||||
let mapYsBasedOnRanges = (fn, t) =>
|
||||
Belt.Array.zip(t.xs, t.ys)
|
||||
|> E.A.toRanges
|
||||
|> E.R.toOption
|
||||
|> E.O.fmap(r => r |> Belt.Array.map(_, mapper) |> reducer);
|
||||
};
|
||||
|> E.O.fmap(r => r |> Belt.Array.map(_, r => (nextX(r), fn(r))));
|
||||
|
||||
let mapYsBasedOnRanges = fn => inRanges(r => (nextX(r), fn(r)), toT);
|
||||
|
||||
let integrateWithSteps = z =>
|
||||
mapYsBasedOnRanges(rangeAreaAssumingSteps, z) |> E.O.fmap(accumulateYs);
|
||||
|
||||
let integrateWithTriangles = z =>
|
||||
mapYsBasedOnRanges(rangeAreaAssumingTriangles, z)
|
||||
let integrateWithTriangles = z => {
|
||||
let rangeItems = mapYsBasedOnRanges(rangeAreaAssumingTriangles, z);
|
||||
(
|
||||
switch (rangeItems, z |> first) {
|
||||
| (Some(r), Some((firstX, _))) =>
|
||||
Some(Belt.Array.concat([|(firstX, 0.0)|], r))
|
||||
| _ => None
|
||||
}
|
||||
)
|
||||
|> E.O.fmap(toT)
|
||||
|> E.O.fmap(accumulateYs);
|
||||
};
|
||||
|
||||
let derivative = mapYsBasedOnRanges(delta_y_over_delta_x);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user