commit
45017f3145
|
@ -6,12 +6,12 @@ let makeTest = (~only=false, str, item1, item2) =>
|
||||||
? Only.test(str, () => expect(item1) -> toEqual(item2))
|
? Only.test(str, () => expect(item1) -> toEqual(item2))
|
||||||
: test(str, () => expect(item1) -> toEqual(item2))
|
: test(str, () => expect(item1) -> toEqual(item2))
|
||||||
|
|
||||||
describe("DistTypes", () =>
|
describe("PointSetTypes", () =>
|
||||||
describe("Domain", () => {
|
describe("Domain", () => {
|
||||||
let makeComplete = (yPoint, expectation) =>
|
let makeComplete = (yPoint, expectation) =>
|
||||||
makeTest(
|
makeTest(
|
||||||
"With input: " ++ Js.Float.toString(yPoint),
|
"With input: " ++ Js.Float.toString(yPoint),
|
||||||
DistTypes.Domain.yPointToSubYPoint(Complete, yPoint),
|
PointSetTypes.Domain.yPointToSubYPoint(Complete, yPoint),
|
||||||
expectation,
|
expectation,
|
||||||
)
|
)
|
||||||
let makeSingle = (direction: [#left | #right], excludingProbabilityMass, yPoint, expectation) =>
|
let makeSingle = (direction: [#left | #right], excludingProbabilityMass, yPoint, expectation) =>
|
||||||
|
@ -19,7 +19,7 @@ describe("DistTypes", () =>
|
||||||
"Excluding: " ++
|
"Excluding: " ++
|
||||||
(Js.Float.toString(excludingProbabilityMass) ++
|
(Js.Float.toString(excludingProbabilityMass) ++
|
||||||
(" and yPoint: " ++ Js.Float.toString(yPoint))),
|
(" and yPoint: " ++ Js.Float.toString(yPoint))),
|
||||||
DistTypes.Domain.yPointToSubYPoint(
|
PointSetTypes.Domain.yPointToSubYPoint(
|
||||||
direction == #left
|
direction == #left
|
||||||
? LeftLimited({xPoint: 3.0, excludingProbabilityMass: excludingProbabilityMass})
|
? LeftLimited({xPoint: 3.0, excludingProbabilityMass: excludingProbabilityMass})
|
||||||
: RightLimited({xPoint: 3.0, excludingProbabilityMass: excludingProbabilityMass}),
|
: RightLimited({xPoint: 3.0, excludingProbabilityMass: excludingProbabilityMass}),
|
||||||
|
@ -28,7 +28,7 @@ describe("DistTypes", () =>
|
||||||
expectation,
|
expectation,
|
||||||
)
|
)
|
||||||
let makeDouble = (domain, yPoint, expectation) =>
|
let makeDouble = (domain, yPoint, expectation) =>
|
||||||
makeTest("Excluding: limits", DistTypes.Domain.yPointToSubYPoint(domain, yPoint), expectation)
|
makeTest("Excluding: limits", PointSetTypes.Domain.yPointToSubYPoint(domain, yPoint), expectation)
|
||||||
|
|
||||||
describe("With Complete Domain", () => {
|
describe("With Complete Domain", () => {
|
||||||
makeComplete(0.0, Some(0.0))
|
makeComplete(0.0, Some(0.0))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
|
|
||||||
let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
// let PointSetDist: PointSetTypes.xyPointSetDist = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
|
|
||||||
// let makeTest = (~only=false, str, item1, item2) =>
|
// let makeTest = (~only=false, str, item1, item2) =>
|
||||||
// only
|
// only
|
||||||
|
@ -21,15 +21,15 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// expect(item1) |> toBeSoCloseTo(item2, ~digits)
|
// expect(item1) |> toBeSoCloseTo(item2, ~digits)
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// describe("Shape", () => {
|
// describe("PointSetDist", () => {
|
||||||
// describe("Continuous", () => {
|
// describe("Continuous", () => {
|
||||||
// open Continuous;
|
// open Continuous;
|
||||||
// let continuous = make(`Linear, shape, None);
|
// let continuous = make(`Linear, PointSetDist, None);
|
||||||
// makeTest("minX", T.minX(continuous), 1.0);
|
// makeTest("minX", T.minX(continuous), 1.0);
|
||||||
// makeTest("maxX", T.maxX(continuous), 8.0);
|
// makeTest("maxX", T.maxX(continuous), 8.0);
|
||||||
// makeTest(
|
// makeTest(
|
||||||
// "mapY",
|
// "mapY",
|
||||||
// T.mapY(r => r *. 2.0, continuous) |> getShape |> (r => r.ys),
|
// T.mapY(r => r *. 2.0, continuous) |> getPointSetDist |> (r => r.ys),
|
||||||
// [|16., 18.0, 4.0|],
|
// [|16., 18.0, 4.0|],
|
||||||
// );
|
// );
|
||||||
// describe("xToY", () => {
|
// describe("xToY", () => {
|
||||||
|
@ -57,7 +57,7 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// );
|
// );
|
||||||
// });
|
// });
|
||||||
// describe("when Stepwise", () => {
|
// describe("when Stepwise", () => {
|
||||||
// let continuous = make(`Stepwise, shape, None);
|
// let continuous = make(`Stepwise, PointSetDist, None);
|
||||||
// makeTest(
|
// makeTest(
|
||||||
// "at 4.0",
|
// "at 4.0",
|
||||||
// T.xToY(4., continuous),
|
// T.xToY(4., continuous),
|
||||||
|
@ -82,7 +82,7 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// });
|
// });
|
||||||
// makeTest(
|
// makeTest(
|
||||||
// "integral",
|
// "integral",
|
||||||
// T.Integral.get(~cache=None, continuous) |> getShape,
|
// T.Integral.get(~cache=None, continuous) |> getPointSetDist,
|
||||||
// {xs: [|1.0, 4.0, 8.0|], ys: [|0.0, 25.5, 47.5|]},
|
// {xs: [|1.0, 4.0, 8.0|], ys: [|0.0, 25.5, 47.5|]},
|
||||||
// );
|
// );
|
||||||
// makeTest(
|
// makeTest(
|
||||||
|
@ -90,7 +90,7 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// {
|
// {
|
||||||
// let continuous =
|
// let continuous =
|
||||||
// make(`Stepwise, {xs: [|1., 4., 8.|], ys: [|0.1, 5., 1.0|]}, None);
|
// make(`Stepwise, {xs: [|1., 4., 8.|], ys: [|0.1, 5., 1.0|]}, None);
|
||||||
// continuous |> toLinear |> E.O.fmap(getShape);
|
// continuous |> toLinear |> E.O.fmap(getPointSetDist);
|
||||||
// },
|
// },
|
||||||
// Some({
|
// Some({
|
||||||
// xs: [|1.00007, 1.00007, 4.0, 4.00007, 8.0, 8.00007|],
|
// xs: [|1.00007, 1.00007, 4.0, 4.00007, 8.0, 8.00007|],
|
||||||
|
@ -101,7 +101,7 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// "toLinear",
|
// "toLinear",
|
||||||
// {
|
// {
|
||||||
// let continuous = make(`Stepwise, {xs: [|0.0|], ys: [|0.3|]}, None);
|
// let continuous = make(`Stepwise, {xs: [|0.0|], ys: [|0.3|]}, None);
|
||||||
// continuous |> toLinear |> E.O.fmap(getShape);
|
// continuous |> toLinear |> E.O.fmap(getPointSetDist);
|
||||||
// },
|
// },
|
||||||
// Some({xs: [|0.0|], ys: [|0.3|]}),
|
// Some({xs: [|0.0|], ys: [|0.3|]}),
|
||||||
// );
|
// );
|
||||||
|
@ -131,16 +131,16 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
|
|
||||||
// describe("Discrete", () => {
|
// describe("Discrete", () => {
|
||||||
// open Discrete;
|
// open Discrete;
|
||||||
// let shape: DistTypes.xyShape = {
|
// let PointSetDist: PointSetTypes.xyPointSetDist = {
|
||||||
// xs: [|1., 4., 8.|],
|
// xs: [|1., 4., 8.|],
|
||||||
// ys: [|0.3, 0.5, 0.2|],
|
// ys: [|0.3, 0.5, 0.2|],
|
||||||
// };
|
// };
|
||||||
// let discrete = make(shape, None);
|
// let discrete = make(PointSetDist, None);
|
||||||
// makeTest("minX", T.minX(discrete), 1.0);
|
// makeTest("minX", T.minX(discrete), 1.0);
|
||||||
// makeTest("maxX", T.maxX(discrete), 8.0);
|
// makeTest("maxX", T.maxX(discrete), 8.0);
|
||||||
// makeTest(
|
// makeTest(
|
||||||
// "mapY",
|
// "mapY",
|
||||||
// T.mapY(r => r *. 2.0, discrete) |> (r => getShape(r).ys),
|
// T.mapY(r => r *. 2.0, discrete) |> (r => getPointSetDist(r).ys),
|
||||||
// [|0.6, 1.0, 0.4|],
|
// [|0.6, 1.0, 0.4|],
|
||||||
// );
|
// );
|
||||||
// makeTest(
|
// makeTest(
|
||||||
|
@ -209,11 +209,11 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
|
|
||||||
// describe("Mixed", () => {
|
// describe("Mixed", () => {
|
||||||
// open Distributions.Mixed;
|
// open Distributions.Mixed;
|
||||||
// let discreteShape: DistTypes.xyShape = {
|
// let discretePointSetDist: PointSetTypes.xyPointSetDist = {
|
||||||
// xs: [|1., 4., 8.|],
|
// xs: [|1., 4., 8.|],
|
||||||
// ys: [|0.3, 0.5, 0.2|],
|
// ys: [|0.3, 0.5, 0.2|],
|
||||||
// };
|
// };
|
||||||
// let discrete = Discrete.make(discreteShape, None);
|
// let discrete = Discrete.make(discretePointSetDist, None);
|
||||||
// let continuous =
|
// let continuous =
|
||||||
// Continuous.make(
|
// Continuous.make(
|
||||||
// `Linear,
|
// `Linear,
|
||||||
|
@ -309,11 +309,11 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
|
|
||||||
// describe("Distplus", () => {
|
// describe("Distplus", () => {
|
||||||
// open DistPlus;
|
// open DistPlus;
|
||||||
// let discreteShape: DistTypes.xyShape = {
|
// let discretePointSetDist: PointSetTypes.xyPointSetDist = {
|
||||||
// xs: [|1., 4., 8.|],
|
// xs: [|1., 4., 8.|],
|
||||||
// ys: [|0.3, 0.5, 0.2|],
|
// ys: [|0.3, 0.5, 0.2|],
|
||||||
// };
|
// };
|
||||||
// let discrete = Discrete.make(discreteShape, None);
|
// let discrete = Discrete.make(discretePointSetDist, None);
|
||||||
// let continuous =
|
// let continuous =
|
||||||
// Continuous.make(
|
// Continuous.make(
|
||||||
// `Linear,
|
// `Linear,
|
||||||
|
@ -328,7 +328,7 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// );
|
// );
|
||||||
// let distPlus =
|
// let distPlus =
|
||||||
// DistPlus.make(
|
// DistPlus.make(
|
||||||
// ~shape=Mixed(mixed),
|
// ~PointSetDist=Mixed(mixed),
|
||||||
// ~squiggleString=None,
|
// ~squiggleString=None,
|
||||||
// (),
|
// (),
|
||||||
// );
|
// );
|
||||||
|
@ -376,38 +376,38 @@ let shape: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [8., 9., 2.]}
|
||||||
// );
|
// );
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// describe("Shape", () => {
|
// describe("PointSetDist", () => {
|
||||||
// let mean = 10.0;
|
// let mean = 10.0;
|
||||||
// let stdev = 4.0;
|
// let stdev = 4.0;
|
||||||
// let variance = stdev ** 2.0;
|
// let variance = stdev ** 2.0;
|
||||||
// let numSamples = 10000;
|
// let numSamples = 10000;
|
||||||
// open Distributions.Shape;
|
// open Distributions.PointSetDist;
|
||||||
// let normal: SymbolicTypes.symbolicDist = `Normal({mean, stdev});
|
// let normal: SymbolicDistTypes.symbolicDist = `Normal({mean, stdev});
|
||||||
// let normalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(normal));
|
// let normalPointSetDist = AST.toPointSetDist(numSamples, `SymbolicDist(normal));
|
||||||
// let lognormal = SymbolicDist.Lognormal.fromMeanAndStdev(mean, stdev);
|
// let lognormal = SymbolicDist.Lognormal.fromMeanAndStdev(mean, stdev);
|
||||||
// let lognormalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(lognormal));
|
// let lognormalPointSetDist = AST.toPointSetDist(numSamples, `SymbolicDist(lognormal));
|
||||||
|
|
||||||
// makeTestCloseEquality(
|
// makeTestCloseEquality(
|
||||||
// "Mean of a normal",
|
// "Mean of a normal",
|
||||||
// T.mean(normalShape),
|
// T.mean(normalPointSetDist),
|
||||||
// mean,
|
// mean,
|
||||||
// ~digits=2,
|
// ~digits=2,
|
||||||
// );
|
// );
|
||||||
// makeTestCloseEquality(
|
// makeTestCloseEquality(
|
||||||
// "Variance of a normal",
|
// "Variance of a normal",
|
||||||
// T.variance(normalShape),
|
// T.variance(normalPointSetDist),
|
||||||
// variance,
|
// variance,
|
||||||
// ~digits=1,
|
// ~digits=1,
|
||||||
// );
|
// );
|
||||||
// makeTestCloseEquality(
|
// makeTestCloseEquality(
|
||||||
// "Mean of a lognormal",
|
// "Mean of a lognormal",
|
||||||
// T.mean(lognormalShape),
|
// T.mean(lognormalPointSetDist),
|
||||||
// mean,
|
// mean,
|
||||||
// ~digits=2,
|
// ~digits=2,
|
||||||
// );
|
// );
|
||||||
// makeTestCloseEquality(
|
// makeTestCloseEquality(
|
||||||
// "Variance of a lognormal",
|
// "Variance of a lognormal",
|
||||||
// T.variance(lognormalShape),
|
// T.variance(lognormalPointSetDist),
|
||||||
// variance,
|
// variance,
|
||||||
// ~digits=0,
|
// ~digits=0,
|
||||||
// );
|
// );
|
||||||
|
|
|
@ -10,12 +10,12 @@ let makeTest = (~only=false, str, item1, item2) =>
|
||||||
expect(item1) |> toEqual(item2)
|
expect(item1) |> toEqual(item2)
|
||||||
);
|
);
|
||||||
|
|
||||||
let evalParams: ExpressionTypes.ExpressionTree.evaluationParams = {
|
let evalParams: ASTTypes.AST.evaluationParams = {
|
||||||
samplingInputs: {
|
samplingInputs: {
|
||||||
sampleCount: 1000,
|
sampleCount: 1000,
|
||||||
outputXYPoints: 10000,
|
outputXYPoints: 10000,
|
||||||
kernelWidth: None,
|
kernelWidth: None,
|
||||||
shapeLength: 1000,
|
PointSetDistLength: 1000,
|
||||||
},
|
},
|
||||||
environment:
|
environment:
|
||||||
[|
|
[|
|
||||||
|
@ -25,12 +25,12 @@ let evalParams: ExpressionTypes.ExpressionTree.evaluationParams = {
|
||||||
("T", `SymbolicDist(`Float(1000000000000.0))),
|
("T", `SymbolicDist(`Float(1000000000000.0))),
|
||||||
|]
|
|]
|
||||||
->Belt.Map.String.fromArray,
|
->Belt.Map.String.fromArray,
|
||||||
evaluateNode: ExpressionTreeEvaluator.toLeaf,
|
evaluateNode: ASTEvaluator.toLeaf,
|
||||||
};
|
};
|
||||||
|
|
||||||
let shape1: DistTypes.xyShape = {xs: [|1., 4., 8.|], ys: [|0.2, 0.4, 0.8|]};
|
let PointSetDist1: PointSetTypes.xyPointSetDist = {xs: [|1., 4., 8.|], ys: [|0.2, 0.4, 0.8|]};
|
||||||
|
|
||||||
describe("XYShapes", () => {
|
describe("XYPointSetDists", () => {
|
||||||
describe("logScorePoint", () => {
|
describe("logScorePoint", () => {
|
||||||
makeTest(
|
makeTest(
|
||||||
"When identical",
|
"When identical",
|
||||||
|
|
|
@ -10,12 +10,12 @@ describe("Lodash", () =>
|
||||||
describe("Lodash", () => {
|
describe("Lodash", () => {
|
||||||
makeTest(
|
makeTest(
|
||||||
"split",
|
"split",
|
||||||
SamplesToShape.Internals.T.splitContinuousAndDiscrete([1.432, 1.33455, 2.0]),
|
SampleSet.Internals.T.splitContinuousAndDiscrete([1.432, 1.33455, 2.0]),
|
||||||
([1.432, 1.33455, 2.0], E.FloatFloatMap.empty()),
|
([1.432, 1.33455, 2.0], E.FloatFloatMap.empty()),
|
||||||
)
|
)
|
||||||
makeTest(
|
makeTest(
|
||||||
"split",
|
"split",
|
||||||
SamplesToShape.Internals.T.splitContinuousAndDiscrete([
|
SampleSet.Internals.T.splitContinuousAndDiscrete([
|
||||||
1.432,
|
1.432,
|
||||||
1.33455,
|
1.33455,
|
||||||
2.0,
|
2.0,
|
||||||
|
@ -32,13 +32,13 @@ describe("Lodash", () =>
|
||||||
E.A.concatMany([sorted, sorted, sorted, sorted]) |> Belt.SortArray.stableSortBy(_, compare)
|
E.A.concatMany([sorted, sorted, sorted, sorted]) |> Belt.SortArray.stableSortBy(_, compare)
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, discrete) = SamplesToShape.Internals.T.splitContinuousAndDiscrete(
|
let (_, discrete) = SampleSet.Internals.T.splitContinuousAndDiscrete(
|
||||||
makeDuplicatedArray(10),
|
makeDuplicatedArray(10),
|
||||||
)
|
)
|
||||||
let toArr = discrete |> E.FloatFloatMap.toArray
|
let toArr = discrete |> E.FloatFloatMap.toArray
|
||||||
makeTest("splitMedium", toArr |> Belt.Array.length, 10)
|
makeTest("splitMedium", toArr |> Belt.Array.length, 10)
|
||||||
|
|
||||||
let (c, discrete) = SamplesToShape.Internals.T.splitContinuousAndDiscrete(
|
let (c, discrete) = SampleSet.Internals.T.splitContinuousAndDiscrete(
|
||||||
makeDuplicatedArray(500),
|
makeDuplicatedArray(500),
|
||||||
)
|
)
|
||||||
let toArr = discrete |> E.FloatFloatMap.toArray
|
let toArr = discrete |> E.FloatFloatMap.toArray
|
||||||
|
|
|
@ -6,25 +6,25 @@ let makeTest = (~only=false, str, item1, item2) =>
|
||||||
? Only.test(str, () => expect(item1) -> toEqual(item2))
|
? Only.test(str, () => expect(item1) -> toEqual(item2))
|
||||||
: test(str, () => expect(item1) -> toEqual(item2))
|
: test(str, () => expect(item1) -> toEqual(item2))
|
||||||
|
|
||||||
let shape1: DistTypes.xyShape = {xs: [1., 4., 8.], ys: [0.2, 0.4, 0.8]}
|
let pointSetDist1: PointSetTypes.xyShape = {xs: [1., 4., 8.], ys: [0.2, 0.4, 0.8]}
|
||||||
|
|
||||||
let shape2: DistTypes.xyShape = {
|
let pointSetDist2: PointSetTypes.xyShape = {
|
||||||
xs: [1., 5., 10.],
|
xs: [1., 5., 10.],
|
||||||
ys: [0.2, 0.5, 0.8],
|
ys: [0.2, 0.5, 0.8],
|
||||||
}
|
}
|
||||||
|
|
||||||
let shape3: DistTypes.xyShape = {
|
let pointSetDist3: PointSetTypes.xyShape = {
|
||||||
xs: [1., 20., 50.],
|
xs: [1., 20., 50.],
|
||||||
ys: [0.2, 0.5, 0.8],
|
ys: [0.2, 0.5, 0.8],
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("XYShapes", () => {
|
describe("XYShapes", () => {
|
||||||
describe("logScorePoint", () => {
|
describe("logScorePoint", () => {
|
||||||
makeTest("When identical", XYShape.logScorePoint(30, shape1, shape1), Some(0.0))
|
makeTest("When identical", XYShape.logScorePoint(30, pointSetDist1, pointSetDist1), Some(0.0))
|
||||||
makeTest("When similar", XYShape.logScorePoint(30, shape1, shape2), Some(1.658971191043856))
|
makeTest("When similar", XYShape.logScorePoint(30, pointSetDist1, pointSetDist2), Some(1.658971191043856))
|
||||||
makeTest(
|
makeTest(
|
||||||
"When very different",
|
"When very different",
|
||||||
XYShape.logScorePoint(30, shape1, shape3),
|
XYShape.logScorePoint(30, pointSetDist1, pointSetDist3),
|
||||||
Some(210.3721280423322),
|
Some(210.3721280423322),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -41,7 +41,7 @@ describe("XYShapes", () => {
|
||||||
describe("integrateWithTriangles", () =>
|
describe("integrateWithTriangles", () =>
|
||||||
makeTest(
|
makeTest(
|
||||||
"integrates correctly",
|
"integrates correctly",
|
||||||
XYShape.Range.integrateWithTriangles(shape1),
|
XYShape.Range.integrateWithTriangles(pointSetDist1),
|
||||||
Some({
|
Some({
|
||||||
xs: [1., 4., 8.],
|
xs: [1., 4., 8.],
|
||||||
ys: [0.0, 0.9000000000000001, 3.3000000000000007],
|
ys: [0.0, 0.9000000000000001, 3.3000000000000007],
|
||||||
|
|
36
packages/squiggle-lang/dist/index.js
vendored
36
packages/squiggle-lang/dist/index.js
vendored
File diff suppressed because one or more lines are too long
2
packages/squiggle-lang/dist/report.html
vendored
2
packages/squiggle-lang/dist/report.html
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +0,0 @@
|
||||||
type t = ExpressionTypes.Program.program
|
|
||||||
|
|
||||||
let last = (r: t) => E.A.last(r) |> E.O.toResult("No rendered lines")
|
|
||||||
// let run = (p:program) => p |> E.A.last |> E.O.fmap(r =>
|
|
||||||
// )
|
|
|
@ -1,3 +1,3 @@
|
||||||
const ProgramEvaluator = require('../distPlus/ProgramEvaluator.gen.js');
|
const ProgramEvaluator = require('../rescript/ProgramEvaluator.gen.js');
|
||||||
|
|
||||||
exports.runMePlease = ProgramEvaluator.runAll
|
exports.runMePlease = ProgramEvaluator.runAll
|
|
@ -5,7 +5,7 @@ module Inputs = {
|
||||||
sampleCount: option<int>,
|
sampleCount: option<int>,
|
||||||
outputXYPoints: option<int>,
|
outputXYPoints: option<int>,
|
||||||
kernelWidth: option<float>,
|
kernelWidth: option<float>,
|
||||||
shapeLength: option<int>,
|
pointSetDistLength: option<int>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let defaultRecommendedLength = 100
|
let defaultRecommendedLength = 100
|
||||||
|
@ -14,20 +14,20 @@ module Inputs = {
|
||||||
type inputs = {
|
type inputs = {
|
||||||
squiggleString: string,
|
squiggleString: string,
|
||||||
samplingInputs: SamplingInputs.t,
|
samplingInputs: SamplingInputs.t,
|
||||||
environment: ExpressionTypes.ExpressionTree.environment,
|
environment: ASTTypes.AST.environment,
|
||||||
}
|
}
|
||||||
|
|
||||||
let empty: SamplingInputs.t = {
|
let empty: SamplingInputs.t = {
|
||||||
sampleCount: None,
|
sampleCount: None,
|
||||||
outputXYPoints: None,
|
outputXYPoints: None,
|
||||||
kernelWidth: None,
|
kernelWidth: None,
|
||||||
shapeLength: None,
|
pointSetDistLength: None,
|
||||||
}
|
}
|
||||||
|
|
||||||
let make = (
|
let make = (
|
||||||
~samplingInputs=empty,
|
~samplingInputs=empty,
|
||||||
~squiggleString,
|
~squiggleString,
|
||||||
~environment=ExpressionTypes.ExpressionTree.Environment.empty,
|
~environment=ASTTypes.AST.Environment.empty,
|
||||||
(),
|
(),
|
||||||
): inputs => {
|
): inputs => {
|
||||||
samplingInputs: samplingInputs,
|
samplingInputs: samplingInputs,
|
||||||
|
@ -40,8 +40,8 @@ type \"export" = [
|
||||||
| #DistPlus(DistPlus.t)
|
| #DistPlus(DistPlus.t)
|
||||||
| #Float(float)
|
| #Float(float)
|
||||||
| #Function(
|
| #Function(
|
||||||
(array<string>, ExpressionTypes.ExpressionTree.node),
|
(array<string>, ASTTypes.AST.node),
|
||||||
ExpressionTypes.ExpressionTree.environment,
|
ASTTypes.AST.environment,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -53,28 +53,28 @@ module Internals = {
|
||||||
): Inputs.inputs => {
|
): Inputs.inputs => {
|
||||||
samplingInputs: samplingInputs,
|
samplingInputs: samplingInputs,
|
||||||
squiggleString: squiggleString,
|
squiggleString: squiggleString,
|
||||||
environment: ExpressionTypes.ExpressionTree.Environment.update(environment, str, _ => Some(
|
environment: ASTTypes.AST.Environment.update(environment, str, _ => Some(
|
||||||
node,
|
node,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
|
||||||
type outputs = {
|
type outputs = {
|
||||||
graph: ExpressionTypes.ExpressionTree.node,
|
graph: ASTTypes.AST.node,
|
||||||
shape: DistTypes.shape,
|
pointSetDist: PointSetTypes.pointSetDist,
|
||||||
}
|
}
|
||||||
let makeOutputs = (graph, shape): outputs => {graph: graph, shape: shape}
|
let makeOutputs = (graph, pointSetDist): outputs => {graph: graph, pointSetDist: pointSetDist}
|
||||||
|
|
||||||
let makeInputs = (inputs: Inputs.inputs): ExpressionTypes.ExpressionTree.samplingInputs => {
|
let makeInputs = (inputs: Inputs.inputs): ASTTypes.AST.samplingInputs => {
|
||||||
sampleCount: inputs.samplingInputs.sampleCount |> E.O.default(10000),
|
sampleCount: inputs.samplingInputs.sampleCount |> E.O.default(10000),
|
||||||
outputXYPoints: inputs.samplingInputs.outputXYPoints |> E.O.default(10000),
|
outputXYPoints: inputs.samplingInputs.outputXYPoints |> E.O.default(10000),
|
||||||
kernelWidth: inputs.samplingInputs.kernelWidth,
|
kernelWidth: inputs.samplingInputs.kernelWidth,
|
||||||
shapeLength: inputs.samplingInputs.shapeLength |> E.O.default(10000),
|
pointSetDistLength: inputs.samplingInputs.pointSetDistLength |> E.O.default(10000),
|
||||||
}
|
}
|
||||||
|
|
||||||
let runNode = (inputs, node) =>
|
let runNode = (inputs, node) =>
|
||||||
ExpressionTree.toLeaf(makeInputs(inputs), inputs.environment, node)
|
AST.toLeaf(makeInputs(inputs), inputs.environment, node)
|
||||||
|
|
||||||
let runProgram = (inputs: Inputs.inputs, p: ExpressionTypes.Program.program) => {
|
let runProgram = (inputs: Inputs.inputs, p: ASTTypes.Program.program) => {
|
||||||
let ins = ref(inputs)
|
let ins = ref(inputs)
|
||||||
p
|
p
|
||||||
|> E.A.fmap(x =>
|
|> E.A.fmap(x =>
|
||||||
|
@ -91,14 +91,14 @@ module Internals = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputsToLeaf = (inputs: Inputs.inputs) =>
|
let inputsToLeaf = (inputs: Inputs.inputs) =>
|
||||||
MathJsParser.fromString(inputs.squiggleString) |> E.R.bind(_, g => runProgram(inputs, g))
|
Parser.fromString(inputs.squiggleString) |> E.R.bind(_, g => runProgram(inputs, g))
|
||||||
|
|
||||||
let outputToDistPlus = (inputs: Inputs.inputs, shape: DistTypes.shape) =>
|
let outputToDistPlus = (inputs: Inputs.inputs, pointSetDist: PointSetTypes.pointSetDist) =>
|
||||||
DistPlus.make(~shape, ~squiggleString=Some(inputs.squiggleString), ())
|
DistPlus.make(~pointSetDist, ~squiggleString=Some(inputs.squiggleString), ())
|
||||||
}
|
}
|
||||||
|
|
||||||
let renderIfNeeded = (inputs: Inputs.inputs, node: ExpressionTypes.ExpressionTree.node): result<
|
let renderIfNeeded = (inputs: Inputs.inputs, node: ASTTypes.AST.node): result<
|
||||||
ExpressionTypes.ExpressionTree.node,
|
ASTTypes.AST.node,
|
||||||
string,
|
string,
|
||||||
> =>
|
> =>
|
||||||
node |> (
|
node |> (
|
||||||
|
@ -121,11 +121,11 @@ let renderIfNeeded = (inputs: Inputs.inputs, node: ExpressionTypes.ExpressionTre
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Consider using ExpressionTypes.ExpressionTree.getFloat or similar in this function
|
// TODO: Consider using ASTTypes.AST.getFloat or similar in this function
|
||||||
let coersionToExportedTypes = (
|
let coersionToExportedTypes = (
|
||||||
inputs,
|
inputs,
|
||||||
env: ExpressionTypes.ExpressionTree.environment,
|
env: ASTTypes.AST.environment,
|
||||||
node: ExpressionTypes.ExpressionTree.node,
|
node: ASTTypes.AST.node,
|
||||||
): result<\"export", string> =>
|
): result<\"export", string> =>
|
||||||
node
|
node
|
||||||
|> renderIfNeeded(inputs)
|
|> renderIfNeeded(inputs)
|
||||||
|
@ -135,7 +135,7 @@ let coersionToExportedTypes = (
|
||||||
| #SymbolicDist(#Float(x)) => Ok(#Float(x))
|
| #SymbolicDist(#Float(x)) => Ok(#Float(x))
|
||||||
| #RenderedDist(n) => Ok(#DistPlus(Internals.outputToDistPlus(inputs, n)))
|
| #RenderedDist(n) => Ok(#DistPlus(Internals.outputToDistPlus(inputs, n)))
|
||||||
| #Function(n) => Ok(#Function(n, env))
|
| #Function(n) => Ok(#Function(n, env))
|
||||||
| n => Error("Didn't output a rendered distribution. Format:" ++ ExpressionTree.toString(n))
|
| n => Error("Didn't output a rendered distribution. Format:" ++ AST.toString(n))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -160,10 +160,10 @@ let evaluateProgram = (inputs: Inputs.inputs) =>
|
||||||
|
|
||||||
let evaluateFunction = (
|
let evaluateFunction = (
|
||||||
inputs: Inputs.inputs,
|
inputs: Inputs.inputs,
|
||||||
fn: (array<string>, ExpressionTypes.ExpressionTree.node),
|
fn: (array<string>, ASTTypes.AST.node),
|
||||||
fnInputs,
|
fnInputs,
|
||||||
) => {
|
) => {
|
||||||
let output = ExpressionTree.runFunction(
|
let output = AST.runFunction(
|
||||||
Internals.makeInputs(inputs),
|
Internals.makeInputs(inputs),
|
||||||
inputs.environment,
|
inputs.environment,
|
||||||
fnInputs,
|
fnInputs,
|
||||||
|
@ -179,7 +179,7 @@ let runAll = (squiggleString: string) => {
|
||||||
sampleCount: Some(10000),
|
sampleCount: Some(10000),
|
||||||
outputXYPoints: Some(10000),
|
outputXYPoints: Some(10000),
|
||||||
kernelWidth: None,
|
kernelWidth: None,
|
||||||
shapeLength: Some(1000),
|
pointSetDistLength: Some(1000),
|
||||||
},
|
},
|
||||||
~squiggleString,
|
~squiggleString,
|
||||||
~environment=[]->Belt.Map.String.fromArray,
|
~environment=[]->Belt.Map.String.fromArray,
|
|
@ -1,17 +1,19 @@
|
||||||
open ExpressionTypes.ExpressionTree
|
open ASTTypes.AST
|
||||||
|
|
||||||
|
let toString = ASTBasic.toString
|
||||||
|
|
||||||
let toString = ExpressionTreeBasic.toString
|
|
||||||
let envs = (samplingInputs, environment) => {
|
let envs = (samplingInputs, environment) => {
|
||||||
samplingInputs: samplingInputs,
|
samplingInputs: samplingInputs,
|
||||||
environment: environment,
|
environment: environment,
|
||||||
evaluateNode: ExpressionTreeEvaluator.toLeaf,
|
evaluateNode: ASTEvaluator.toLeaf,
|
||||||
}
|
}
|
||||||
|
|
||||||
let toLeaf = (samplingInputs, environment, node: node) =>
|
let toLeaf = (samplingInputs, environment, node: node) =>
|
||||||
ExpressionTreeEvaluator.toLeaf(envs(samplingInputs, environment), node)
|
ASTEvaluator.toLeaf(envs(samplingInputs, environment), node)
|
||||||
let toShape = (samplingInputs, environment, node: node) =>
|
|
||||||
|
let toPointSetDist = (samplingInputs, environment, node: node) =>
|
||||||
switch toLeaf(samplingInputs, environment, node) {
|
switch toLeaf(samplingInputs, environment, node) {
|
||||||
| Ok(#RenderedDist(shape)) => Ok(shape)
|
| Ok(#RenderedDist(pointSetDist)) => Ok(pointSetDist)
|
||||||
| Ok(_) => Error("Rendering failed.")
|
| Ok(_) => Error("Rendering failed.")
|
||||||
| Error(e) => Error(e)
|
| Error(e) => Error(e)
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
open ExpressionTypes.ExpressionTree
|
open ASTTypes.AST
|
||||||
|
// This file exists to manage a dependency cycle. It would be good to refactor later.
|
||||||
|
|
||||||
let rec toString: node => string = x =>
|
let rec toString: node => string = x =>
|
||||||
switch x {
|
switch x {
|
||||||
|
@ -23,4 +24,4 @@ let rec toString: node => string = x =>
|
||||||
|> E.A.fmap(((name, value)) => name ++ (":" ++ toString(value)))
|
|> E.A.fmap(((name, value)) => name ++ (":" ++ toString(value)))
|
||||||
|> Js.String.concatMany(_, ",")) ++
|
|> Js.String.concatMany(_, ",")) ++
|
||||||
"}")
|
"}")
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
open ExpressionTypes
|
open ASTTypes
|
||||||
open ExpressionTypes.ExpressionTree
|
open ASTTypes.AST
|
||||||
|
|
||||||
type t = node
|
type t = node
|
||||||
type tResult = node => result<node, string>
|
type tResult = node => result<node, string>
|
||||||
|
@ -27,7 +27,7 @@ module AlgebraicCombination = {
|
||||||
E.R.merge(
|
E.R.merge(
|
||||||
Render.ensureIsRenderedAndGetShape(evaluationParams, t1),
|
Render.ensureIsRenderedAndGetShape(evaluationParams, t1),
|
||||||
Render.ensureIsRenderedAndGetShape(evaluationParams, t2),
|
Render.ensureIsRenderedAndGetShape(evaluationParams, t2),
|
||||||
) |> E.R.fmap(((a, b)) => #RenderedDist(Shape.combineAlgebraically(algebraicOp, a, b)))
|
) |> E.R.fmap(((a, b)) => #RenderedDist(PointSetDist.combineAlgebraically(algebraicOp, a, b)))
|
||||||
|
|
||||||
let nodeScore: node => int = x =>
|
let nodeScore: node => int = x =>
|
||||||
switch x {
|
switch x {
|
||||||
|
@ -56,7 +56,7 @@ module AlgebraicCombination = {
|
||||||
|
|
||||||
let operationToLeaf = (
|
let operationToLeaf = (
|
||||||
evaluationParams: evaluationParams,
|
evaluationParams: evaluationParams,
|
||||||
algebraicOp: ExpressionTypes.algebraicOperation,
|
algebraicOp: ASTTypes.algebraicOperation,
|
||||||
t1: t,
|
t1: t,
|
||||||
t2: t,
|
t2: t,
|
||||||
): result<node, string> =>
|
): result<node, string> =>
|
||||||
|
@ -76,7 +76,7 @@ module PointwiseCombination = {
|
||||||
| (Ok(#RenderedDist(rs1)), Ok(#RenderedDist(rs2))) =>
|
| (Ok(#RenderedDist(rs1)), Ok(#RenderedDist(rs2))) =>
|
||||||
Ok(
|
Ok(
|
||||||
#RenderedDist(
|
#RenderedDist(
|
||||||
Shape.combinePointwise(
|
PointSetDist.combinePointwise(
|
||||||
~integralSumCachesFn=(a, b) => Some(a +. b),
|
~integralSumCachesFn=(a, b) => Some(a +. b),
|
||||||
~integralCachesFn=(a, b) => Some(
|
~integralCachesFn=(a, b) => Some(
|
||||||
Continuous.combinePointwise(~distributionType=#CDF, \"+.", a, b),
|
Continuous.combinePointwise(~distributionType=#CDF, \"+.", a, b),
|
||||||
|
@ -94,11 +94,11 @@ module PointwiseCombination = {
|
||||||
|
|
||||||
let pointwiseCombine = (fn, evaluationParams: evaluationParams, t1: t, t2: t) =>
|
let pointwiseCombine = (fn, evaluationParams: evaluationParams, t1: t, t2: t) =>
|
||||||
switch // TODO: construct a function that we can easily sample from, to construct
|
switch // TODO: construct a function that we can easily sample from, to construct
|
||||||
// a RenderedDist. Use the xMin and xMax of the rendered shapes to tell the sampling function where to look.
|
// a RenderedDist. Use the xMin and xMax of the rendered pointSetDists to tell the sampling function where to look.
|
||||||
// TODO: This should work for symbolic distributions too!
|
// TODO: This should work for symbolic distributions too!
|
||||||
(Render.render(evaluationParams, t1), Render.render(evaluationParams, t2)) {
|
(Render.render(evaluationParams, t1), Render.render(evaluationParams, t2)) {
|
||||||
| (Ok(#RenderedDist(rs1)), Ok(#RenderedDist(rs2))) =>
|
| (Ok(#RenderedDist(rs1)), Ok(#RenderedDist(rs2))) =>
|
||||||
Ok(#RenderedDist(Shape.combinePointwise(fn, rs1, rs2)))
|
Ok(#RenderedDist(PointSetDist.combinePointwise(fn, rs1, rs2)))
|
||||||
| (Error(e1), _) => Error(e1)
|
| (Error(e1), _) => Error(e1)
|
||||||
| (_, Error(e2)) => Error(e2)
|
| (_, Error(e2)) => Error(e2)
|
||||||
| _ => Error("Pointwise combination: rendering failed.")
|
| _ => Error("Pointwise combination: rendering failed.")
|
||||||
|
@ -132,7 +132,7 @@ module Truncate = {
|
||||||
switch // TODO: use named args for xMin/xMax in renderToShape; if we're lucky we can at least get the tail
|
switch // TODO: use named args for xMin/xMax in renderToShape; if we're lucky we can at least get the tail
|
||||||
// of a distribution we otherwise wouldn't get at all
|
// of a distribution we otherwise wouldn't get at all
|
||||||
Render.ensureIsRendered(evaluationParams, t) {
|
Render.ensureIsRendered(evaluationParams, t) {
|
||||||
| Ok(#RenderedDist(rs)) => Ok(#RenderedDist(Shape.T.truncate(leftCutoff, rightCutoff, rs)))
|
| Ok(#RenderedDist(rs)) => Ok(#RenderedDist(PointSetDist.T.truncate(leftCutoff, rightCutoff, rs)))
|
||||||
| Error(e) => Error(e)
|
| Error(e) => Error(e)
|
||||||
| _ => Error("Could not truncate distribution.")
|
| _ => Error("Could not truncate distribution.")
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ module Truncate = {
|
||||||
module Normalize = {
|
module Normalize = {
|
||||||
let rec operationToLeaf = (evaluationParams, t: node): result<node, string> =>
|
let rec operationToLeaf = (evaluationParams, t: node): result<node, string> =>
|
||||||
switch t {
|
switch t {
|
||||||
| #RenderedDist(s) => Ok(#RenderedDist(Shape.T.normalize(s)))
|
| #RenderedDist(s) => Ok(#RenderedDist(PointSetDist.T.normalize(s)))
|
||||||
| #SymbolicDist(_) => Ok(t)
|
| #SymbolicDist(_) => Ok(t)
|
||||||
| _ => evaluateAndRetry(evaluationParams, operationToLeaf, t)
|
| _ => evaluateAndRetry(evaluationParams, operationToLeaf, t)
|
||||||
}
|
}
|
||||||
|
@ -174,9 +174,9 @@ module FunctionCall = {
|
||||||
)
|
)
|
||||||
|
|
||||||
let _runWithEvaluatedInputs = (
|
let _runWithEvaluatedInputs = (
|
||||||
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
|
evaluationParams: ASTTypes.AST.evaluationParams,
|
||||||
name,
|
name,
|
||||||
args: array<ExpressionTypes.ExpressionTree.node>,
|
args: array<ASTTypes.AST.node>,
|
||||||
) =>
|
) =>
|
||||||
_runHardcodedFunction(name, evaluationParams, args) |> E.O.default(
|
_runHardcodedFunction(name, evaluationParams, args) |> E.O.default(
|
||||||
_runLocalFunction(name, evaluationParams, args),
|
_runLocalFunction(name, evaluationParams, args),
|
||||||
|
@ -195,8 +195,8 @@ module Render = {
|
||||||
switch t {
|
switch t {
|
||||||
| #Function(_) => Error("Cannot render a function")
|
| #Function(_) => Error("Cannot render a function")
|
||||||
| #SymbolicDist(d) =>
|
| #SymbolicDist(d) =>
|
||||||
Ok(#RenderedDist(SymbolicDist.T.toShape(evaluationParams.samplingInputs.shapeLength, d)))
|
Ok(#RenderedDist(SymbolicDist.T.toPointSetDist(evaluationParams.samplingInputs.pointSetDistLength, d)))
|
||||||
| #RenderedDist(_) as t => Ok(t) // already a rendered shape, we're done here
|
| #RenderedDist(_) as t => Ok(t) // already a rendered pointSetDist, we're done here
|
||||||
| _ => evaluateAndRetry(evaluationParams, operationToLeaf, t)
|
| _ => evaluateAndRetry(evaluationParams, operationToLeaf, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ module Render = {
|
||||||
This function is used mainly to turn a parse tree into a single RenderedDist
|
This function is used mainly to turn a parse tree into a single RenderedDist
|
||||||
that can then be displayed to the user. */
|
that can then be displayed to the user. */
|
||||||
let rec toLeaf = (
|
let rec toLeaf = (
|
||||||
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
|
evaluationParams: ASTTypes.AST.evaluationParams,
|
||||||
node: t,
|
node: t,
|
||||||
): result<t, string> =>
|
): result<t, string> =>
|
||||||
switch node {
|
switch node {
|
||||||
|
@ -236,7 +236,7 @@ let rec toLeaf = (
|
||||||
|> E.A.R.firstErrorOrOpen
|
|> E.A.R.firstErrorOrOpen
|
||||||
|> E.R.fmap(r => #Hash(r))
|
|> E.R.fmap(r => #Hash(r))
|
||||||
| #Symbol(r) =>
|
| #Symbol(r) =>
|
||||||
ExpressionTypes.ExpressionTree.Environment.get(evaluationParams.environment, r)
|
ASTTypes.AST.Environment.get(evaluationParams.environment, r)
|
||||||
|> E.O.toResult("Undeclared variable " ++ r)
|
|> E.O.toResult("Undeclared variable " ++ r)
|
||||||
|> E.R.bind(_, toLeaf(evaluationParams))
|
|> E.R.bind(_, toLeaf(evaluationParams))
|
||||||
| #FunctionCall(name, args) =>
|
| #FunctionCall(name, args) =>
|
|
@ -15,11 +15,11 @@ type distToFloatOperation = [
|
||||||
| #Sample
|
| #Sample
|
||||||
]
|
]
|
||||||
|
|
||||||
module ExpressionTree = {
|
module AST = {
|
||||||
type rec hash = array<(string, node)>
|
type rec hash = array<(string, node)>
|
||||||
and node = [
|
and node = [
|
||||||
| #SymbolicDist(SymbolicTypes.symbolicDist)
|
| #SymbolicDist(SymbolicDistTypes.symbolicDist)
|
||||||
| #RenderedDist(DistTypes.shape)
|
| #RenderedDist(PointSetTypes.pointSetDist)
|
||||||
| #Symbol(string)
|
| #Symbol(string)
|
||||||
| #Hash(hash)
|
| #Hash(hash)
|
||||||
| #Array(array<node>)
|
| #Array(array<node>)
|
||||||
|
@ -64,7 +64,7 @@ module ExpressionTree = {
|
||||||
sampleCount: int,
|
sampleCount: int,
|
||||||
outputXYPoints: int,
|
outputXYPoints: int,
|
||||||
kernelWidth: option<float>,
|
kernelWidth: option<float>,
|
||||||
shapeLength: int,
|
pointSetDistLength: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
module SamplingInputs = {
|
module SamplingInputs = {
|
||||||
|
@ -72,13 +72,13 @@ module ExpressionTree = {
|
||||||
sampleCount: option<int>,
|
sampleCount: option<int>,
|
||||||
outputXYPoints: option<int>,
|
outputXYPoints: option<int>,
|
||||||
kernelWidth: option<float>,
|
kernelWidth: option<float>,
|
||||||
shapeLength: option<int>,
|
pointSetDistLength: option<int>,
|
||||||
}
|
}
|
||||||
let withDefaults = (t: t): samplingInputs => {
|
let withDefaults = (t: t): samplingInputs => {
|
||||||
sampleCount: t.sampleCount |> E.O.default(10000),
|
sampleCount: t.sampleCount |> E.O.default(10000),
|
||||||
outputXYPoints: t.outputXYPoints |> E.O.default(10000),
|
outputXYPoints: t.outputXYPoints |> E.O.default(10000),
|
||||||
kernelWidth: t.kernelWidth,
|
kernelWidth: t.kernelWidth,
|
||||||
shapeLength: t.shapeLength |> E.O.default(10000),
|
pointSetDistLength: t.pointSetDistLength |> E.O.default(10000),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ module ExpressionTree = {
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
let _toFloat = (t: DistTypes.shape) =>
|
let _toFloat = (t: PointSetTypes.pointSetDist) =>
|
||||||
switch t {
|
switch t {
|
||||||
| Discrete({xyShape: {xs: [x], ys: [1.0]}}) => Some(#SymbolicDist(#Float(x)))
|
| Discrete({xyShape: {xs: [x], ys: [1.0]}}) => Some(#SymbolicDist(#Float(x)))
|
||||||
| _ => None
|
| _ => None
|
||||||
|
@ -160,15 +160,15 @@ module ExpressionTree = {
|
||||||
}
|
}
|
||||||
|
|
||||||
type simplificationResult = [
|
type simplificationResult = [
|
||||||
| #Solution(ExpressionTree.node)
|
| #Solution(AST.node)
|
||||||
| #Error(string)
|
| #Error(string)
|
||||||
| #NoSolution
|
| #NoSolution
|
||||||
]
|
]
|
||||||
|
|
||||||
module Program = {
|
module Program = {
|
||||||
type statement = [
|
type statement = [
|
||||||
| #Assignment(string, ExpressionTree.node)
|
| #Assignment(string, AST.node)
|
||||||
| #Expression(ExpressionTree.node)
|
| #Expression(AST.node)
|
||||||
]
|
]
|
||||||
type program = array<statement>
|
type program = array<statement>
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
open ExpressionTypes
|
open ASTTypes
|
||||||
|
|
||||||
module Algebraic = {
|
module Algebraic = {
|
||||||
type t = algebraicOperation
|
type t = algebraicOperation
|
||||||
|
@ -103,5 +103,5 @@ module T = {
|
||||||
| #Truncate(lc, rc, t) => truncateToString(lc, rc, nodeToString(t))
|
| #Truncate(lc, rc, t) => truncateToString(lc, rc, nodeToString(t))
|
||||||
| #Render(t) => nodeToString(t)
|
| #Render(t) => nodeToString(t)
|
||||||
| _ => ""
|
| _ => ""
|
||||||
} // SymbolicDist and RenderedDist are handled in ExpressionTree.toString.
|
} // SymbolicDist and RenderedDist are handled in AST.toString.
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
open ExpressionTypes.ExpressionTree
|
open ASTTypes.AST
|
||||||
|
|
||||||
module Function = {
|
module Function = {
|
||||||
type t = (array<string>, node)
|
type t = (array<string>, node)
|
||||||
|
@ -10,7 +10,7 @@ module Function = {
|
||||||
let argumentNames = ((a, _): t) => a
|
let argumentNames = ((a, _): t) => a
|
||||||
let internals = ((_, b): t) => b
|
let internals = ((_, b): t) => b
|
||||||
let run = (
|
let run = (
|
||||||
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
|
evaluationParams: ASTTypes.AST.evaluationParams,
|
||||||
args: array<node>,
|
args: array<node>,
|
||||||
t: t,
|
t: t,
|
||||||
) =>
|
) =>
|
||||||
|
@ -19,10 +19,10 @@ module Function = {
|
||||||
Belt.Array.zip(
|
Belt.Array.zip(
|
||||||
argumentNames(t),
|
argumentNames(t),
|
||||||
args,
|
args,
|
||||||
) |> ExpressionTypes.ExpressionTree.Environment.fromArray
|
) |> ASTTypes.AST.Environment.fromArray
|
||||||
let newEvaluationParams: ExpressionTypes.ExpressionTree.evaluationParams = {
|
let newEvaluationParams: ASTTypes.AST.evaluationParams = {
|
||||||
samplingInputs: evaluationParams.samplingInputs,
|
samplingInputs: evaluationParams.samplingInputs,
|
||||||
environment: ExpressionTypes.ExpressionTree.Environment.mergeKeepSecond(
|
environment: ASTTypes.AST.Environment.mergeKeepSecond(
|
||||||
evaluationParams.environment,
|
evaluationParams.environment,
|
||||||
newEnvironment,
|
newEnvironment,
|
||||||
),
|
),
|
||||||
|
@ -36,8 +36,8 @@ module Function = {
|
||||||
|
|
||||||
module Primative = {
|
module Primative = {
|
||||||
type t = [
|
type t = [
|
||||||
| #SymbolicDist(SymbolicTypes.symbolicDist)
|
| #SymbolicDist(SymbolicDistTypes.symbolicDist)
|
||||||
| #RenderedDist(DistTypes.shape)
|
| #RenderedDist(PointSetTypes.pointSetDist)
|
||||||
| #Function(array<string>, node)
|
| #Function(array<string>, node)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ module Primative = {
|
||||||
|
|
||||||
module SamplingDistribution = {
|
module SamplingDistribution = {
|
||||||
type t = [
|
type t = [
|
||||||
| #SymbolicDist(SymbolicTypes.symbolicDist)
|
| #SymbolicDist(SymbolicDistTypes.symbolicDist)
|
||||||
| #RenderedDist(DistTypes.shape)
|
| #RenderedDist(PointSetTypes.pointSetDist)
|
||||||
]
|
]
|
||||||
|
|
||||||
let isSamplingDistribution: node => bool = x =>
|
let isSamplingDistribution: node => bool = x =>
|
||||||
|
@ -98,7 +98,7 @@ module SamplingDistribution = {
|
||||||
)
|
)
|
||||||
|
|
||||||
let sampleN = n =>
|
let sampleN = n =>
|
||||||
map(~renderedDistFn=Shape.sampleNRendered(n), ~symbolicDistFn=SymbolicDist.T.sampleN(n))
|
map(~renderedDistFn=PointSetDist.sampleNRendered(n), ~symbolicDistFn=SymbolicDist.T.sampleN(n))
|
||||||
|
|
||||||
let getCombinationSamples = (n, algebraicOp, t1: node, t2: node) =>
|
let getCombinationSamples = (n, algebraicOp, t1: node, t2: node) =>
|
||||||
switch (sampleN(n, t1), sampleN(n, t2)) {
|
switch (sampleN(n, t1), sampleN(n, t2)) {
|
||||||
|
@ -126,12 +126,13 @@ module SamplingDistribution = {
|
||||||
)
|
)
|
||||||
|
|
||||||
// todo: This bottom part should probably be somewhere else.
|
// todo: This bottom part should probably be somewhere else.
|
||||||
let shape =
|
// todo: REFACTOR: I'm not sure about the SampleSet line.
|
||||||
|
let pointSetDist =
|
||||||
samples
|
samples
|
||||||
|> E.O.fmap(SamplesToShape.fromSamples(~samplingInputs=evaluationParams.samplingInputs))
|
|> E.O.fmap(r => SampleSet.toPointSetDist(~samplingInputs=evaluationParams.samplingInputs, ~samples=r, ()))
|
||||||
|> E.O.bind(_, r => r.shape)
|
|> E.O.bind(_, r => r.pointSetDist)
|
||||||
|> E.O.toResult("No response")
|
|> E.O.toResult("No response")
|
||||||
shape |> E.R.fmap(r => #Normalize(#RenderedDist(r)))
|
pointSetDist |> E.R.fmap(r => #Normalize(#RenderedDist(r)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -84,13 +84,13 @@ let makeDist = (name, fn) =>
|
||||||
)
|
)
|
||||||
|
|
||||||
let floatFromDist = (
|
let floatFromDist = (
|
||||||
distToFloatOp: ExpressionTypes.distToFloatOperation,
|
distToFloatOp: ASTTypes.distToFloatOperation,
|
||||||
t: TypeSystem.samplingDist,
|
t: TypeSystem.samplingDist,
|
||||||
): result<node, string> =>
|
): result<node, string> =>
|
||||||
switch t {
|
switch t {
|
||||||
| #SymbolicDist(s) =>
|
| #SymbolicDist(s) =>
|
||||||
SymbolicDist.T.operate(distToFloatOp, s) |> E.R.bind(_, v => Ok(#SymbolicDist(#Float(v))))
|
SymbolicDist.T.operate(distToFloatOp, s) |> E.R.bind(_, v => Ok(#SymbolicDist(#Float(v))))
|
||||||
| #RenderedDist(rs) => Shape.operate(distToFloatOp, rs) |> (v => Ok(#SymbolicDist(#Float(v))))
|
| #RenderedDist(rs) => PointSetDist.operate(distToFloatOp, rs) |> (v => Ok(#SymbolicDist(#Float(v))))
|
||||||
}
|
}
|
||||||
|
|
||||||
let verticalScaling = (scaleOp, rs, scaleBy) => {
|
let verticalScaling = (scaleOp, rs, scaleBy) => {
|
||||||
|
@ -100,7 +100,7 @@ let verticalScaling = (scaleOp, rs, scaleBy) => {
|
||||||
let integralCacheFn = Operation.Scale.toIntegralCacheFn(scaleOp)
|
let integralCacheFn = Operation.Scale.toIntegralCacheFn(scaleOp)
|
||||||
Ok(
|
Ok(
|
||||||
#RenderedDist(
|
#RenderedDist(
|
||||||
Shape.T.mapY(
|
PointSetDist.T.mapY(
|
||||||
~integralSumCacheFn=integralSumCacheFn(scaleBy),
|
~integralSumCacheFn=integralSumCacheFn(scaleBy),
|
||||||
~integralCacheFn=integralCacheFn(scaleBy),
|
~integralCacheFn=integralCacheFn(scaleBy),
|
||||||
~fn=fn(scaleBy),
|
~fn=fn(scaleBy),
|
||||||
|
@ -111,7 +111,7 @@ let verticalScaling = (scaleOp, rs, scaleBy) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
module Multimodal = {
|
module Multimodal = {
|
||||||
let getByNameResult = ExpressionTypes.ExpressionTree.Hash.getByNameResult
|
let getByNameResult = ASTTypes.AST.Hash.getByNameResult
|
||||||
|
|
||||||
let _paramsToDistsAndWeights = (r: array<typedValue>) =>
|
let _paramsToDistsAndWeights = (r: array<typedValue>) =>
|
||||||
switch r {
|
switch r {
|
||||||
|
@ -209,7 +209,7 @@ let all = [
|
||||||
~run=x =>
|
~run=x =>
|
||||||
switch x {
|
switch x {
|
||||||
| [#SamplingDist(#SymbolicDist(c))] => Ok(#SymbolicDist(c))
|
| [#SamplingDist(#SymbolicDist(c))] => Ok(#SymbolicDist(c))
|
||||||
| [#SamplingDist(#RenderedDist(c))] => Ok(#RenderedDist(Shape.T.normalize(c)))
|
| [#SamplingDist(#RenderedDist(c))] => Ok(#RenderedDist(PointSetDist.T.normalize(c)))
|
||||||
| e => wrongInputsError(e)
|
| e => wrongInputsError(e)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
|
@ -1,9 +1,9 @@
|
||||||
type node = ExpressionTypes.ExpressionTree.node
|
type node = ASTTypes.AST.node
|
||||||
let getFloat = ExpressionTypes.ExpressionTree.getFloat
|
let getFloat = ASTTypes.AST.getFloat
|
||||||
|
|
||||||
type samplingDist = [
|
type samplingDist = [
|
||||||
| #SymbolicDist(SymbolicTypes.symbolicDist)
|
| #SymbolicDist(SymbolicDistTypes.symbolicDist)
|
||||||
| #RenderedDist(DistTypes.shape)
|
| #RenderedDist(PointSetTypes.pointSetDist)
|
||||||
]
|
]
|
||||||
|
|
||||||
type rec hashType = array<(string, _type)>
|
type rec hashType = array<(string, _type)>
|
||||||
|
@ -18,7 +18,7 @@ and _type = [
|
||||||
type rec hashTypedValue = array<(string, typedValue)>
|
type rec hashTypedValue = array<(string, typedValue)>
|
||||||
and typedValue = [
|
and typedValue = [
|
||||||
| #Float(float)
|
| #Float(float)
|
||||||
| #RenderedDist(DistTypes.shape)
|
| #RenderedDist(PointSetTypes.pointSetDist)
|
||||||
| #SamplingDist(samplingDist)
|
| #SamplingDist(samplingDist)
|
||||||
| #Array(array<typedValue>)
|
| #Array(array<typedValue>)
|
||||||
| #Hash(hashTypedValue)
|
| #Hash(hashTypedValue)
|
||||||
|
@ -39,7 +39,7 @@ module TypedValue = {
|
||||||
let rec toString: typedValue => string = x =>
|
let rec toString: typedValue => string = x =>
|
||||||
switch x {
|
switch x {
|
||||||
| #SamplingDist(_) => "[sampling dist]"
|
| #SamplingDist(_) => "[sampling dist]"
|
||||||
| #RenderedDist(_) => "[rendered Shape]"
|
| #RenderedDist(_) => "[rendered PointSetDist]"
|
||||||
| #Float(f) => "Float: " ++ Js.Float.toString(f)
|
| #Float(f) => "Float: " ++ Js.Float.toString(f)
|
||||||
| #Array(a) => "[" ++ ((a |> E.A.fmap(toString) |> Js.String.concatMany(_, ",")) ++ "]")
|
| #Array(a) => "[" ++ ((a |> E.A.fmap(toString) |> Js.String.concatMany(_, ",")) ++ "]")
|
||||||
| #Hash(v) =>
|
| #Hash(v) =>
|
||||||
|
@ -61,7 +61,7 @@ module TypedValue = {
|
||||||
|> E.A.fmap(((name, t)) => fromNode(t) |> E.R.fmap(r => (name, r)))
|
|> E.A.fmap(((name, t)) => fromNode(t) |> E.R.fmap(r => (name, r)))
|
||||||
|> E.A.R.firstErrorOrOpen
|
|> E.A.R.firstErrorOrOpen
|
||||||
|> E.R.fmap(r => #Hash(r))
|
|> E.R.fmap(r => #Hash(r))
|
||||||
| e => Error("Wrong type: " ++ ExpressionTreeBasic.toString(e))
|
| e => Error("Wrong type: " ++ ASTBasic.toString(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Arrays and hashes
|
// todo: Arrays and hashes
|
||||||
|
@ -78,7 +78,7 @@ module TypedValue = {
|
||||||
node,
|
node,
|
||||||
) |> E.R.bind(_, fromNode)
|
) |> E.R.bind(_, fromNode)
|
||||||
| (#RenderedDistribution, _) =>
|
| (#RenderedDistribution, _) =>
|
||||||
ExpressionTypes.ExpressionTree.Render.render(evaluationParams, node) |> E.R.bind(_, fromNode)
|
ASTTypes.AST.Render.render(evaluationParams, node) |> E.R.bind(_, fromNode)
|
||||||
| (#Array(_type), #Array(b)) =>
|
| (#Array(_type), #Array(b)) =>
|
||||||
b
|
b
|
||||||
|> E.A.fmap(fromNodeWithTypeCoercion(evaluationParams, _type))
|
|> E.A.fmap(fromNodeWithTypeCoercion(evaluationParams, _type))
|
||||||
|
@ -89,7 +89,7 @@ module TypedValue = {
|
||||||
named |> E.A.fmap(((name, intendedType)) => (
|
named |> E.A.fmap(((name, intendedType)) => (
|
||||||
name,
|
name,
|
||||||
intendedType,
|
intendedType,
|
||||||
ExpressionTypes.ExpressionTree.Hash.getByName(r, name),
|
ASTTypes.AST.Hash.getByName(r, name),
|
||||||
))
|
))
|
||||||
let typedHash =
|
let typedHash =
|
||||||
keyValues
|
keyValues
|
||||||
|
@ -172,7 +172,7 @@ module Function = {
|
||||||
|> E.A.R.firstErrorOrOpen
|
|> E.A.R.firstErrorOrOpen
|
||||||
|
|
||||||
let inputsToTypedValues = (
|
let inputsToTypedValues = (
|
||||||
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
|
evaluationParams: ASTTypes.AST.evaluationParams,
|
||||||
inputNodes: inputNodes,
|
inputNodes: inputNodes,
|
||||||
t: t,
|
t: t,
|
||||||
) =>
|
) =>
|
||||||
|
@ -181,7 +181,7 @@ module Function = {
|
||||||
)
|
)
|
||||||
|
|
||||||
let run = (
|
let run = (
|
||||||
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
|
evaluationParams: ASTTypes.AST.evaluationParams,
|
||||||
inputNodes: inputNodes,
|
inputNodes: inputNodes,
|
||||||
t: t,
|
t: t,
|
||||||
) =>
|
) =>
|
|
@ -122,7 +122,7 @@ module MathAdtToDistDst = {
|
||||||
| _ => Error("Lognormal distribution needs either mean and stdev or mu and sigma")
|
| _ => Error("Lognormal distribution needs either mean and stdev or mu and sigma")
|
||||||
}
|
}
|
||||||
| _ =>
|
| _ =>
|
||||||
parseArgs() |> E.R.fmap((args: array<ExpressionTypes.ExpressionTree.node>) =>
|
parseArgs() |> E.R.fmap((args: array<ASTTypes.AST.node>) =>
|
||||||
#FunctionCall("lognormal", args)
|
#FunctionCall("lognormal", args)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -130,8 +130,8 @@ module MathAdtToDistDst = {
|
||||||
// Error("Dotwise exponentiation needs two operands")
|
// Error("Dotwise exponentiation needs two operands")
|
||||||
let operationParser = (
|
let operationParser = (
|
||||||
name: string,
|
name: string,
|
||||||
args: result<array<ExpressionTypes.ExpressionTree.node>, string>,
|
args: result<array<ASTTypes.AST.node>, string>,
|
||||||
): result<ExpressionTypes.ExpressionTree.node, string> => {
|
): result<ASTTypes.AST.node, string> => {
|
||||||
let toOkAlgebraic = r => Ok(#AlgebraicCombination(r))
|
let toOkAlgebraic = r => Ok(#AlgebraicCombination(r))
|
||||||
let toOkPointwise = r => Ok(#PointwiseCombination(r))
|
let toOkPointwise = r => Ok(#PointwiseCombination(r))
|
||||||
let toOkTruncate = r => Ok(#Truncate(r))
|
let toOkTruncate = r => Ok(#Truncate(r))
|
||||||
|
@ -170,12 +170,12 @@ module MathAdtToDistDst = {
|
||||||
|
|
||||||
let functionParser = (
|
let functionParser = (
|
||||||
nodeParser: MathJsonToMathJsAdt.arg => Belt.Result.t<
|
nodeParser: MathJsonToMathJsAdt.arg => Belt.Result.t<
|
||||||
ExpressionTypes.ExpressionTree.node,
|
ASTTypes.AST.node,
|
||||||
string,
|
string,
|
||||||
>,
|
>,
|
||||||
name: string,
|
name: string,
|
||||||
args: array<MathJsonToMathJsAdt.arg>,
|
args: array<MathJsonToMathJsAdt.arg>,
|
||||||
): result<ExpressionTypes.ExpressionTree.node, string> => {
|
): result<ASTTypes.AST.node, string> => {
|
||||||
let parseArray = ags => ags |> E.A.fmap(nodeParser) |> E.A.R.firstErrorOrOpen
|
let parseArray = ags => ags |> E.A.fmap(nodeParser) |> E.A.R.firstErrorOrOpen
|
||||||
let parseArgs = () => parseArray(args)
|
let parseArgs = () => parseArray(args)
|
||||||
switch name {
|
switch name {
|
||||||
|
@ -212,27 +212,27 @@ module MathAdtToDistDst = {
|
||||||
| (Some(Error(r)), _) => Error(r)
|
| (Some(Error(r)), _) => Error(r)
|
||||||
| (_, Error(r)) => Error(r)
|
| (_, Error(r)) => Error(r)
|
||||||
| (None, Ok(dists)) =>
|
| (None, Ok(dists)) =>
|
||||||
let hash: ExpressionTypes.ExpressionTree.node = #FunctionCall(
|
let hash: ASTTypes.AST.node = #FunctionCall(
|
||||||
"multimodal",
|
"multimodal",
|
||||||
[#Hash([("dists", #Array(dists)), ("weights", #Array([]))])],
|
[#Hash([("dists", #Array(dists)), ("weights", #Array([]))])],
|
||||||
)
|
)
|
||||||
Ok(hash)
|
Ok(hash)
|
||||||
| (Some(Ok(weights)), Ok(dists)) =>
|
| (Some(Ok(weights)), Ok(dists)) =>
|
||||||
let hash: ExpressionTypes.ExpressionTree.node = #FunctionCall(
|
let hash: ASTTypes.AST.node = #FunctionCall(
|
||||||
"multimodal",
|
"multimodal",
|
||||||
[#Hash([("dists", #Array(dists)), ("weights", #Array(weights))])],
|
[#Hash([("dists", #Array(dists)), ("weights", #Array(weights))])],
|
||||||
)
|
)
|
||||||
Ok(hash)
|
Ok(hash)
|
||||||
}
|
}
|
||||||
| name =>
|
| name =>
|
||||||
parseArgs() |> E.R.fmap((args: array<ExpressionTypes.ExpressionTree.node>) =>
|
parseArgs() |> E.R.fmap((args: array<ASTTypes.AST.node>) =>
|
||||||
#FunctionCall(name, args)
|
#FunctionCall(name, args)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let rec nodeParser: MathJsonToMathJsAdt.arg => result<
|
let rec nodeParser: MathJsonToMathJsAdt.arg => result<
|
||||||
ExpressionTypes.ExpressionTree.node,
|
ASTTypes.AST.node,
|
||||||
string,
|
string,
|
||||||
> = x =>
|
> = x =>
|
||||||
switch x {
|
switch x {
|
||||||
|
@ -246,7 +246,7 @@ module MathAdtToDistDst = {
|
||||||
// let evaluatedExpression = run(expression);
|
// let evaluatedExpression = run(expression);
|
||||||
// `Function(_ => Ok(evaluatedExpression));
|
// `Function(_ => Ok(evaluatedExpression));
|
||||||
// }
|
// }
|
||||||
let rec topLevel = (r): result<ExpressionTypes.Program.program, string> =>
|
let rec topLevel = (r): result<ASTTypes.Program.program, string> =>
|
||||||
switch r {
|
switch r {
|
||||||
| FunctionAssignment({name, args, expression}) =>
|
| FunctionAssignment({name, args, expression}) =>
|
||||||
switch nodeParser(expression) {
|
switch nodeParser(expression) {
|
||||||
|
@ -267,7 +267,7 @@ module MathAdtToDistDst = {
|
||||||
blocks |> E.A.fmap(b => topLevel(b)) |> E.A.R.firstErrorOrOpen |> E.R.fmap(E.A.concatMany)
|
blocks |> E.A.fmap(b => topLevel(b)) |> E.A.R.firstErrorOrOpen |> E.R.fmap(E.A.concatMany)
|
||||||
}
|
}
|
||||||
|
|
||||||
let run = (r): result<ExpressionTypes.Program.program, string> =>
|
let run = (r): result<ASTTypes.Program.program, string> =>
|
||||||
r |> MathAdtCleaner.run |> topLevel
|
r |> MathAdtCleaner.run |> topLevel
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,10 +96,10 @@ let toDiscretePointMassesFromTriangulars = (
|
||||||
}
|
}
|
||||||
|
|
||||||
let combineShapesContinuousContinuous = (
|
let combineShapesContinuousContinuous = (
|
||||||
op: ExpressionTypes.algebraicOperation,
|
op: ASTTypes.algebraicOperation,
|
||||||
s1: DistTypes.xyShape,
|
s1: PointSetTypes.xyShape,
|
||||||
s2: DistTypes.xyShape,
|
s2: PointSetTypes.xyShape,
|
||||||
): DistTypes.xyShape => {
|
): PointSetTypes.xyShape => {
|
||||||
let t1n = s1 |> XYShape.T.length
|
let t1n = s1 |> XYShape.T.length
|
||||||
let t2n = s2 |> XYShape.T.length
|
let t2n = s2 |> XYShape.T.length
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ let combineShapesContinuousContinuous = (
|
||||||
{xs: outputXs, ys: outputYs}
|
{xs: outputXs, ys: outputYs}
|
||||||
}
|
}
|
||||||
|
|
||||||
let toDiscretePointMassesFromDiscrete = (s: DistTypes.xyShape): pointMassesWithMoments => {
|
let toDiscretePointMassesFromDiscrete = (s: PointSetTypes.xyShape): pointMassesWithMoments => {
|
||||||
let {xs, ys}: XYShape.T.t = s
|
let {xs, ys}: XYShape.T.t = s
|
||||||
let n = E.A.length(xs)
|
let n = E.A.length(xs)
|
||||||
|
|
||||||
|
@ -200,10 +200,10 @@ let toDiscretePointMassesFromDiscrete = (s: DistTypes.xyShape): pointMassesWithM
|
||||||
}
|
}
|
||||||
|
|
||||||
let combineShapesContinuousDiscrete = (
|
let combineShapesContinuousDiscrete = (
|
||||||
op: ExpressionTypes.algebraicOperation,
|
op: ASTTypes.algebraicOperation,
|
||||||
continuousShape: DistTypes.xyShape,
|
continuousShape: PointSetTypes.xyShape,
|
||||||
discreteShape: DistTypes.xyShape,
|
discreteShape: PointSetTypes.xyShape,
|
||||||
): DistTypes.xyShape => {
|
): PointSetTypes.xyShape => {
|
||||||
let t1n = continuousShape |> XYShape.T.length
|
let t1n = continuousShape |> XYShape.T.length
|
||||||
let t2n = discreteShape |> XYShape.T.length
|
let t2n = discreteShape |> XYShape.T.length
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = DistTypes.continuousShape
|
type t = PointSetTypes.continuousShape
|
||||||
let getShape = (t: t) => t.xyShape
|
let getShape = (t: t) => t.xyShape
|
||||||
let interpolation = (t: t) => t.interpolation
|
let interpolation = (t: t) => t.interpolation
|
||||||
let make = (~interpolation=#Linear, ~integralSumCache=None, ~integralCache=None, xyShape): t => {
|
let make = (~interpolation=#Linear, ~integralSumCache=None, ~integralCache=None, xyShape): t => {
|
||||||
|
@ -17,10 +17,10 @@ let shapeMap = (fn, {xyShape, interpolation, integralSumCache, integralCache}: t
|
||||||
}
|
}
|
||||||
let lastY = (t: t) => t |> getShape |> XYShape.T.lastY
|
let lastY = (t: t) => t |> getShape |> XYShape.T.lastY
|
||||||
let oShapeMap = (fn, {xyShape, interpolation, integralSumCache, integralCache}: t): option<
|
let oShapeMap = (fn, {xyShape, interpolation, integralSumCache, integralCache}: t): option<
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
> => fn(xyShape) |> E.O.fmap(make(~interpolation, ~integralSumCache, ~integralCache))
|
> => fn(xyShape) |> E.O.fmap(make(~interpolation, ~integralSumCache, ~integralCache))
|
||||||
|
|
||||||
let emptyIntegral: DistTypes.continuousShape = {
|
let emptyIntegral: PointSetTypes.continuousShape = {
|
||||||
xyShape: {
|
xyShape: {
|
||||||
xs: [neg_infinity],
|
xs: [neg_infinity],
|
||||||
ys: [0.0],
|
ys: [0.0],
|
||||||
|
@ -29,7 +29,7 @@ let emptyIntegral: DistTypes.continuousShape = {
|
||||||
integralSumCache: Some(0.0),
|
integralSumCache: Some(0.0),
|
||||||
integralCache: None,
|
integralCache: None,
|
||||||
}
|
}
|
||||||
let empty: DistTypes.continuousShape = {
|
let empty: PointSetTypes.continuousShape = {
|
||||||
xyShape: XYShape.T.empty,
|
xyShape: XYShape.T.empty,
|
||||||
interpolation: #Linear,
|
interpolation: #Linear,
|
||||||
integralSumCache: Some(0.0),
|
integralSumCache: Some(0.0),
|
||||||
|
@ -47,11 +47,11 @@ let stepwiseToLinear = (t: t): t =>
|
||||||
let combinePointwise = (
|
let combinePointwise = (
|
||||||
~integralSumCachesFn=(_, _) => None,
|
~integralSumCachesFn=(_, _) => None,
|
||||||
~integralCachesFn: (t, t) => option<t>=(_, _) => None,
|
~integralCachesFn: (t, t) => option<t>=(_, _) => None,
|
||||||
~distributionType: DistTypes.distributionType=#PDF,
|
~distributionType: PointSetTypes.distributionType=#PDF,
|
||||||
fn: (float, float) => float,
|
fn: (float, float) => float,
|
||||||
t1: DistTypes.continuousShape,
|
t1: PointSetTypes.continuousShape,
|
||||||
t2: DistTypes.continuousShape,
|
t2: PointSetTypes.continuousShape,
|
||||||
): DistTypes.continuousShape => {
|
): PointSetTypes.continuousShape => {
|
||||||
// If we're adding the distributions, and we know the total of each, then we
|
// If we're adding the distributions, and we know the total of each, then we
|
||||||
// can just sum them up. Otherwise, all bets are off.
|
// can just sum them up. Otherwise, all bets are off.
|
||||||
let combinedIntegralSum = Common.combineIntegralSums(
|
let combinedIntegralSum = Common.combineIntegralSums(
|
||||||
|
@ -130,19 +130,19 @@ let rec scaleBy = (~scale=1.0, t: t): t => {
|
||||||
}
|
}
|
||||||
|
|
||||||
module T = Dist({
|
module T = Dist({
|
||||||
type t = DistTypes.continuousShape
|
type t = PointSetTypes.continuousShape
|
||||||
type integral = DistTypes.continuousShape
|
type integral = PointSetTypes.continuousShape
|
||||||
let minX = shapeFn(XYShape.T.minX)
|
let minX = shapeFn(XYShape.T.minX)
|
||||||
let maxX = shapeFn(XYShape.T.maxX)
|
let maxX = shapeFn(XYShape.T.maxX)
|
||||||
let mapY = mapY
|
let mapY = mapY
|
||||||
let updateIntegralCache = updateIntegralCache
|
let updateIntegralCache = updateIntegralCache
|
||||||
let toDiscreteProbabilityMassFraction = _ => 0.0
|
let toDiscreteProbabilityMassFraction = _ => 0.0
|
||||||
let toShape = (t: t): DistTypes.shape => Continuous(t)
|
let toPointSetDist = (t: t): PointSetTypes.pointSetDist => Continuous(t)
|
||||||
let xToY = (f, {interpolation, xyShape}: t) =>
|
let xToY = (f, {interpolation, xyShape}: t) =>
|
||||||
switch interpolation {
|
switch interpolation {
|
||||||
| #Stepwise => xyShape |> XYShape.XtoY.stepwiseIncremental(f) |> E.O.default(0.0)
|
| #Stepwise => xyShape |> XYShape.XtoY.stepwiseIncremental(f) |> E.O.default(0.0)
|
||||||
| #Linear => xyShape |> XYShape.XtoY.linear(f)
|
| #Linear => xyShape |> XYShape.XtoY.linear(f)
|
||||||
} |> DistTypes.MixedPoint.makeContinuous
|
} |> PointSetTypes.MixedPoint.makeContinuous
|
||||||
|
|
||||||
let truncate = (leftCutoff: option<float>, rightCutoff: option<float>, t: t) => {
|
let truncate = (leftCutoff: option<float>, rightCutoff: option<float>, t: t) => {
|
||||||
let lc = E.O.default(neg_infinity, leftCutoff)
|
let lc = E.O.default(neg_infinity, leftCutoff)
|
||||||
|
@ -211,9 +211,9 @@ module T = Dist({
|
||||||
/* This simply creates multiple copies of the continuous distribution, scaled and shifted according to
|
/* This simply creates multiple copies of the continuous distribution, scaled and shifted according to
|
||||||
each discrete data point, and then adds them all together. */
|
each discrete data point, and then adds them all together. */
|
||||||
let combineAlgebraicallyWithDiscrete = (
|
let combineAlgebraicallyWithDiscrete = (
|
||||||
op: ExpressionTypes.algebraicOperation,
|
op: ASTTypes.algebraicOperation,
|
||||||
t1: t,
|
t1: t,
|
||||||
t2: DistTypes.discreteShape,
|
t2: PointSetTypes.discreteShape,
|
||||||
) => {
|
) => {
|
||||||
let t1s = t1 |> getShape
|
let t1s = t1 |> getShape
|
||||||
let t2s = t2.xyShape // TODO would like to use Discrete.getShape here, but current file structure doesn't allow for that
|
let t2s = t2.xyShape // TODO would like to use Discrete.getShape here, but current file structure doesn't allow for that
|
||||||
|
@ -244,7 +244,7 @@ let combineAlgebraicallyWithDiscrete = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let combineAlgebraically = (op: ExpressionTypes.algebraicOperation, t1: t, t2: t) => {
|
let combineAlgebraically = (op: ASTTypes.algebraicOperation, t1: t, t2: t) => {
|
||||||
let s1 = t1 |> getShape
|
let s1 = t1 |> getShape
|
||||||
let s2 = t2 |> getShape
|
let s2 = t2 |> getShape
|
||||||
let t1n = s1 |> XYShape.T.length
|
let t1n = s1 |> XYShape.T.length
|
|
@ -1,6 +1,6 @@
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = DistTypes.discreteShape
|
type t = PointSetTypes.discreteShape
|
||||||
|
|
||||||
let make = (~integralSumCache=None, ~integralCache=None, xyShape): t => {
|
let make = (~integralSumCache=None, ~integralCache=None, xyShape): t => {
|
||||||
xyShape: xyShape,
|
xyShape: xyShape,
|
||||||
|
@ -16,13 +16,13 @@ let getShape = (t: t) => t.xyShape
|
||||||
let oShapeMap = (fn, {xyShape, integralSumCache, integralCache}: t): option<t> =>
|
let oShapeMap = (fn, {xyShape, integralSumCache, integralCache}: t): option<t> =>
|
||||||
fn(xyShape) |> E.O.fmap(make(~integralSumCache, ~integralCache))
|
fn(xyShape) |> E.O.fmap(make(~integralSumCache, ~integralCache))
|
||||||
|
|
||||||
let emptyIntegral: DistTypes.continuousShape = {
|
let emptyIntegral: PointSetTypes.continuousShape = {
|
||||||
xyShape: {xs: [neg_infinity], ys: [0.0]},
|
xyShape: {xs: [neg_infinity], ys: [0.0]},
|
||||||
interpolation: #Stepwise,
|
interpolation: #Stepwise,
|
||||||
integralSumCache: Some(0.0),
|
integralSumCache: Some(0.0),
|
||||||
integralCache: None,
|
integralCache: None,
|
||||||
}
|
}
|
||||||
let empty: DistTypes.discreteShape = {
|
let empty: PointSetTypes.discreteShape = {
|
||||||
xyShape: XYShape.T.empty,
|
xyShape: XYShape.T.empty,
|
||||||
integralSumCache: Some(0.0),
|
integralSumCache: Some(0.0),
|
||||||
integralCache: Some(emptyIntegral),
|
integralCache: Some(emptyIntegral),
|
||||||
|
@ -35,13 +35,13 @@ let lastY = (t: t) => t |> getShape |> XYShape.T.lastY
|
||||||
let combinePointwise = (
|
let combinePointwise = (
|
||||||
~integralSumCachesFn=(_, _) => None,
|
~integralSumCachesFn=(_, _) => None,
|
||||||
~integralCachesFn: (
|
~integralCachesFn: (
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
) => option<DistTypes.continuousShape>=(_, _) => None,
|
) => option<PointSetTypes.continuousShape>=(_, _) => None,
|
||||||
fn,
|
fn,
|
||||||
t1: DistTypes.discreteShape,
|
t1: PointSetTypes.discreteShape,
|
||||||
t2: DistTypes.discreteShape,
|
t2: PointSetTypes.discreteShape,
|
||||||
): DistTypes.discreteShape => {
|
): PointSetTypes.discreteShape => {
|
||||||
let combinedIntegralSum = Common.combineIntegralSums(
|
let combinedIntegralSum = Common.combineIntegralSums(
|
||||||
integralSumCachesFn,
|
integralSumCachesFn,
|
||||||
t1.integralSumCache,
|
t1.integralSumCache,
|
||||||
|
@ -67,7 +67,7 @@ let reduce = (
|
||||||
~integralCachesFn=(_, _) => None,
|
~integralCachesFn=(_, _) => None,
|
||||||
fn,
|
fn,
|
||||||
discreteShapes,
|
discreteShapes,
|
||||||
): DistTypes.discreteShape =>
|
): PointSetTypes.discreteShape =>
|
||||||
discreteShapes |> E.A.fold_left(
|
discreteShapes |> E.A.fold_left(
|
||||||
combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn),
|
combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn),
|
||||||
empty,
|
empty,
|
||||||
|
@ -85,7 +85,7 @@ let updateIntegralCache = (integralCache, t: t): t => {
|
||||||
|
|
||||||
/* This multiples all of the data points together and creates a new discrete distribution from the results.
|
/* This multiples all of the data points together and creates a new discrete distribution from the results.
|
||||||
Data points at the same xs get added together. It may be a good idea to downsample t1 and t2 before and/or the result after. */
|
Data points at the same xs get added together. It may be a good idea to downsample t1 and t2 before and/or the result after. */
|
||||||
let combineAlgebraically = (op: ExpressionTypes.algebraicOperation, t1: t, t2: t): t => {
|
let combineAlgebraically = (op: ASTTypes.algebraicOperation, t1: t, t2: t): t => {
|
||||||
let t1s = t1 |> getShape
|
let t1s = t1 |> getShape
|
||||||
let t2s = t2 |> getShape
|
let t2s = t2 |> getShape
|
||||||
let t1n = t1s |> XYShape.T.length
|
let t1n = t1s |> XYShape.T.length
|
||||||
|
@ -134,8 +134,8 @@ let scaleBy = (~scale=1.0, t: t): t => {
|
||||||
}
|
}
|
||||||
|
|
||||||
module T = Dist({
|
module T = Dist({
|
||||||
type t = DistTypes.discreteShape
|
type t = PointSetTypes.discreteShape
|
||||||
type integral = DistTypes.continuousShape
|
type integral = PointSetTypes.continuousShape
|
||||||
let integral = t =>
|
let integral = t =>
|
||||||
switch (getShape(t) |> XYShape.T.isEmpty, t.integralCache) {
|
switch (getShape(t) |> XYShape.T.isEmpty, t.integralCache) {
|
||||||
| (true, _) => emptyIntegral
|
| (true, _) => emptyIntegral
|
||||||
|
@ -157,7 +157,7 @@ module T = Dist({
|
||||||
let toDiscreteProbabilityMassFraction = _ => 1.0
|
let toDiscreteProbabilityMassFraction = _ => 1.0
|
||||||
let mapY = mapY
|
let mapY = mapY
|
||||||
let updateIntegralCache = updateIntegralCache
|
let updateIntegralCache = updateIntegralCache
|
||||||
let toShape = (t: t): DistTypes.shape => Discrete(t)
|
let toPointSetDist = (t: t): PointSetTypes.pointSetDist => Discrete(t)
|
||||||
let toContinuous = _ => None
|
let toContinuous = _ => None
|
||||||
let toDiscrete = t => Some(t)
|
let toDiscrete = t => Some(t)
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ module T = Dist({
|
||||||
|> getShape
|
|> getShape
|
||||||
|> XYShape.XtoY.stepwiseIfAtX(f)
|
|> XYShape.XtoY.stepwiseIfAtX(f)
|
||||||
|> E.O.default(0.0)
|
|> E.O.default(0.0)
|
||||||
|> DistTypes.MixedPoint.makeDiscrete
|
|> PointSetTypes.MixedPoint.makeDiscrete
|
||||||
|
|
||||||
let integralXtoY = (f, t) => t |> integral |> Continuous.getShape |> XYShape.XtoY.linear(f)
|
let integralXtoY = (f, t) => t |> integral |> Continuous.getShape |> XYShape.XtoY.linear(f)
|
||||||
|
|
|
@ -1,40 +1,40 @@
|
||||||
open DistTypes;
|
open PointSetTypes;
|
||||||
|
|
||||||
type t = DistTypes.distPlus;
|
type t = PointSetTypes.distPlus;
|
||||||
|
|
||||||
let shapeIntegral = shape => Shape.T.Integral.get(shape);
|
let pointSetDistIntegral = pointSetDist => PointSetDist.T.Integral.get(pointSetDist);
|
||||||
let make =
|
let make =
|
||||||
(
|
(
|
||||||
~shape,
|
~pointSetDist,
|
||||||
~squiggleString,
|
~squiggleString,
|
||||||
~domain=Complete,
|
~domain=Complete,
|
||||||
~unit=UnspecifiedDistribution,
|
~unit=UnspecifiedDistribution,
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
: t => {
|
: t => {
|
||||||
let integral = shapeIntegral(shape);
|
let integral = pointSetDistIntegral(pointSetDist);
|
||||||
{shape, domain, integralCache: integral, unit, squiggleString};
|
{pointSetDist, domain, integralCache: integral, unit, squiggleString};
|
||||||
};
|
};
|
||||||
|
|
||||||
let update =
|
let update =
|
||||||
(
|
(
|
||||||
~shape=?,
|
~pointSetDist=?,
|
||||||
~integralCache=?,
|
~integralCache=?,
|
||||||
~domain=?,
|
~domain=?,
|
||||||
~unit=?,
|
~unit=?,
|
||||||
~squiggleString=?,
|
~squiggleString=?,
|
||||||
t: t,
|
t: t,
|
||||||
) => {
|
) => {
|
||||||
shape: E.O.default(t.shape, shape),
|
pointSetDist: E.O.default(t.pointSetDist, pointSetDist),
|
||||||
integralCache: E.O.default(t.integralCache, integralCache),
|
integralCache: E.O.default(t.integralCache, integralCache),
|
||||||
domain: E.O.default(t.domain, domain),
|
domain: E.O.default(t.domain, domain),
|
||||||
unit: E.O.default(t.unit, unit),
|
unit: E.O.default(t.unit, unit),
|
||||||
squiggleString: E.O.default(t.squiggleString, squiggleString),
|
squiggleString: E.O.default(t.squiggleString, squiggleString),
|
||||||
};
|
};
|
||||||
|
|
||||||
let updateShape = (shape, t) => {
|
let updateShape = (pointSetDist, t) => {
|
||||||
let integralCache = shapeIntegral(shape);
|
let integralCache = pointSetDistIntegral(pointSetDist);
|
||||||
update(~shape, ~integralCache, t);
|
update(~pointSetDist, ~integralCache, t);
|
||||||
};
|
};
|
||||||
|
|
||||||
let domainIncludedProbabilityMass = (t: t) =>
|
let domainIncludedProbabilityMass = (t: t) =>
|
||||||
|
@ -43,87 +43,87 @@ let domainIncludedProbabilityMass = (t: t) =>
|
||||||
let domainIncludedProbabilityMassAdjustment = (t: t, f) =>
|
let domainIncludedProbabilityMassAdjustment = (t: t, f) =>
|
||||||
f *. Domain.includedProbabilityMass(t.domain);
|
f *. Domain.includedProbabilityMass(t.domain);
|
||||||
|
|
||||||
let toShape = ({shape, _}: t) => shape;
|
let toPointSetDist = ({pointSetDist, _}: t) => pointSetDist;
|
||||||
|
|
||||||
let shapeFn = (fn, {shape}: t) => fn(shape);
|
let pointSetDistFn = (fn, {pointSetDist}: t) => fn(pointSetDist);
|
||||||
|
|
||||||
module T =
|
module T =
|
||||||
Distributions.Dist({
|
Distributions.Dist({
|
||||||
type t = DistTypes.distPlus;
|
type t = PointSetTypes.distPlus;
|
||||||
type integral = DistTypes.distPlus;
|
type integral = PointSetTypes.distPlus;
|
||||||
let toShape = toShape;
|
let toPointSetDist = toPointSetDist;
|
||||||
let toContinuous = shapeFn(Shape.T.toContinuous);
|
let toContinuous = pointSetDistFn(PointSetDist.T.toContinuous);
|
||||||
let toDiscrete = shapeFn(Shape.T.toDiscrete);
|
let toDiscrete = pointSetDistFn(PointSetDist.T.toDiscrete);
|
||||||
|
|
||||||
let normalize = (t: t): t => {
|
let normalize = (t: t): t => {
|
||||||
let normalizedShape = t |> toShape |> Shape.T.normalize;
|
let normalizedShape = t |> toPointSetDist |> PointSetDist.T.normalize;
|
||||||
t |> updateShape(normalizedShape);
|
t |> updateShape(normalizedShape);
|
||||||
};
|
};
|
||||||
|
|
||||||
let truncate = (leftCutoff, rightCutoff, t: t): t => {
|
let truncate = (leftCutoff, rightCutoff, t: t): t => {
|
||||||
let truncatedShape =
|
let truncatedShape =
|
||||||
t
|
t
|
||||||
|> toShape
|
|> toPointSetDist
|
||||||
|> Shape.T.truncate(leftCutoff, rightCutoff);
|
|> PointSetDist.T.truncate(leftCutoff, rightCutoff);
|
||||||
|
|
||||||
t |> updateShape(truncatedShape);
|
t |> updateShape(truncatedShape);
|
||||||
};
|
};
|
||||||
|
|
||||||
let xToY = (f, t: t) =>
|
let xToY = (f, t: t) =>
|
||||||
t
|
t
|
||||||
|> toShape
|
|> toPointSetDist
|
||||||
|> Shape.T.xToY(f)
|
|> PointSetDist.T.xToY(f)
|
||||||
|> MixedPoint.fmap(domainIncludedProbabilityMassAdjustment(t));
|
|> MixedPoint.fmap(domainIncludedProbabilityMassAdjustment(t));
|
||||||
|
|
||||||
let minX = shapeFn(Shape.T.minX);
|
let minX = pointSetDistFn(PointSetDist.T.minX);
|
||||||
let maxX = shapeFn(Shape.T.maxX);
|
let maxX = pointSetDistFn(PointSetDist.T.maxX);
|
||||||
let toDiscreteProbabilityMassFraction =
|
let toDiscreteProbabilityMassFraction =
|
||||||
shapeFn(Shape.T.toDiscreteProbabilityMassFraction);
|
pointSetDistFn(PointSetDist.T.toDiscreteProbabilityMassFraction);
|
||||||
|
|
||||||
// This bit is kind of awkward, could probably use rethinking.
|
// This bit is kind of awkward, could probably use rethinking.
|
||||||
let integral = (t: t) =>
|
let integral = (t: t) =>
|
||||||
updateShape(Continuous(t.integralCache), t);
|
updateShape(Continuous(t.integralCache), t);
|
||||||
|
|
||||||
let updateIntegralCache = (integralCache: option<DistTypes.continuousShape>, t) =>
|
let updateIntegralCache = (integralCache: option<PointSetTypes.continuousShape>, t) =>
|
||||||
update(~integralCache=E.O.default(t.integralCache, integralCache), t);
|
update(~integralCache=E.O.default(t.integralCache, integralCache), t);
|
||||||
|
|
||||||
let downsample = (i, t): t =>
|
let downsample = (i, t): t =>
|
||||||
updateShape(t |> toShape |> Shape.T.downsample(i), t);
|
updateShape(t |> toPointSetDist |> PointSetDist.T.downsample(i), t);
|
||||||
// todo: adjust for limit, maybe?
|
// todo: adjust for limit, maybe?
|
||||||
let mapY =
|
let mapY =
|
||||||
(
|
(
|
||||||
~integralSumCacheFn=previousIntegralSum => None,
|
~integralSumCacheFn=previousIntegralSum => None,
|
||||||
~integralCacheFn=previousIntegralCache => None,
|
~integralCacheFn=previousIntegralCache => None,
|
||||||
~fn,
|
~fn,
|
||||||
{shape, _} as t: t,
|
{pointSetDist, _} as t: t,
|
||||||
)
|
)
|
||||||
: t =>
|
: t =>
|
||||||
Shape.T.mapY(~integralSumCacheFn, ~fn, shape)
|
PointSetDist.T.mapY(~integralSumCacheFn, ~fn, pointSetDist)
|
||||||
|> updateShape(_, t);
|
|> updateShape(_, t);
|
||||||
|
|
||||||
// get the total of everything
|
// get the total of everything
|
||||||
let integralEndY = (t: t) => {
|
let integralEndY = (t: t) => {
|
||||||
Shape.T.Integral.sum(
|
PointSetDist.T.Integral.sum(
|
||||||
toShape(t),
|
toPointSetDist(t),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Fix this below, obviously. Adjust for limits
|
// TODO: Fix this below, obviously. Adjust for limits
|
||||||
let integralXtoY = (f, t: t) => {
|
let integralXtoY = (f, t: t) => {
|
||||||
Shape.T.Integral.xToY(
|
PointSetDist.T.Integral.xToY(
|
||||||
f,
|
f,
|
||||||
toShape(t),
|
toPointSetDist(t),
|
||||||
)
|
)
|
||||||
|> domainIncludedProbabilityMassAdjustment(t);
|
|> domainIncludedProbabilityMassAdjustment(t);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: This part is broken when there is a limit, if this is supposed to be taken into account.
|
// TODO: This part is broken when there is a limit, if this is supposed to be taken into account.
|
||||||
let integralYtoX = (f, t: t) => {
|
let integralYtoX = (f, t: t) => {
|
||||||
Shape.T.Integral.yToX(f, toShape(t));
|
PointSetDist.T.Integral.yToX(f, toPointSetDist(t));
|
||||||
};
|
};
|
||||||
|
|
||||||
let mean = (t: t) => {
|
let mean = (t: t) => {
|
||||||
Shape.T.mean(t.shape);
|
PointSetDist.T.mean(t.pointSetDist);
|
||||||
};
|
};
|
||||||
let variance = (t: t) => Shape.T.variance(t.shape);
|
let variance = (t: t) => PointSetDist.T.variance(t.pointSetDist);
|
||||||
});
|
});
|
|
@ -5,20 +5,20 @@ module type dist = {
|
||||||
let maxX: t => float
|
let maxX: t => float
|
||||||
let mapY: (
|
let mapY: (
|
||||||
~integralSumCacheFn: float => option<float>=?,
|
~integralSumCacheFn: float => option<float>=?,
|
||||||
~integralCacheFn: DistTypes.continuousShape => option<DistTypes.continuousShape>=?,
|
~integralCacheFn: PointSetTypes.continuousShape => option<PointSetTypes.continuousShape>=?,
|
||||||
~fn: float => float,
|
~fn: float => float,
|
||||||
t,
|
t,
|
||||||
) => t
|
) => t
|
||||||
let xToY: (float, t) => DistTypes.mixedPoint
|
let xToY: (float, t) => PointSetTypes.mixedPoint
|
||||||
let toShape: t => DistTypes.shape
|
let toPointSetDist: t => PointSetTypes.pointSetDist
|
||||||
let toContinuous: t => option<DistTypes.continuousShape>
|
let toContinuous: t => option<PointSetTypes.continuousShape>
|
||||||
let toDiscrete: t => option<DistTypes.discreteShape>
|
let toDiscrete: t => option<PointSetTypes.discreteShape>
|
||||||
let normalize: t => t
|
let normalize: t => t
|
||||||
let toDiscreteProbabilityMassFraction: t => float
|
let toDiscreteProbabilityMassFraction: t => float
|
||||||
let downsample: (int, t) => t
|
let downsample: (int, t) => t
|
||||||
let truncate: (option<float>, option<float>, t) => t
|
let truncate: (option<float>, option<float>, t) => t
|
||||||
|
|
||||||
let updateIntegralCache: (option<DistTypes.continuousShape>, t) => t
|
let updateIntegralCache: (option<PointSetTypes.continuousShape>, t) => t
|
||||||
|
|
||||||
let integral: t => integral
|
let integral: t => integral
|
||||||
let integralEndY: t => float
|
let integralEndY: t => float
|
||||||
|
@ -39,7 +39,7 @@ module Dist = (T: dist) => {
|
||||||
let mapY = T.mapY
|
let mapY = T.mapY
|
||||||
let xToY = T.xToY
|
let xToY = T.xToY
|
||||||
let downsample = T.downsample
|
let downsample = T.downsample
|
||||||
let toShape = T.toShape
|
let toPointSetDist = T.toPointSetDist
|
||||||
let toDiscreteProbabilityMassFraction = T.toDiscreteProbabilityMassFraction
|
let toDiscreteProbabilityMassFraction = T.toDiscreteProbabilityMassFraction
|
||||||
let toContinuous = T.toContinuous
|
let toContinuous = T.toContinuous
|
||||||
let toDiscrete = T.toDiscrete
|
let toDiscrete = T.toDiscrete
|
||||||
|
@ -74,11 +74,11 @@ module Common = {
|
||||||
|
|
||||||
let combineIntegrals = (
|
let combineIntegrals = (
|
||||||
combineFn: (
|
combineFn: (
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
) => option<DistTypes.continuousShape>,
|
) => option<PointSetTypes.continuousShape>,
|
||||||
t1IntegralCache: option<DistTypes.continuousShape>,
|
t1IntegralCache: option<PointSetTypes.continuousShape>,
|
||||||
t2IntegralCache: option<DistTypes.continuousShape>,
|
t2IntegralCache: option<PointSetTypes.continuousShape>,
|
||||||
) =>
|
) =>
|
||||||
switch (t1IntegralCache, t2IntegralCache) {
|
switch (t1IntegralCache, t2IntegralCache) {
|
||||||
| (None, _)
|
| (None, _)
|
|
@ -1,6 +1,6 @@
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = DistTypes.mixedShape
|
type t = PointSetTypes.mixedShape
|
||||||
let make = (~integralSumCache=None, ~integralCache=None, ~continuous, ~discrete): t => {
|
let make = (~integralSumCache=None, ~integralCache=None, ~continuous, ~discrete): t => {
|
||||||
continuous: continuous,
|
continuous: continuous,
|
||||||
discrete: discrete,
|
discrete: discrete,
|
||||||
|
@ -37,13 +37,13 @@ let updateIntegralCache = (integralCache, t: t): t => {
|
||||||
}
|
}
|
||||||
|
|
||||||
module T = Dist({
|
module T = Dist({
|
||||||
type t = DistTypes.mixedShape
|
type t = PointSetTypes.mixedShape
|
||||||
type integral = DistTypes.continuousShape
|
type integral = PointSetTypes.continuousShape
|
||||||
let minX = ({continuous, discrete}: t) =>
|
let minX = ({continuous, discrete}: t) =>
|
||||||
min(Continuous.T.minX(continuous), Discrete.T.minX(discrete))
|
min(Continuous.T.minX(continuous), Discrete.T.minX(discrete))
|
||||||
let maxX = ({continuous, discrete}: t) =>
|
let maxX = ({continuous, discrete}: t) =>
|
||||||
max(Continuous.T.maxX(continuous), Discrete.T.maxX(discrete))
|
max(Continuous.T.maxX(continuous), Discrete.T.maxX(discrete))
|
||||||
let toShape = (t: t): DistTypes.shape => Mixed(t)
|
let toPointSetDist = (t: t): PointSetTypes.pointSetDist => Mixed(t)
|
||||||
|
|
||||||
let updateIntegralCache = updateIntegralCache
|
let updateIntegralCache = updateIntegralCache
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ module T = Dist({
|
||||||
let {continuous, discrete}: t = normalize(t)
|
let {continuous, discrete}: t = normalize(t)
|
||||||
let c = Continuous.T.xToY(x, continuous)
|
let c = Continuous.T.xToY(x, continuous)
|
||||||
let d = Discrete.T.xToY(x, discrete)
|
let d = Discrete.T.xToY(x, discrete)
|
||||||
DistTypes.MixedPoint.add(c, d) // "add" here just combines the two values into a single MixedPoint.
|
PointSetTypes.MixedPoint.add(c, d) // "add" here just combines the two values into a single MixedPoint.
|
||||||
}
|
}
|
||||||
|
|
||||||
let toDiscreteProbabilityMassFraction = ({discrete, continuous}: t) => {
|
let toDiscreteProbabilityMassFraction = ({discrete, continuous}: t) => {
|
||||||
|
@ -170,13 +170,13 @@ module T = Dist({
|
||||||
~fn,
|
~fn,
|
||||||
t: t,
|
t: t,
|
||||||
): t => {
|
): t => {
|
||||||
let yMappedDiscrete: DistTypes.discreteShape =
|
let yMappedDiscrete: PointSetTypes.discreteShape =
|
||||||
t.discrete
|
t.discrete
|
||||||
|> Discrete.T.mapY(~fn)
|
|> Discrete.T.mapY(~fn)
|
||||||
|> Discrete.updateIntegralSumCache(E.O.bind(t.discrete.integralSumCache, integralSumCacheFn))
|
|> Discrete.updateIntegralSumCache(E.O.bind(t.discrete.integralSumCache, integralSumCacheFn))
|
||||||
|> Discrete.updateIntegralCache(E.O.bind(t.discrete.integralCache, integralCacheFn))
|
|> Discrete.updateIntegralCache(E.O.bind(t.discrete.integralCache, integralCacheFn))
|
||||||
|
|
||||||
let yMappedContinuous: DistTypes.continuousShape =
|
let yMappedContinuous: PointSetTypes.continuousShape =
|
||||||
t.continuous
|
t.continuous
|
||||||
|> Continuous.T.mapY(~fn)
|
|> Continuous.T.mapY(~fn)
|
||||||
|> Continuous.updateIntegralSumCache(
|
|> Continuous.updateIntegralSumCache(
|
||||||
|
@ -227,7 +227,7 @@ module T = Dist({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let combineAlgebraically = (op: ExpressionTypes.algebraicOperation, t1: t, t2: t): t => {
|
let combineAlgebraically = (op: ASTTypes.algebraicOperation, t1: t, t2: t): t => {
|
||||||
// Discrete convolution can cause a huge increase in the number of samples,
|
// Discrete convolution can cause a huge increase in the number of samples,
|
||||||
// so we'll first downsample.
|
// so we'll first downsample.
|
||||||
|
|
|
@ -9,9 +9,9 @@ type assumptions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let buildSimple = (
|
let buildSimple = (
|
||||||
~continuous: option<DistTypes.continuousShape>,
|
~continuous: option<PointSetTypes.continuousShape>,
|
||||||
~discrete: option<DistTypes.discreteShape>,
|
~discrete: option<PointSetTypes.discreteShape>,
|
||||||
): option<DistTypes.shape> => {
|
): option<PointSetTypes.pointSetDist> => {
|
||||||
let continuous =
|
let continuous =
|
||||||
continuous |> E.O.default(Continuous.make(~integralSumCache=Some(0.0), {xs: [], ys: []}))
|
continuous |> E.O.default(Continuous.make(~integralSumCache=Some(0.0), {xs: [], ys: []}))
|
||||||
let discrete =
|
let discrete =
|
|
@ -1,6 +1,6 @@
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = DistTypes.shape
|
type t = PointSetTypes.pointSetDist
|
||||||
let mapToAll = ((fn1, fn2, fn3), t: t) =>
|
let mapToAll = ((fn1, fn2, fn3), t: t) =>
|
||||||
switch t {
|
switch t {
|
||||||
| Mixed(m) => fn1(m)
|
| Mixed(m) => fn1(m)
|
||||||
|
@ -33,49 +33,49 @@ let toMixed = mapToAll((
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
|
||||||
let combineAlgebraically = (op: ExpressionTypes.algebraicOperation, t1: t, t2: t): t =>
|
let combineAlgebraically = (op: ASTTypes.algebraicOperation, t1: t, t2: t): t =>
|
||||||
switch (t1, t2) {
|
switch (t1, t2) {
|
||||||
| (Continuous(m1), Continuous(m2)) =>
|
| (Continuous(m1), Continuous(m2)) =>
|
||||||
Continuous.combineAlgebraically(op, m1, m2) |> Continuous.T.toShape
|
Continuous.combineAlgebraically(op, m1, m2) |> Continuous.T.toPointSetDist
|
||||||
| (Continuous(m1), Discrete(m2))
|
| (Continuous(m1), Discrete(m2))
|
||||||
| (Discrete(m2), Continuous(m1)) =>
|
| (Discrete(m2), Continuous(m1)) =>
|
||||||
Continuous.combineAlgebraicallyWithDiscrete(op, m1, m2) |> Continuous.T.toShape
|
Continuous.combineAlgebraicallyWithDiscrete(op, m1, m2) |> Continuous.T.toPointSetDist
|
||||||
| (Discrete(m1), Discrete(m2)) => Discrete.combineAlgebraically(op, m1, m2) |> Discrete.T.toShape
|
| (Discrete(m1), Discrete(m2)) => Discrete.combineAlgebraically(op, m1, m2) |> Discrete.T.toPointSetDist
|
||||||
| (m1, m2) => Mixed.combineAlgebraically(op, toMixed(m1), toMixed(m2)) |> Mixed.T.toShape
|
| (m1, m2) => Mixed.combineAlgebraically(op, toMixed(m1), toMixed(m2)) |> Mixed.T.toPointSetDist
|
||||||
}
|
}
|
||||||
|
|
||||||
let combinePointwise = (
|
let combinePointwise = (
|
||||||
~integralSumCachesFn: (float, float) => option<float>=(_, _) => None,
|
~integralSumCachesFn: (float, float) => option<float>=(_, _) => None,
|
||||||
~integralCachesFn: (
|
~integralCachesFn: (
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
DistTypes.continuousShape,
|
PointSetTypes.continuousShape,
|
||||||
) => option<DistTypes.continuousShape>=(_, _) => None,
|
) => option<PointSetTypes.continuousShape>=(_, _) => None,
|
||||||
fn,
|
fn,
|
||||||
t1: t,
|
t1: t,
|
||||||
t2: t,
|
t2: t,
|
||||||
) =>
|
) =>
|
||||||
switch (t1, t2) {
|
switch (t1, t2) {
|
||||||
| (Continuous(m1), Continuous(m2)) =>
|
| (Continuous(m1), Continuous(m2)) =>
|
||||||
DistTypes.Continuous(
|
PointSetTypes.Continuous(
|
||||||
Continuous.combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn, m1, m2),
|
Continuous.combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn, m1, m2),
|
||||||
)
|
)
|
||||||
| (Discrete(m1), Discrete(m2)) =>
|
| (Discrete(m1), Discrete(m2)) =>
|
||||||
DistTypes.Discrete(
|
PointSetTypes.Discrete(
|
||||||
Discrete.combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn, m1, m2),
|
Discrete.combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn, m1, m2),
|
||||||
)
|
)
|
||||||
| (m1, m2) =>
|
| (m1, m2) =>
|
||||||
DistTypes.Mixed(
|
PointSetTypes.Mixed(
|
||||||
Mixed.combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn, toMixed(m1), toMixed(m2)),
|
Mixed.combinePointwise(~integralSumCachesFn, ~integralCachesFn, fn, toMixed(m1), toMixed(m2)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
module T = Dist({
|
module T = Dist({
|
||||||
type t = DistTypes.shape
|
type t = PointSetTypes.pointSetDist
|
||||||
type integral = DistTypes.continuousShape
|
type integral = PointSetTypes.continuousShape
|
||||||
|
|
||||||
let xToY = (f: float) => mapToAll((Mixed.T.xToY(f), Discrete.T.xToY(f), Continuous.T.xToY(f)))
|
let xToY = (f: float) => mapToAll((Mixed.T.xToY(f), Discrete.T.xToY(f), Continuous.T.xToY(f)))
|
||||||
|
|
||||||
let toShape = (t: t) => t
|
let toPointSetDist = (t: t) => t
|
||||||
|
|
||||||
let toContinuous = t => None
|
let toContinuous = t => None
|
||||||
let toDiscrete = t => None
|
let toDiscrete = t => None
|
||||||
|
@ -163,7 +163,7 @@ module T = Dist({
|
||||||
})
|
})
|
||||||
|
|
||||||
let pdf = (f: float, t: t) => {
|
let pdf = (f: float, t: t) => {
|
||||||
let mixedPoint: DistTypes.mixedPoint = T.xToY(f, t)
|
let mixedPoint: PointSetTypes.mixedPoint = T.xToY(f, t)
|
||||||
mixedPoint.continuous +. mixedPoint.discrete
|
mixedPoint.continuous +. mixedPoint.discrete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ let sampleNRendered = (n, dist) => {
|
||||||
doN(n, () => sample(distWithUpdatedIntegralCache))
|
doN(n, () => sample(distWithUpdatedIntegralCache))
|
||||||
}
|
}
|
||||||
|
|
||||||
let operate = (distToFloatOp: ExpressionTypes.distToFloatOperation, s): float =>
|
let operate = (distToFloatOp: ASTTypes.distToFloatOperation, s): float =>
|
||||||
switch distToFloatOp {
|
switch distToFloatOp {
|
||||||
| #Pdf(f) => pdf(f, s)
|
| #Pdf(f) => pdf(f, s)
|
||||||
| #Cdf(f) => pdf(f, s)
|
| #Cdf(f) => pdf(f, s)
|
|
@ -50,15 +50,15 @@ type mixedShape = {
|
||||||
integralCache: option<continuousShape>,
|
integralCache: option<continuousShape>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type shapeMonad<'a, 'b, 'c> =
|
type pointSetDistMonad<'a, 'b, 'c> =
|
||||||
| Mixed('a)
|
| Mixed('a)
|
||||||
| Discrete('b)
|
| Discrete('b)
|
||||||
| Continuous('c)
|
| Continuous('c)
|
||||||
|
|
||||||
type shape = shapeMonad<mixedShape, discreteShape, continuousShape>
|
type pointSetDist = pointSetDistMonad<mixedShape, discreteShape, continuousShape>
|
||||||
|
|
||||||
module ShapeMonad = {
|
module ShapeMonad = {
|
||||||
let fmap = (t: shapeMonad<'a, 'b, 'c>, (fn1, fn2, fn3)): shapeMonad<'d, 'e, 'f> =>
|
let fmap = (t: pointSetDistMonad<'a, 'b, 'c>, (fn1, fn2, fn3)): pointSetDistMonad<'d, 'e, 'f> =>
|
||||||
switch t {
|
switch t {
|
||||||
| Mixed(m) => Mixed(fn1(m))
|
| Mixed(m) => Mixed(fn1(m))
|
||||||
| Discrete(m) => Discrete(fn2(m))
|
| Discrete(m) => Discrete(fn2(m))
|
||||||
|
@ -68,13 +68,13 @@ module ShapeMonad = {
|
||||||
|
|
||||||
type generationSource =
|
type generationSource =
|
||||||
| SquiggleString(string)
|
| SquiggleString(string)
|
||||||
| Shape(shape)
|
| Shape(pointSetDist)
|
||||||
|
|
||||||
type distributionUnit =
|
type distributionUnit =
|
||||||
| UnspecifiedDistribution
|
| UnspecifiedDistribution
|
||||||
|
|
||||||
type distPlus = {
|
type distPlus = {
|
||||||
shape: shape,
|
pointSetDist: pointSetDist,
|
||||||
domain: domain,
|
domain: domain,
|
||||||
integralCache: continuousShape,
|
integralCache: continuousShape,
|
||||||
unit: distributionUnit,
|
unit: distributionUnit,
|
|
@ -1,4 +1,4 @@
|
||||||
open DistTypes
|
open PointSetTypes
|
||||||
|
|
||||||
let interpolate = (xMin: float, xMax: float, yMin: float, yMax: float, xIntended: float): float => {
|
let interpolate = (xMin: float, xMax: float, yMin: float, yMax: float, xIntended: float): float => {
|
||||||
let minProportion = (xMax -. xIntended) /. (xMax -. xMin)
|
let minProportion = (xMax -. xIntended) /. (xMax -. xMin)
|
||||||
|
@ -126,8 +126,8 @@ module XtoY = {
|
||||||
/* Returns a between-points-interpolating function that can be used with PointwiseCombination.combine.
|
/* Returns a between-points-interpolating function that can be used with PointwiseCombination.combine.
|
||||||
Interpolation can either be stepwise (using the value on the left) or linear. Extrapolation can be `UseZero or `UseOutermostPoints. */
|
Interpolation can either be stepwise (using the value on the left) or linear. Extrapolation can be `UseZero or `UseOutermostPoints. */
|
||||||
let continuousInterpolator = (
|
let continuousInterpolator = (
|
||||||
interpolation: DistTypes.interpolationStrategy,
|
interpolation: PointSetTypes.interpolationStrategy,
|
||||||
extrapolation: DistTypes.extrapolationStrategy,
|
extrapolation: PointSetTypes.extrapolationStrategy,
|
||||||
): interpolator =>
|
): interpolator =>
|
||||||
switch (interpolation, extrapolation) {
|
switch (interpolation, extrapolation) {
|
||||||
| (#Linear, #UseZero) =>
|
| (#Linear, #UseZero) =>
|
||||||
|
@ -395,7 +395,7 @@ module Analysis = {
|
||||||
let integrateContinuousShape = (
|
let integrateContinuousShape = (
|
||||||
~indefiniteIntegralStepwise=(p, h1) => h1 *. p,
|
~indefiniteIntegralStepwise=(p, h1) => h1 *. p,
|
||||||
~indefiniteIntegralLinear=(p, a, b) => a *. p +. b *. p ** 2.0 /. 2.0,
|
~indefiniteIntegralLinear=(p, a, b) => a *. p +. b *. p ** 2.0 /. 2.0,
|
||||||
t: DistTypes.continuousShape,
|
t: PointSetTypes.continuousShape,
|
||||||
): float => {
|
): float => {
|
||||||
let xs = t.xyShape.xs
|
let xs = t.xyShape.xs
|
||||||
let ys = t.xyShape.ys
|
let ys = t.xyShape.ys
|
||||||
|
@ -424,7 +424,7 @@ module Analysis = {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let getMeanOfSquaresContinuousShape = (t: DistTypes.continuousShape) => {
|
let getMeanOfSquaresContinuousShape = (t: PointSetTypes.continuousShape) => {
|
||||||
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 3.0 /. 3.0 +. b *. p ** 4.0 /. 4.0
|
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 3.0 /. 3.0 +. b *. p ** 4.0 /. 4.0
|
||||||
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 3.0 /. 3.0
|
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 3.0 /. 3.0
|
||||||
integrateContinuousShape(~indefiniteIntegralStepwise, ~indefiniteIntegralLinear, t)
|
integrateContinuousShape(~indefiniteIntegralStepwise, ~indefiniteIntegralLinear, t)
|
|
@ -15,7 +15,6 @@ const samplesToContinuousPdf = (
|
||||||
return {xs: pdf.map(r => r.x), ys: pdf.map(r => r.y)};
|
return {xs: pdf.map(r => r.x), ys: pdf.map(r => r.y)};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
samplesToContinuousPdf,
|
samplesToContinuousPdf,
|
||||||
};
|
};
|
|
@ -11,7 +11,7 @@ module Internals = {
|
||||||
|
|
||||||
type outputs = {
|
type outputs = {
|
||||||
continuousParseParams: option<samplingStats>,
|
continuousParseParams: option<samplingStats>,
|
||||||
shape: option<DistTypes.shape>,
|
pointSetDist: option<PointSetTypes.pointSetDist>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ module Internals = {
|
||||||
ys: array<float>,
|
ys: array<float>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let jsToDist = (d: distJs): DistTypes.xyShape => {
|
let jsToDist = (d: distJs): PointSetTypes.xyShape => {
|
||||||
xs: xsGet(d),
|
xs: xsGet(d),
|
||||||
ys: ysGet(d),
|
ys: ysGet(d),
|
||||||
}
|
}
|
||||||
|
@ -78,15 +78,15 @@ module Internals = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let toShape = (
|
let toPointSetDist = (
|
||||||
~samples: Internals.T.t,
|
~samples: Internals.T.t,
|
||||||
~samplingInputs: ExpressionTypes.ExpressionTree.samplingInputs,
|
~samplingInputs: ASTTypes.AST.samplingInputs,
|
||||||
(),
|
(),
|
||||||
) => {
|
) => {
|
||||||
Array.fast_sort(compare, samples)
|
Array.fast_sort(compare, samples)
|
||||||
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples)
|
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples)
|
||||||
let length = samples |> E.A.length |> float_of_int
|
let length = samples |> E.A.length |> float_of_int
|
||||||
let discrete: DistTypes.discreteShape =
|
let discrete: PointSetTypes.discreteShape =
|
||||||
discretePart
|
discretePart
|
||||||
|> E.FloatFloatMap.fmap(r => r /. length)
|
|> E.FloatFloatMap.fmap(r => r /. length)
|
||||||
|> E.FloatFloatMap.toArray
|
|> E.FloatFloatMap.toArray
|
||||||
|
@ -127,17 +127,15 @@ let toShape = (
|
||||||
}
|
}
|
||||||
: None
|
: None
|
||||||
|
|
||||||
let shape = MixedShapeBuilder.buildSimple(
|
let pointSetDist = MixedShapeBuilder.buildSimple(
|
||||||
~continuous=pdf |> E.O.fmap(fst),
|
~continuous=pdf |> E.O.fmap(fst),
|
||||||
~discrete=Some(discrete),
|
~discrete=Some(discrete),
|
||||||
)
|
)
|
||||||
|
|
||||||
let samplesParse: Internals.Types.outputs = {
|
let samplesParse: Internals.Types.outputs = {
|
||||||
continuousParseParams: pdf |> E.O.fmap(snd),
|
continuousParseParams: pdf |> E.O.fmap(snd),
|
||||||
shape: shape,
|
pointSetDist: pointSetDist,
|
||||||
}
|
}
|
||||||
|
|
||||||
samplesParse
|
samplesParse
|
||||||
}
|
}
|
||||||
|
|
||||||
let fromSamples = (~samplingInputs, samples) => toShape(~samples, ~samplingInputs, ())
|
|
|
@ -1,4 +1,4 @@
|
||||||
open SymbolicTypes
|
open SymbolicDistTypes
|
||||||
|
|
||||||
module Normal = {
|
module Normal = {
|
||||||
type t = normal
|
type t = normal
|
||||||
|
@ -272,7 +272,7 @@ module T = {
|
||||||
| #Float(n) => Float.mean(n)
|
| #Float(n) => Float.mean(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
let operate = (distToFloatOp: ExpressionTypes.distToFloatOperation, s) =>
|
let operate = (distToFloatOp: ASTTypes.distToFloatOperation, s) =>
|
||||||
switch distToFloatOp {
|
switch distToFloatOp {
|
||||||
| #Cdf(f) => Ok(cdf(f, s))
|
| #Cdf(f) => Ok(cdf(f, s))
|
||||||
| #Pdf(f) => Ok(pdf(f, s))
|
| #Pdf(f) => Ok(pdf(f, s))
|
||||||
|
@ -302,7 +302,7 @@ module T = {
|
||||||
let tryAnalyticalSimplification = (
|
let tryAnalyticalSimplification = (
|
||||||
d1: symbolicDist,
|
d1: symbolicDist,
|
||||||
d2: symbolicDist,
|
d2: symbolicDist,
|
||||||
op: ExpressionTypes.algebraicOperation,
|
op: ASTTypes.algebraicOperation,
|
||||||
): analyticalSimplificationResult =>
|
): analyticalSimplificationResult =>
|
||||||
switch (d1, d2) {
|
switch (d1, d2) {
|
||||||
| (#Float(v1), #Float(v2)) =>
|
| (#Float(v1), #Float(v2)) =>
|
||||||
|
@ -317,7 +317,7 @@ module T = {
|
||||||
| _ => #NoSolution
|
| _ => #NoSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
let toShape = (sampleCount, d: symbolicDist): DistTypes.shape =>
|
let toPointSetDist = (sampleCount, d: symbolicDist): PointSetTypes.pointSetDist =>
|
||||||
switch d {
|
switch d {
|
||||||
| #Float(v) => Discrete(Discrete.make(~integralSumCache=Some(1.0), {xs: [v], ys: [1.0]}))
|
| #Float(v) => Discrete(Discrete.make(~integralSumCache=Some(1.0), {xs: [v], ys: [1.0]}))
|
||||||
| _ =>
|
| _ =>
|
Loading…
Reference in New Issue
Block a user