Minor changes, but seemed to break percentiles

This commit is contained in:
Ozzie Gooen 2020-03-16 16:59:58 +00:00
parent 80d040e138
commit c682fff280
9 changed files with 178 additions and 984 deletions

View File

@ -39,5 +39,15 @@ describe("XYShapes", () => {
XYShape.logScorePoint(30, shape1, shape3), XYShape.logScorePoint(30, shape1, shape3),
Some(210.3721280423322), Some(210.3721280423322),
); );
}) });
describe("transverse", () => {
makeTest(
"When very different",
XYShape.T._transverse2(
(aCurrent, aLast) => aCurrent +. aLast,
[|1.0, 2.0, 3.0, 4.0|],
),
[|1.0, 3.0, 6.0, 10.0|],
)
});
}); });

View File

@ -29,7 +29,7 @@
"@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", "@glennsl/bs-jest": "^0.5.0",
"antd": "3.17.0", "antd": "3.17.0",
"autoprefixer": "9.7.4", "autoprefixer": "9.7.4",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
@ -55,8 +55,9 @@
"pdfast": "^0.2.0", "pdfast": "^0.2.0",
"postcss-cli": "7.1.0", "postcss-cli": "7.1.0",
"rationale": "0.2.0", "rationale": "0.2.0",
"react": "16.12.0", "react": "^16.8.0",
"react-dom": "16.12.0", "react-dom": "^16.8.0",
"react-use": "^13.27.0",
"reason-react": ">=0.7.0", "reason-react": ">=0.7.0",
"reschema": "1.3.0", "reschema": "1.3.0",
"tailwindcss": "1.2.0" "tailwindcss": "1.2.0"

View File

@ -248,9 +248,7 @@ module IntegralChart = {
[@react.component] [@react.component]
let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => { let make = (~distPlus: DistTypes.distPlus, ~config: chartConfig, ~onHover) => {
open Distributions.DistPlus; open Distributions.DistPlus;
let integral = let integral = distPlus.integralCache;
Distributions.DistPlus.T.toShape(distPlus)
|> Distributions.Shape.T.Integral.get(~cache=None);
let continuous = let continuous =
integral integral
|> Distributions.Continuous.toLinear |> Distributions.Continuous.toLinear

View File

@ -147,9 +147,9 @@ module Continuous = {
}; };
let integralEndY = (~cache, t) => t |> integral(~cache) |> lastY; let integralEndY = (~cache, t) => t |> integral(~cache) |> lastY;
let integralXtoY = (~cache, f, t) => let integralXtoY = (~cache, f, t) =>
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f)); t |> integral(~cache) |> shapeFn(XYShape.T.findY(f));
let integralYtoX = (~cache, f, t) => let integralYtoX = (~cache, f, t) =>
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findX(f)); t |> integral(~cache) |> shapeFn(XYShape.T.findX(f));
let toContinuous = t => Some(t); let toContinuous = t => Some(t);
let toDiscrete = _ => None; let toDiscrete = _ => None;
let toScaledContinuous = t => Some(t); let toScaledContinuous = t => Some(t);
@ -202,16 +202,10 @@ module Discrete = {
// todo: This should use cache and/or same code as above. FindingY is more complex, should use interpolationType. // todo: This should use cache and/or same code as above. FindingY is more complex, should use interpolationType.
let integralXtoY = (~cache, f, t) => let integralXtoY = (~cache, f, t) =>
t t |> integral(~cache) |> Continuous.getShape |> XYShape.T.findY(f);
|> integral(~cache)
|> Continuous.getShape
|> CdfLibrary.Distribution.findY(f);
let integralYtoX = (~cache, f, t) => let integralYtoX = (~cache, f, t) =>
t t |> integral(~cache) |> Continuous.getShape |> XYShape.T.findX(f);
|> integral(~cache)
|> Continuous.getShape
|> CdfLibrary.Distribution.findX(f);
}); });
}; };
@ -354,17 +348,11 @@ module Mixed = {
}; };
let integralXtoY = (~cache, f, t) => { let integralXtoY = (~cache, f, t) => {
t t |> integral(~cache) |> Continuous.getShape |> XYShape.T.findX(f);
|> integral(~cache)
|> Continuous.getShape
|> CdfLibrary.Distribution.findX(f);
}; };
let integralYtoX = (~cache, f, t) => { let integralYtoX = (~cache, f, t) => {
t t |> integral(~cache) |> Continuous.getShape |> XYShape.T.findY(f);
|> integral(~cache)
|> Continuous.getShape
|> CdfLibrary.Distribution.findY(f);
}; };
// TODO: This functionality is kinda weird, because it seems to assume the cdf adds to 1.0 elsewhere, which wouldn't happen here. // TODO: This functionality is kinda weird, because it seems to assume the cdf adds to 1.0 elsewhere, which wouldn't happen here.

View File

@ -49,6 +49,8 @@ module T = {
}; };
let findY = (x: float, t: t): float => { let findY = (x: float, t: t): float => {
// todo: change getIndexBy to realize it's sorted
// Belt.SortArray.binarySearchBy
let firstHigherIndex = Belt.Array.getIndexBy(xs(t), e => e >= x); let firstHigherIndex = Belt.Array.getIndexBy(xs(t), e => e >= x);
switch (firstHigherIndex) { switch (firstHigherIndex) {
| None => maxY(t) |> E.O.default(0.0) | None => maxY(t) |> E.O.default(0.0)
@ -71,7 +73,28 @@ module T = {
}; };
}; };
let findX = CdfLibrary.Distribution.findX; let findX = (y: float, t: t): float => {
let firstHigherIndex = Belt.Array.getIndexBy(ys(t), e => e >= y);
switch (firstHigherIndex) {
| None => maxX(t) |> E.O.default(0.0)
| Some(0) => minX(t) |> E.O.default(0.0)
| Some(firstHigherIndex) =>
let lowerOrEqualIndex =
firstHigherIndex - 1 < 0 ? 0 : firstHigherIndex - 1;
let needsInterpolation = ys(t)[lowerOrEqualIndex] != y;
if (needsInterpolation) {
Functions.interpolate(
ys(t)[lowerOrEqualIndex],
ys(t)[firstHigherIndex],
ys(t)[lowerOrEqualIndex],
ys(t)[firstHigherIndex],
y,
);
} else {
xs(t)[lowerOrEqualIndex];
};
};
};
module XtoY = { module XtoY = {
let stepwiseIncremental = (f, t: t) => let stepwiseIncremental = (f, t: t) =>
@ -180,6 +203,38 @@ module T = {
let ySum = yFold((a, b) => a +. b); let ySum = yFold((a, b) => a +. b);
let _transverseSimple = fn =>
Belt.Array.reduce(_, [||], (items, y) =>
switch (E.A.last(items)) {
| Some(yLast) => Belt.Array.concat(items, [|fn(y, yLast)|])
| None => [|y|]
}
);
let _transverse2 = (fn, items) => {
let length = items |> E.A.length;
let empty = Belt.Array.make(length, items |> E.A.unsafe_get(_, 0));
Belt.Array.forEachWithIndex(
items,
(index, element) => {
let item =
switch (index) {
| 0 => element
| index => fn(element, E.A.unsafe_get(empty, index - 1))
};
let _ = Belt.Array.set(empty, index, item);
();
},
);
empty;
};
let _transverseB = (fn, items) => {
let (xs, ys) = items |> Belt.Array.unzip;
let newYs = _transverse2(fn, ys);
Belt.Array.zip(xs, newYs);
};
let _transverse = fn => let _transverse = fn =>
Belt.Array.reduce(_, [||], (items, (x, y)) => Belt.Array.reduce(_, [||], (items, (x, y)) =>
switch (E.A.last(items)) { switch (E.A.last(items)) {
@ -191,7 +246,7 @@ module T = {
let _transverseShape = (fn, p: t) => { let _transverseShape = (fn, p: t) => {
Belt.Array.zip(p.xs, p.ys) Belt.Array.zip(p.xs, p.ys)
|> _transverse(fn) |> _transverseB(fn)
|> Belt.Array.unzip |> Belt.Array.unzip
|> fromArray; |> fromArray;
}; };

View File

@ -134,12 +134,10 @@ module S = {
module J = { module J = {
let toString = Js.Json.decodeString ||> O.default(""); let toString = Js.Json.decodeString ||> O.default("");
let toMoment = toString ||> MomentRe.moment;
let fromString = Js.Json.string; let fromString = Js.Json.string;
let fromNumber = Js.Json.number; let fromNumber = Js.Json.number;
module O = { module O = {
let toMoment = O.fmap(toMoment);
let fromString = (str: string) => let fromString = (str: string) =>
switch (str) { switch (str) {

View File

@ -104,7 +104,6 @@ module KDE = {
part2Data part2Data
|> Internals.samplesToContinuousPdf(_, part2XYPoints, 3) |> Internals.samplesToContinuousPdf(_, part2XYPoints, 3)
|> CdfLibrary.JS.jsToDist; |> CdfLibrary.JS.jsToDist;
Js.log4(partitionAt, part1XYPoints, part1, part2);
let opp = 1.0 -. cuttoff; let opp = 1.0 -. cuttoff;
// let result = // let result =
// XYShape.T.Combine.combineLinear( // XYShape.T.Combine.combineLinear(
@ -141,7 +140,6 @@ let toMixed =
let length = samples |> E.A.length; let length = samples |> E.A.length;
Array.fast_sort(compare, samples); Array.fast_sort(compare, samples);
Js.log2("SORTED?", samples);
// let items = // let items =
// E.A.uniq(samples) // E.A.uniq(samples)
// |> E.A.fmap(r => (r, samples |> E.A.filter(n => n == r) |> E.A.length)); // |> E.A.fmap(r => (r, samples |> E.A.filter(n => n == r) |> E.A.length));
@ -158,8 +156,8 @@ let toMixed =
let pdf: DistTypes.xyShape = let pdf: DistTypes.xyShape =
continuousPart |> E.A.length > 20 continuousPart |> E.A.length > 20
? { ? {
samples |> KDE.inGroups(_, outputXYPoints, kernelWidth, ~cuttoff, ()); // samples |> KDE.inGroups(_, outputXYPoints, kernelWidth, ~cuttoff, ());
// samples |> KDE.normalSampling(_, outputXYPoints, kernelWidth); samples |> KDE.normalSampling(_, outputXYPoints, kernelWidth);
} }
: {xs: [||], ys: [||]}; : {xs: [||], ys: [||]};
timeMessage("Finished pdf"); timeMessage("Finished pdf");

View File

@ -90,15 +90,18 @@ const stringToSamples = (
sampleCount, sampleCount,
inputs = [], inputs = [],
) => { ) => {
const [_error, item] = Guesstimator.parse({ text:"=" + text }); const [_error, { parsedInput, parsedError }] = Guesstimator.parse({ text:"=" + text });
const { parsedInput } = item;
const guesstimator = new Guesstimator({ parsedInput }); const guesstimator = new Guesstimator({ parsedInput });
const value = guesstimator.sample( const {values, errors} = guesstimator.sample(
sampleCount, sampleCount,
inputs, inputs,
); );
return value.values if (errors.length > 0){
return []
} else {
return values
}
}; };

1037
yarn.lock

File diff suppressed because it is too large Load Diff