commit
3f901a1102
179
__tests__/CDF__Test.re
Normal file
179
__tests__/CDF__Test.re
Normal file
|
@ -0,0 +1,179 @@
|
|||
open Jest;
|
||||
open Expect;
|
||||
|
||||
exception ShapeWrong(string);
|
||||
describe("CDF", () => {
|
||||
test("raise - w/o order", () => {
|
||||
expect(() => {
|
||||
module Cdf =
|
||||
CDF.Make({
|
||||
let shape: DistTypes.xyShape = {
|
||||
xs: [|10., 4., 8.|],
|
||||
ys: [|8., 9., 2.|],
|
||||
};
|
||||
});
|
||||
();
|
||||
})
|
||||
|> toThrow
|
||||
});
|
||||
test("raise - with order", () => {
|
||||
expect(() => {
|
||||
module Cdf =
|
||||
CDF.Make({
|
||||
let shape: DistTypes.xyShape = {
|
||||
xs: [|1., 4., 8.|],
|
||||
ys: [|8., 9., 2.|],
|
||||
};
|
||||
});
|
||||
();
|
||||
})
|
||||
|> not_
|
||||
|> toThrow
|
||||
});
|
||||
test("order#1", () => {
|
||||
let a = CDF.order({xs: [|1., 4., 8.|], ys: [|8., 9., 2.|]});
|
||||
let b: DistTypes.xyShape = {xs: [|1., 4., 8.|], ys: [|8., 9., 2.|]};
|
||||
expect(a) |> toEqual(b);
|
||||
});
|
||||
test("order#2", () => {
|
||||
let a = CDF.order({xs: [|10., 5., 12.|], ys: [|8., 9., 2.|]});
|
||||
let b: DistTypes.xyShape = {xs: [|5., 10., 12.|], ys: [|9., 8., 2.|]};
|
||||
expect(a) |> toEqual(b);
|
||||
});
|
||||
|
||||
describe("minX - maxX", () => {
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape = CDF.order({xs: [|20., 4., 8.|], ys: [|8., 9., 2.|]});
|
||||
});
|
||||
test("minX", () => {
|
||||
expect(Dist.minX()) |> toEqual(4.)
|
||||
});
|
||||
test("maxX", () => {
|
||||
expect(Dist.maxX()) |> toEqual(20.)
|
||||
});
|
||||
});
|
||||
|
||||
describe("findY", () => {
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape = CDF.order({xs: [|1., 2., 3.|], ys: [|5., 6., 7.|]});
|
||||
});
|
||||
test("#1", () => {
|
||||
expect(Dist.findY(1.)) |> toEqual(5.)
|
||||
});
|
||||
test("#2", () => {
|
||||
expect(Dist.findY(1.5)) |> toEqual(5.5)
|
||||
});
|
||||
test("#3", () => {
|
||||
expect(Dist.findY(3.)) |> toEqual(7.)
|
||||
});
|
||||
test("#4", () => {
|
||||
expect(Dist.findY(4.)) |> toEqual(7.)
|
||||
});
|
||||
test("#5", () => {
|
||||
expect(Dist.findY(15.)) |> toEqual(7.)
|
||||
});
|
||||
test("#6", () => {
|
||||
expect(Dist.findY(-1.)) |> toEqual(5.)
|
||||
});
|
||||
});
|
||||
|
||||
describe("findX", () => {
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape = CDF.order({xs: [|1., 2., 3.|], ys: [|5., 6., 7.|]});
|
||||
});
|
||||
test("#1", () => {
|
||||
expect(Dist.findX(5.)) |> toEqual(1.)
|
||||
});
|
||||
test("#2", () => {
|
||||
expect(Dist.findX(7.)) |> toEqual(3.)
|
||||
});
|
||||
test("#3", () => {
|
||||
expect(Dist.findX(5.5)) |> toEqual(1.5)
|
||||
});
|
||||
test("#4", () => {
|
||||
expect(Dist.findX(8.)) |> toEqual(3.)
|
||||
});
|
||||
test("#5", () => {
|
||||
expect(Dist.findX(4.)) |> toEqual(1.)
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertWithAlternativeXs", () => {
|
||||
open Functions;
|
||||
let xs = up(1, 9);
|
||||
let ys = up(20, 28);
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape = CDF.order({xs, ys});
|
||||
});
|
||||
|
||||
let xs2 = up(3, 7);
|
||||
module Dist2 =
|
||||
CDF.Make({
|
||||
let shape = Dist.convertWithAlternativeXs(xs2);
|
||||
});
|
||||
|
||||
test("#1", () => {
|
||||
expect(Dist2.xs) |> toEqual([|3., 4., 5., 6., 7.|])
|
||||
});
|
||||
test("#2", () => {
|
||||
expect(Dist2.ys) |> toEqual([|22., 23., 24., 25., 26.|])
|
||||
});
|
||||
});
|
||||
|
||||
describe("convertToNewLength", () => {
|
||||
open Functions;
|
||||
let xs = up(1, 9);
|
||||
let ys = up(50, 58);
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape = CDF.order({xs, ys});
|
||||
});
|
||||
module Dist2 =
|
||||
CDF.Make({
|
||||
let shape = Dist.convertToNewLength(3);
|
||||
});
|
||||
test("#1", () => {
|
||||
expect(Dist2.xs) |> toEqual([|1., 5., 9.|])
|
||||
});
|
||||
test("#2", () => {
|
||||
expect(Dist2.ys) |> toEqual([|50., 54., 58.|])
|
||||
});
|
||||
});
|
||||
|
||||
// @todo: Should each test expect 70.?
|
||||
describe("sample", () => {
|
||||
open Functions;
|
||||
let xs = up(1, 9);
|
||||
let ys = up(70, 78);
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape = CDF.order({xs, ys});
|
||||
});
|
||||
|
||||
let xs2 = Dist.sample(3);
|
||||
test("#1", () => {
|
||||
expect(xs2[0]) |> toBe(70.)
|
||||
});
|
||||
test("#2", () => {
|
||||
expect(xs2[1]) |> toBe(70.)
|
||||
});
|
||||
test("#3", () => {
|
||||
expect(xs2[2]) |> toBe(70.)
|
||||
});
|
||||
});
|
||||
|
||||
describe("integral", () => {
|
||||
module Dist =
|
||||
CDF.Make({
|
||||
let shape =
|
||||
CDF.order({xs: [|0., 1., 2., 4.|], ys: [|0.0, 1.0, 2.0, 2.0|]});
|
||||
});
|
||||
test("with regular inputs", () => {
|
||||
expect(Dist.integral()) |> toBe(6.)
|
||||
});
|
||||
});
|
||||
});
|
92
__tests__/Functions__Test.re
Normal file
92
__tests__/Functions__Test.re
Normal file
|
@ -0,0 +1,92 @@
|
|||
open Jest;
|
||||
open Expect;
|
||||
|
||||
exception ShapeWrong(string);
|
||||
describe("Functions", () => {
|
||||
test("interpolate", () => {
|
||||
let a = Functions.interpolate(10., 20., 1., 2., 15.);
|
||||
let b = 1.5;
|
||||
expect(a) |> toEqual(b);
|
||||
});
|
||||
test("range#1", () => {
|
||||
expect(Functions.range(1., 5., 3)) |> toEqual([|1., 3., 5.|])
|
||||
});
|
||||
test("range#2", () => {
|
||||
expect(Functions.range(1., 5., 5)) |> toEqual([|1., 2., 3., 4., 5.|])
|
||||
});
|
||||
test("range#3", () => {
|
||||
expect(Functions.range(-10., 15., 2)) |> toEqual([|(-10.), 15.|])
|
||||
});
|
||||
test("range#4", () => {
|
||||
expect(Functions.range(-10., 15., 3)) |> toEqual([|(-10.), 2.5, 15.|])
|
||||
});
|
||||
test("range#5", () => {
|
||||
expect(Functions.range(-10.3, 17., 3))
|
||||
|> toEqual([|(-10.3), 3.3499999999999996, 17.|])
|
||||
});
|
||||
test("range#6", () => {
|
||||
expect(Functions.range(-10.3, 17., 5))
|
||||
|> toEqual([|
|
||||
(-10.3),
|
||||
(-3.4750000000000005),
|
||||
3.3499999999999996,
|
||||
10.175,
|
||||
17.0,
|
||||
|])
|
||||
});
|
||||
test("range#7", () => {
|
||||
expect(Functions.range(-10.3, 17.31, 3))
|
||||
|> toEqual([|(-10.3), 3.504999999999999, 17.31|])
|
||||
});
|
||||
test("range#8", () => {
|
||||
expect(Functions.range(1., 1., 3)) |> toEqual([|1., 1., 1.|])
|
||||
});
|
||||
test("mean#1", () => {
|
||||
expect(Functions.mean([|1., 2., 3.|])) |> toEqual(2.)
|
||||
});
|
||||
test("mean#2", () => {
|
||||
expect(Functions.mean([|1., 2., 3., (-2.)|])) |> toEqual(1.)
|
||||
});
|
||||
test("mean#3", () => {
|
||||
expect(Functions.mean([|1., 2., 3., (-2.), (-10.)|])) |> toEqual(-1.2)
|
||||
});
|
||||
test("min#1", () => {
|
||||
expect(Functions.min([|1., 2., 3.|])) |> toEqual(1.)
|
||||
});
|
||||
test("min#2", () => {
|
||||
expect(Functions.min([|(-1.), (-2.), 0., 20.|])) |> toEqual(-2.)
|
||||
});
|
||||
test("min#3", () => {
|
||||
expect(Functions.min([|(-1.), (-2.), 0., 20., (-2.2)|]))
|
||||
|> toEqual(-2.2)
|
||||
});
|
||||
test("max#1", () => {
|
||||
expect(Functions.max([|1., 2., 3.|])) |> toEqual(3.)
|
||||
});
|
||||
test("max#2", () => {
|
||||
expect(Functions.max([|(-1.), (-2.), 0., 20.|])) |> toEqual(20.)
|
||||
});
|
||||
test("max#3", () => {
|
||||
expect(Functions.max([|(-1.), (-2.), 0., (-2.2)|])) |> toEqual(0.)
|
||||
});
|
||||
test("random#1", () => {
|
||||
expect(Functions.random(1, 5)) |> toBeLessThanOrEqual(5)
|
||||
});
|
||||
test("random#2", () => {
|
||||
expect(Functions.random(1, 5)) |> toBeGreaterThanOrEqual(1)
|
||||
});
|
||||
test("up#1", () => {
|
||||
expect(Functions.up(1, 5)) |> toEqual([|1., 2., 3., 4., 5.|])
|
||||
});
|
||||
test("up#2", () => {
|
||||
expect(Functions.up(-1, 5))
|
||||
|> toEqual([|(-1.), 0., 1., 2., 3., 4., 5.|])
|
||||
});
|
||||
test("down#1", () => {
|
||||
expect(Functions.down(5, 1)) |> toEqual([|5., 4., 3., 2., 1.|])
|
||||
});
|
||||
test("down#2", () => {
|
||||
expect(Functions.down(5, -1))
|
||||
|> toEqual([|5., 4., 3., 2., 1., 0., (-1.)|])
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var React = require("react");
|
||||
var ReactDOMRe = require("reason-react/src/ReactDOMRe.js");
|
||||
var App$ProbExample = require("./App.bs.js");
|
||||
|
||||
((import('./styles/index.css')));
|
||||
|
||||
ReactDOMRe.renderToElementWithId(React.createElement(App$ProbExample.make, { }), "app");
|
||||
|
||||
/* Not a pure module */
|
|
@ -1,174 +1,170 @@
|
|||
const {
|
||||
Cdf,
|
||||
Pdf,
|
||||
ContinuousDistribution,
|
||||
ContinuousDistributionCombination,
|
||||
scoringFunctions,
|
||||
} = require("@foretold/cdf/lib");
|
||||
const _ = require("lodash");
|
||||
Cdf,
|
||||
Pdf,
|
||||
ContinuousDistribution,
|
||||
ContinuousDistributionCombination,
|
||||
scoringFunctions,
|
||||
} = require("@foretold/cdf/lib");
|
||||
const _ = require("lodash");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {{ys: *, xs: *}}
|
||||
*/
|
||||
function cdfToPdf({ xs, ys }) {
|
||||
let cdf = new Cdf(xs, ys);
|
||||
let pdf = cdf.toPdf();
|
||||
return { xs: pdf.xs, ys: pdf.ys };
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {{ys: *, xs: *}}
|
||||
*/
|
||||
function cdfToPdf({ xs, ys }) {
|
||||
let cdf = new Cdf(xs, ys);
|
||||
let pdf = cdf.toPdf();
|
||||
return { xs: pdf.xs, ys: pdf.ys };
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {{ys: *, xs: *}}
|
||||
*/
|
||||
function pdfToCdf({ xs, ys }) {
|
||||
let cdf = new Pdf(xs, ys);
|
||||
let pdf = cdf.toCdf();
|
||||
return { xs: pdf.xs, ys: pdf.ys };
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {{ys: *, xs: *}}
|
||||
*/
|
||||
function pdfToCdf({ xs, ys }) {
|
||||
let cdf = new Pdf(xs, ys);
|
||||
let pdf = cdf.toCdf();
|
||||
return { xs: pdf.xs, ys: pdf.ys };
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sampleCount
|
||||
* @param vars
|
||||
* @returns {{ys: *, xs: *}}
|
||||
*/
|
||||
function mean(sampleCount, vars) {
|
||||
let cdfs = vars.map(r => new Cdf(r.xs, r.ys));
|
||||
let comb = new ContinuousDistributionCombination(cdfs);
|
||||
let newCdf = comb.combineYsWithMean(sampleCount);
|
||||
/**
|
||||
*
|
||||
* @param sampleCount
|
||||
* @param vars
|
||||
* @returns {{ys: *, xs: *}}
|
||||
*/
|
||||
function mean(sampleCount, vars) {
|
||||
let cdfs = vars.map(r => new Cdf(r.xs, r.ys));
|
||||
let comb = new ContinuousDistributionCombination(cdfs);
|
||||
let newCdf = comb.combineYsWithMean(sampleCount);
|
||||
|
||||
return { xs: newCdf.xs, ys: newCdf.ys };
|
||||
}
|
||||
return { xs: newCdf.xs, ys: newCdf.ys };
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sampleCount
|
||||
* @param predictionCdf
|
||||
* @param resolutionCdf
|
||||
*/
|
||||
function scoreNonMarketCdfCdf(sampleCount, predictionCdf, resolutionCdf, resolutionUniformAdditionWeight=0) {
|
||||
let toCdf = (r) => (new Cdf(r.xs, r.ys));
|
||||
let prediction = toCdf(predictionCdf);
|
||||
if (_.isFinite(resolutionUniformAdditionWeight)){
|
||||
prediction = prediction.combineWithUniformOfCdf(
|
||||
{
|
||||
cdf: toCdf(resolutionCdf),
|
||||
uniformWeight: resolutionUniformAdditionWeight,
|
||||
sampleCount
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return scoringFunctions.distributionInputDistributionOutputMarketless({
|
||||
predictionCdf: prediction,
|
||||
resultCdf: toCdf(resolutionCdf),
|
||||
sampleCount,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sampleCount
|
||||
* @param cdf
|
||||
*/
|
||||
function differentialEntropy(sampleCount, cdf) {
|
||||
let toCdf = (r) => (new Cdf(r.xs, r.ys));
|
||||
|
||||
return scoringFunctions.differentialEntropy({
|
||||
cdf: toCdf(cdf),
|
||||
sampleCount: sampleCount
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number}
|
||||
*/
|
||||
function findY(x, { xs, ys }) {
|
||||
let cdf = new Cdf(xs, ys);
|
||||
return cdf.findY(x);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number[]}
|
||||
*/
|
||||
function convertToNewLength(n, { xs, ys }) {
|
||||
let dist = new ContinuousDistribution(xs, ys);
|
||||
return dist.convertToNewLength(n);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param y
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number}
|
||||
*/
|
||||
function findX(y, { xs, ys }) {
|
||||
let cdf = new Cdf(xs, ys);
|
||||
return cdf.findX(y);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number[]}
|
||||
*/
|
||||
function integral({ xs, ys }) {
|
||||
if (_.includes(ys, NaN)){
|
||||
return NaN;
|
||||
}
|
||||
else if (_.includes(ys, Infinity) && _.includes(ys, -Infinity)){
|
||||
return NaN;
|
||||
}
|
||||
else if (_.includes(ys, Infinity)){
|
||||
return Infinity;
|
||||
}
|
||||
else if (_.includes(ys, -Infinity)){
|
||||
return -Infinity;
|
||||
}
|
||||
|
||||
let integral = 0;
|
||||
for (let i = 1; i < ys.length; i++) {
|
||||
let thisY = ys[i];
|
||||
let lastY = ys[i - 1];
|
||||
let thisX = xs[i];
|
||||
let lastX = xs[i - 1];
|
||||
|
||||
if (
|
||||
_.isFinite(thisY) && _.isFinite(lastY) &&
|
||||
_.isFinite(thisX) && _.isFinite(lastX)
|
||||
) {
|
||||
let sectionInterval = ((thisY + lastY) / 2) * (thisX - lastX);
|
||||
integral = integral + sectionInterval;
|
||||
/**
|
||||
*
|
||||
* @param sampleCount
|
||||
* @param predictionCdf
|
||||
* @param resolutionCdf
|
||||
*/
|
||||
function scoreNonMarketCdfCdf(sampleCount, predictionCdf, resolutionCdf, resolutionUniformAdditionWeight = 0) {
|
||||
let toCdf = (r) => (new Cdf(r.xs, r.ys));
|
||||
let prediction = toCdf(predictionCdf);
|
||||
if (_.isFinite(resolutionUniformAdditionWeight)) {
|
||||
prediction = prediction.combineWithUniformOfCdf(
|
||||
{
|
||||
cdf: toCdf(resolutionCdf),
|
||||
uniformWeight: resolutionUniformAdditionWeight,
|
||||
sampleCount
|
||||
}
|
||||
|
||||
}
|
||||
return integral;
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
cdfToPdf,
|
||||
pdfToCdf,
|
||||
findY,
|
||||
findX,
|
||||
convertToNewLength,
|
||||
mean,
|
||||
scoreNonMarketCdfCdf,
|
||||
differentialEntropy,
|
||||
integral,
|
||||
};
|
||||
return scoringFunctions.distributionInputDistributionOutputMarketless({
|
||||
predictionCdf: prediction,
|
||||
resultCdf: toCdf(resolutionCdf),
|
||||
sampleCount,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sampleCount
|
||||
* @param cdf
|
||||
*/
|
||||
function differentialEntropy(sampleCount, cdf) {
|
||||
let toCdf = (r) => (new Cdf(r.xs, r.ys));
|
||||
|
||||
return scoringFunctions.differentialEntropy({
|
||||
cdf: toCdf(cdf),
|
||||
sampleCount: sampleCount
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number}
|
||||
*/
|
||||
function findY(x, { xs, ys }) {
|
||||
let cdf = new Cdf(xs, ys);
|
||||
return cdf.findY(x);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param x
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number[]}
|
||||
*/
|
||||
function convertToNewLength(n, { xs, ys }) {
|
||||
let dist = new ContinuousDistribution(xs, ys);
|
||||
return dist.convertToNewLength(n);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param y
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number}
|
||||
*/
|
||||
function findX(y, { xs, ys }) {
|
||||
let cdf = new Cdf(xs, ys);
|
||||
return cdf.findX(y);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param xs
|
||||
* @param ys
|
||||
* @returns {number[]}
|
||||
*/
|
||||
function integral({ xs, ys }) {
|
||||
if (_.includes(ys, NaN)) {
|
||||
return NaN;
|
||||
} else if (_.includes(ys, Infinity) && _.includes(ys, -Infinity)) {
|
||||
return NaN;
|
||||
} else if (_.includes(ys, Infinity)) {
|
||||
return Infinity;
|
||||
} else if (_.includes(ys, -Infinity)) {
|
||||
return -Infinity;
|
||||
}
|
||||
|
||||
let integral = 0;
|
||||
for (let i = 1; i < ys.length; i++) {
|
||||
let thisY = ys[i];
|
||||
let lastY = ys[i - 1];
|
||||
let thisX = xs[i];
|
||||
let lastX = xs[i - 1];
|
||||
|
||||
if (
|
||||
_.isFinite(thisY) && _.isFinite(lastY) &&
|
||||
_.isFinite(thisX) && _.isFinite(lastX)
|
||||
) {
|
||||
let sectionInterval = ((thisY + lastY) / 2) * (thisX - lastX);
|
||||
integral = integral + sectionInterval;
|
||||
}
|
||||
|
||||
}
|
||||
return integral;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
cdfToPdf,
|
||||
pdfToCdf,
|
||||
findY,
|
||||
findX,
|
||||
convertToNewLength,
|
||||
mean,
|
||||
scoreNonMarketCdfCdf,
|
||||
differentialEntropy,
|
||||
integral,
|
||||
};
|
||||
|
|
107
src/utility/lib/CDF.re
Normal file
107
src/utility/lib/CDF.re
Normal file
|
@ -0,0 +1,107 @@
|
|||
module type Config = {let shape: DistTypes.xyShape;};
|
||||
|
||||
exception ShapeWrong(string);
|
||||
|
||||
let order = (shape: DistTypes.xyShape): DistTypes.xyShape => {
|
||||
let xy =
|
||||
shape.xs
|
||||
|> Array.mapi((i, x) => [x, shape.ys |> Array.get(_, i)])
|
||||
|> Belt.SortArray.stableSortBy(_, ([a, _], [b, _]) => a > b ? 1 : (-1));
|
||||
{
|
||||
xs: xy |> Array.map(([x, _]) => x),
|
||||
ys: xy |> Array.map(([_, y]) => y),
|
||||
};
|
||||
};
|
||||
|
||||
module Make = (Config: Config) => {
|
||||
let xs = Config.shape.xs;
|
||||
let ys = Config.shape.ys;
|
||||
let get = Array.get;
|
||||
let len = Array.length;
|
||||
|
||||
let validateHasLength = (): bool => len(xs) > 0;
|
||||
let validateSize = (): bool => len(xs) == len(ys);
|
||||
if (!validateHasLength()) {
|
||||
raise(ShapeWrong("You need at least one element."));
|
||||
};
|
||||
if (!validateSize()) {
|
||||
raise(ShapeWrong("Arrays of \"xs\" and \"ys\" have different sizes."));
|
||||
};
|
||||
if (!Belt.SortArray.isSorted(xs, (a, b) => a > b ? 1 : (-1))) {
|
||||
raise(ShapeWrong("Arrays of \"xs\" and \"ys\" have different sizes."));
|
||||
};
|
||||
let minX = () => get(xs, 0);
|
||||
let maxX = () => get(xs, len(xs) - 1);
|
||||
let minY = () => get(ys, 0);
|
||||
let maxY = () => get(ys, len(ys) - 1);
|
||||
let findY = (x: float): float => {
|
||||
let firstHigherIndex = Belt.Array.getIndexBy(xs, e => e >= x);
|
||||
switch (firstHigherIndex) {
|
||||
| None => maxY()
|
||||
| Some(0) => minY()
|
||||
| Some(firstHigherIndex) =>
|
||||
let lowerOrEqualIndex =
|
||||
firstHigherIndex - 1 < 0 ? 0 : firstHigherIndex - 1;
|
||||
let needsInterpolation = get(xs, lowerOrEqualIndex) != x;
|
||||
if (needsInterpolation) {
|
||||
Functions.interpolate(
|
||||
get(xs, lowerOrEqualIndex),
|
||||
get(xs, firstHigherIndex),
|
||||
get(ys, lowerOrEqualIndex),
|
||||
get(ys, firstHigherIndex),
|
||||
x,
|
||||
);
|
||||
} else {
|
||||
ys[lowerOrEqualIndex];
|
||||
};
|
||||
};
|
||||
};
|
||||
let findX = (y: float): float => {
|
||||
let firstHigherIndex = Belt.Array.getIndexBy(ys, e => e >= y);
|
||||
switch (firstHigherIndex) {
|
||||
| None => maxX()
|
||||
| Some(0) => minX()
|
||||
| Some(firstHigherIndex) =>
|
||||
let lowerOrEqualIndex =
|
||||
firstHigherIndex - 1 < 0 ? 0 : firstHigherIndex - 1;
|
||||
let needsInterpolation = get(ys, lowerOrEqualIndex) != y;
|
||||
if (needsInterpolation) {
|
||||
Functions.interpolate(
|
||||
get(ys, lowerOrEqualIndex),
|
||||
get(ys, firstHigherIndex),
|
||||
get(xs, lowerOrEqualIndex),
|
||||
get(xs, firstHigherIndex),
|
||||
y,
|
||||
);
|
||||
} else {
|
||||
xs[lowerOrEqualIndex];
|
||||
};
|
||||
};
|
||||
};
|
||||
let convertWithAlternativeXs = (newXs: array(float)): DistTypes.xyShape => {
|
||||
let newYs = Belt.Array.map(newXs, findY);
|
||||
{xs: newXs, ys: newYs};
|
||||
};
|
||||
let convertToNewLength = (newLength: int): DistTypes.xyShape => {
|
||||
Functions.(
|
||||
range(min(xs), max(xs), newLength) |> convertWithAlternativeXs
|
||||
);
|
||||
};
|
||||
let sampleSingle = (): float => Js.Math.random() |> findY;
|
||||
let sample = (size: int): array(float) =>
|
||||
Belt.Array.makeBy(size, i => sampleSingle());
|
||||
let integral = () => {
|
||||
Belt.Array.reduceWithIndex(ys, 0., (integral, y, i) => {
|
||||
switch (i) {
|
||||
| 0 => integral
|
||||
| _ =>
|
||||
let thisY = y;
|
||||
let lastY = get(ys, i - 1);
|
||||
let thisX = get(xs, i);
|
||||
let lastX = get(xs, i - 1);
|
||||
let sectionInterval = (thisY +. lastY) /. 2. *. (thisX -. lastX);
|
||||
integral +. sectionInterval;
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
36
src/utility/lib/Functions.re
Normal file
36
src/utility/lib/Functions.re
Normal file
|
@ -0,0 +1,36 @@
|
|||
exception RangeWrong(string);
|
||||
|
||||
let interpolate =
|
||||
(xMin: float, xMax: float, yMin: float, yMax: float, xIntended: float)
|
||||
: float => {
|
||||
let minProportion = (xMax -. xIntended) /. (xMax -. xMin);
|
||||
let maxProportion = (xIntended -. xMin) /. (xMax -. xMin);
|
||||
yMin *. minProportion +. yMax *. maxProportion;
|
||||
};
|
||||
|
||||
let sum = Belt.Array.reduce(_, 0., (i, j) => i +. j);
|
||||
let mean = a => sum(a) /. (Array.length(a) |> float_of_int);
|
||||
let min = a => Belt.Array.reduce(a, a[0], (i, j) => i < j ? i : j);
|
||||
let max = a => Belt.Array.reduce(a, a[0], (i, j) => i > j ? i : j);
|
||||
let up = (a, b) =>
|
||||
Array.make(b - a + 1, a)
|
||||
|> Array.mapi((i, c) => c + i)
|
||||
|> Belt.Array.map(_, float_of_int);
|
||||
let down = (a, b) =>
|
||||
Array.make(a - b + 1, a)
|
||||
|> Array.mapi((i, c) => c - i)
|
||||
|> Belt.Array.map(_, float_of_int);
|
||||
let range = (min: float, max: float, n: int): array(float) => {
|
||||
switch (n) {
|
||||
| 0 => [||]
|
||||
| 1 => [|min|]
|
||||
| 2 => [|min, max|]
|
||||
| _ when min == max => Belt.Array.make(n, min)
|
||||
| _ when n < 0 => raise(RangeWrong("n is less then zero"))
|
||||
| _ when min > max => raise(RangeWrong("Min values is less then max"))
|
||||
| _ =>
|
||||
let diff = (max -. min) /. Belt.Float.fromInt(n - 1);
|
||||
Belt.Array.makeBy(n, i => {min +. Belt.Float.fromInt(i) *. diff});
|
||||
};
|
||||
};
|
||||
let random = Js.Math.random_int;
|
Loading…
Reference in New Issue
Block a user