Merge pull request #239 from quantified-uncertainty/format-pass
`yarn format`
This commit is contained in:
commit
71f8a8bb06
|
@ -2,7 +2,8 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "squiggle",
|
"name": "squiggle",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"nodeclean": "rm -r node_modules && rm -r packages/*/node_modules"
|
"nodeclean": "rm -r node_modules && rm -r packages/*/node_modules",
|
||||||
|
"format:all": "prettier --write . && cd packages/squiggle-lang && yarn format"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.6.2"
|
"prettier": "^2.6.2"
|
||||||
|
|
|
@ -4,10 +4,10 @@ open Expect
|
||||||
describe("Bandwidth", () => {
|
describe("Bandwidth", () => {
|
||||||
test("nrd0()", () => {
|
test("nrd0()", () => {
|
||||||
let data = [1., 4., 3., 2.]
|
let data = [1., 4., 3., 2.]
|
||||||
expect(SampleSetDist_Bandwidth.nrd0(data)) -> toEqual(0.7625801874014622)
|
expect(SampleSetDist_Bandwidth.nrd0(data))->toEqual(0.7625801874014622)
|
||||||
})
|
})
|
||||||
test("nrd()", () => {
|
test("nrd()", () => {
|
||||||
let data = [1., 4., 3., 2.]
|
let data = [1., 4., 3., 2.]
|
||||||
expect(SampleSetDist_Bandwidth.nrd(data)) -> toEqual(0.8981499984950554)
|
expect(SampleSetDist_Bandwidth.nrd(data))->toEqual(0.8981499984950554)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,6 +6,8 @@ let normalDist: GenericDist_Types.genericDist = normalDist5
|
||||||
let betaDist: GenericDist_Types.genericDist = Symbolic(#Beta({alpha: 2.0, beta: 5.0}))
|
let betaDist: GenericDist_Types.genericDist = Symbolic(#Beta({alpha: 2.0, beta: 5.0}))
|
||||||
let lognormalDist: GenericDist_Types.genericDist = Symbolic(#Lognormal({mu: 0.0, sigma: 1.0}))
|
let lognormalDist: GenericDist_Types.genericDist = Symbolic(#Lognormal({mu: 0.0, sigma: 1.0}))
|
||||||
let cauchyDist: GenericDist_Types.genericDist = Symbolic(#Cauchy({local: 1.0, scale: 1.0}))
|
let cauchyDist: GenericDist_Types.genericDist = Symbolic(#Cauchy({local: 1.0, scale: 1.0}))
|
||||||
let triangularDist: GenericDist_Types.genericDist = Symbolic(#Triangular({low: 1.0, medium: 2.0, high: 3.0}))
|
let triangularDist: GenericDist_Types.genericDist = Symbolic(
|
||||||
|
#Triangular({low: 1.0, medium: 2.0, high: 3.0}),
|
||||||
|
)
|
||||||
let exponentialDist: GenericDist_Types.genericDist = Symbolic(#Exponential({rate: 2.0}))
|
let exponentialDist: GenericDist_Types.genericDist = Symbolic(#Exponential({rate: 2.0}))
|
||||||
let uniformDist: GenericDist_Types.genericDist = Symbolic(#Uniform({low: 9.0, high: 10.0}))
|
let uniformDist: GenericDist_Types.genericDist = Symbolic(#Uniform({low: 9.0, high: 10.0}))
|
||||||
|
|
|
@ -1,70 +1,73 @@
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
open TestHelpers
|
open TestHelpers
|
||||||
|
|
||||||
// TODO: use Normal.make (etc.), but preferably after the new validation dispatch is in.
|
// TODO: use Normal.make (etc.), but preferably after the new validation dispatch is in.
|
||||||
let mkNormal = (mean, stdev) => GenericDist_Types.Symbolic(#Normal({mean: mean, stdev: stdev}))
|
let mkNormal = (mean, stdev) => GenericDist_Types.Symbolic(#Normal({mean: mean, stdev: stdev}))
|
||||||
let mkBeta = (alpha, beta) => GenericDist_Types.Symbolic(#Beta({alpha: alpha, beta: beta}))
|
let mkBeta = (alpha, beta) => GenericDist_Types.Symbolic(#Beta({alpha: alpha, beta: beta}))
|
||||||
let mkExponential = rate => GenericDist_Types.Symbolic(#Exponential({rate: rate}))
|
let mkExponential = rate => GenericDist_Types.Symbolic(#Exponential({rate: rate}))
|
||||||
let mkUniform = (low, high) => GenericDist_Types.Symbolic(#Uniform({low: low, high: high}))
|
let mkUniform = (low, high) => GenericDist_Types.Symbolic(#Uniform({low: low, high: high}))
|
||||||
let mkCauchy = (local, scale) => GenericDist_Types.Symbolic(#Cauchy({local: local, scale: scale}))
|
let mkCauchy = (local, scale) => GenericDist_Types.Symbolic(#Cauchy({local: local, scale: scale}))
|
||||||
let mkLognormal = (mu, sigma) => GenericDist_Types.Symbolic(#Lognormal({mu: mu, sigma: sigma}))
|
let mkLognormal = (mu, sigma) => GenericDist_Types.Symbolic(#Lognormal({mu: mu, sigma: sigma}))
|
||||||
|
|
||||||
describe("mixture", () => {
|
describe("mixture", () => {
|
||||||
testAll("fair mean of two normal distributions", list{(0.0, 1e2), (-1e1, -1e-4), (-1e1, 1e2), (-1e1, 1e1)}, tup => { // should be property
|
|
||||||
let (mean1, mean2) = tup
|
|
||||||
let meanValue = {
|
|
||||||
run(Mixture([(mkNormal(mean1, 9e-1), 0.5), (mkNormal(mean2, 9e-1), 0.5)]))
|
|
||||||
-> outputMap(FromDist(ToFloat(#Mean)))
|
|
||||||
}
|
|
||||||
meanValue -> unpackFloat -> expect -> toBeSoCloseTo((mean1 +. mean2) /. 2.0, ~digits=-1)
|
|
||||||
})
|
|
||||||
testAll(
|
testAll(
|
||||||
"weighted mean of a beta and an exponential",
|
"fair mean of two normal distributions",
|
||||||
// This would not survive property testing, it was easy for me to find cases that NaN'd out.
|
list{(0.0, 1e2), (-1e1, -1e-4), (-1e1, 1e2), (-1e1, 1e1)},
|
||||||
list{((128.0, 1.0), 2.0), ((2e-1, 64.0), 16.0), ((1e0, 1e0), 64.0)},
|
tup => {
|
||||||
tup => {
|
// should be property
|
||||||
let ((alpha, beta), rate) = tup
|
let (mean1, mean2) = tup
|
||||||
let betaWeight = 0.25
|
let meanValue = {
|
||||||
let exponentialWeight = 0.75
|
run(Mixture([(mkNormal(mean1, 9e-1), 0.5), (mkNormal(mean2, 9e-1), 0.5)]))->outputMap(
|
||||||
let meanValue = {
|
FromDist(ToFloat(#Mean)),
|
||||||
run(Mixture(
|
|
||||||
[
|
|
||||||
(mkBeta(alpha, beta), betaWeight),
|
|
||||||
(mkExponential(rate), exponentialWeight)
|
|
||||||
]
|
|
||||||
)) -> outputMap(FromDist(ToFloat(#Mean)))
|
|
||||||
}
|
|
||||||
let betaMean = 1.0 /. (1.0 +. beta /. alpha)
|
|
||||||
let exponentialMean = 1.0 /. rate
|
|
||||||
meanValue
|
|
||||||
-> unpackFloat
|
|
||||||
-> expect
|
|
||||||
-> toBeSoCloseTo(
|
|
||||||
betaWeight *. betaMean +. exponentialWeight *. exponentialMean,
|
|
||||||
~digits=-1
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
meanValue->unpackFloat->expect->toBeSoCloseTo((mean1 +. mean2) /. 2.0, ~digits=-1)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
testAll(
|
testAll(
|
||||||
"weighted mean of lognormal and uniform",
|
"weighted mean of a beta and an exponential",
|
||||||
// Would not survive property tests: very easy to find cases that NaN out.
|
// This would not survive property testing, it was easy for me to find cases that NaN'd out.
|
||||||
list{((-1e2,1e1), (2e0,1e0)), ((-1e-16,1e-16), (1e-8,1e0)), ((0.0,1e0), (1e0,1e-2))},
|
list{((128.0, 1.0), 2.0), ((2e-1, 64.0), 16.0), ((1e0, 1e0), 64.0)},
|
||||||
tup => {
|
tup => {
|
||||||
let ((low, high), (mu, sigma)) = tup
|
let ((alpha, beta), rate) = tup
|
||||||
let uniformWeight = 0.6
|
let betaWeight = 0.25
|
||||||
let lognormalWeight = 0.4
|
let exponentialWeight = 0.75
|
||||||
let meanValue = {
|
let meanValue = {
|
||||||
run(Mixture([(mkUniform(low, high), uniformWeight), (mkLognormal(mu, sigma), lognormalWeight)]))
|
run(
|
||||||
-> outputMap(FromDist(ToFloat(#Mean)))
|
Mixture([(mkBeta(alpha, beta), betaWeight), (mkExponential(rate), exponentialWeight)]),
|
||||||
}
|
)->outputMap(FromDist(ToFloat(#Mean)))
|
||||||
let uniformMean = (low +. high) /. 2.0
|
|
||||||
let lognormalMean = mu +. sigma ** 2.0 /. 2.0
|
|
||||||
meanValue
|
|
||||||
-> unpackFloat
|
|
||||||
-> expect
|
|
||||||
-> toBeSoCloseTo(uniformWeight *. uniformMean +. lognormalWeight *. lognormalMean, ~digits=-1)
|
|
||||||
}
|
}
|
||||||
|
let betaMean = 1.0 /. (1.0 +. beta /. alpha)
|
||||||
|
let exponentialMean = 1.0 /. rate
|
||||||
|
meanValue
|
||||||
|
->unpackFloat
|
||||||
|
->expect
|
||||||
|
->toBeSoCloseTo(betaWeight *. betaMean +. exponentialWeight *. exponentialMean, ~digits=-1)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
testAll(
|
||||||
|
"weighted mean of lognormal and uniform",
|
||||||
|
// Would not survive property tests: very easy to find cases that NaN out.
|
||||||
|
list{((-1e2, 1e1), (2e0, 1e0)), ((-1e-16, 1e-16), (1e-8, 1e0)), ((0.0, 1e0), (1e0, 1e-2))},
|
||||||
|
tup => {
|
||||||
|
let ((low, high), (mu, sigma)) = tup
|
||||||
|
let uniformWeight = 0.6
|
||||||
|
let lognormalWeight = 0.4
|
||||||
|
let meanValue = {
|
||||||
|
run(
|
||||||
|
Mixture([
|
||||||
|
(mkUniform(low, high), uniformWeight),
|
||||||
|
(mkLognormal(mu, sigma), lognormalWeight),
|
||||||
|
]),
|
||||||
|
)->outputMap(FromDist(ToFloat(#Mean)))
|
||||||
|
}
|
||||||
|
let uniformMean = (low +. high) /. 2.0
|
||||||
|
let lognormalMean = mu +. sigma ** 2.0 /. 2.0
|
||||||
|
meanValue
|
||||||
|
->unpackFloat
|
||||||
|
->expect
|
||||||
|
->toBeSoCloseTo(uniformWeight *. uniformMean +. lognormalWeight *. lognormalMean, ~digits=-1)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -38,4 +38,3 @@ describe("Continuous and discrete splits", () => {
|
||||||
let toArr2 = discrete2 |> E.FloatFloatMap.toArray
|
let toArr2 = discrete2 |> E.FloatFloatMap.toArray
|
||||||
makeTest("splitMedium at count=500", toArr2 |> Belt.Array.length, 500)
|
makeTest("splitMedium at count=500", toArr2 |> Belt.Array.length, 500)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -9,125 +9,109 @@ describe("(Symbolic) normalize", () => {
|
||||||
testAll("has no impact on normal distributions", list{-1e8, -1e-2, 0.0, 1e-4, 1e16}, mean => {
|
testAll("has no impact on normal distributions", list{-1e8, -1e-2, 0.0, 1e-4, 1e16}, mean => {
|
||||||
let normalValue = mkNormal(mean, 2.0)
|
let normalValue = mkNormal(mean, 2.0)
|
||||||
let normalizedValue = run(FromDist(ToDist(Normalize), normalValue))
|
let normalizedValue = run(FromDist(ToDist(Normalize), normalValue))
|
||||||
normalizedValue
|
normalizedValue->unpackDist->expect->toEqual(normalValue)
|
||||||
-> unpackDist
|
|
||||||
-> expect
|
|
||||||
-> toEqual(normalValue)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("(Symbolic) mean", () => {
|
describe("(Symbolic) mean", () => {
|
||||||
testAll("of normal distributions", list{-1e8, -16.0, -1e-2, 0.0, 1e-4, 32.0, 1e16}, mean => {
|
testAll("of normal distributions", list{-1e8, -16.0, -1e-2, 0.0, 1e-4, 32.0, 1e16}, mean => {
|
||||||
run(FromDist(ToFloat(#Mean), mkNormal(mean, 4.0)))
|
run(FromDist(ToFloat(#Mean), mkNormal(mean, 4.0)))->unpackFloat->expect->toBeCloseTo(mean)
|
||||||
-> unpackFloat
|
|
||||||
-> expect
|
|
||||||
-> toBeCloseTo(mean)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Skip.test("of normal(0, -1) (it NaNs out)", () => {
|
Skip.test("of normal(0, -1) (it NaNs out)", () => {
|
||||||
run(FromDist(ToFloat(#Mean), mkNormal(1e1, -1e0)))
|
run(FromDist(ToFloat(#Mean), mkNormal(1e1, -1e0)))->unpackFloat->expect->ExpectJs.toBeFalsy
|
||||||
-> unpackFloat
|
|
||||||
-> expect
|
|
||||||
-> ExpectJs.toBeFalsy
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test("of normal(0, 1e-8) (it doesn't freak out at tiny stdev)", () => {
|
test("of normal(0, 1e-8) (it doesn't freak out at tiny stdev)", () => {
|
||||||
run(FromDist(ToFloat(#Mean), mkNormal(0.0, 1e-8)))
|
run(FromDist(ToFloat(#Mean), mkNormal(0.0, 1e-8)))->unpackFloat->expect->toBeCloseTo(0.0)
|
||||||
-> unpackFloat
|
|
||||||
-> expect
|
|
||||||
-> toBeCloseTo(0.0)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
testAll("of exponential distributions", list{1e-7, 2.0, 10.0, 100.0}, rate => {
|
testAll("of exponential distributions", list{1e-7, 2.0, 10.0, 100.0}, rate => {
|
||||||
let meanValue = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Exponential({rate: rate}))))
|
let meanValue = run(
|
||||||
meanValue -> unpackFloat -> expect -> toBeCloseTo(1.0 /. rate) // https://en.wikipedia.org/wiki/Exponential_distribution#Mean,_variance,_moments,_and_median
|
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Exponential({rate: rate}))),
|
||||||
|
)
|
||||||
|
meanValue->unpackFloat->expect->toBeCloseTo(1.0 /. rate) // https://en.wikipedia.org/wiki/Exponential_distribution#Mean,_variance,_moments,_and_median
|
||||||
})
|
})
|
||||||
|
|
||||||
test("of a cauchy distribution", () => {
|
test("of a cauchy distribution", () => {
|
||||||
let meanValue = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Cauchy({local: 1.0, scale: 1.0}))))
|
let meanValue = run(
|
||||||
meanValue
|
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Cauchy({local: 1.0, scale: 1.0}))),
|
||||||
-> unpackFloat
|
)
|
||||||
-> expect
|
meanValue->unpackFloat->expect->toBeCloseTo(2.01868297874546)
|
||||||
-> toBeCloseTo(2.01868297874546)
|
|
||||||
//-> toBe(GenDistError(Other("Cauchy distributions may have no mean value.")))
|
//-> toBe(GenDistError(Other("Cauchy distributions may have no mean value.")))
|
||||||
})
|
})
|
||||||
|
|
||||||
testAll("of triangular distributions", list{(1.0,2.0,3.0), (-1e7,-1e-7,1e-7), (-1e-7,1e0,1e7), (-1e-16,0.0,1e-16)}, tup => {
|
testAll(
|
||||||
let (low, medium, high) = tup
|
"of triangular distributions",
|
||||||
let meanValue = run(FromDist(
|
list{(1.0, 2.0, 3.0), (-1e7, -1e-7, 1e-7), (-1e-7, 1e0, 1e7), (-1e-16, 0.0, 1e-16)},
|
||||||
ToFloat(#Mean),
|
tup => {
|
||||||
GenericDist_Types.Symbolic(#Triangular({low: low, medium: medium, high: high}))
|
let (low, medium, high) = tup
|
||||||
))
|
let meanValue = run(
|
||||||
meanValue
|
FromDist(
|
||||||
-> unpackFloat
|
ToFloat(#Mean),
|
||||||
-> expect
|
GenericDist_Types.Symbolic(#Triangular({low: low, medium: medium, high: high})),
|
||||||
-> toBeCloseTo((low +. medium +. high) /. 3.0) // https://www.statology.org/triangular-distribution/
|
),
|
||||||
})
|
)
|
||||||
|
meanValue->unpackFloat->expect->toBeCloseTo((low +. medium +. high) /. 3.0) // https://www.statology.org/triangular-distribution/
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// TODO: nonpositive inputs are SUPPOSED to crash.
|
// TODO: nonpositive inputs are SUPPOSED to crash.
|
||||||
testAll("of beta distributions", list{(1e-4, 6.4e1), (1.28e2, 1e0), (1e-16, 1e-16), (1e16, 1e16), (-1e4, 1e1), (1e1, -1e4)}, tup => {
|
testAll(
|
||||||
let (alpha, beta) = tup
|
"of beta distributions",
|
||||||
let meanValue = run(FromDist(
|
list{(1e-4, 6.4e1), (1.28e2, 1e0), (1e-16, 1e-16), (1e16, 1e16), (-1e4, 1e1), (1e1, -1e4)},
|
||||||
ToFloat(#Mean),
|
tup => {
|
||||||
GenericDist_Types.Symbolic(#Beta({alpha: alpha, beta: beta}))
|
let (alpha, beta) = tup
|
||||||
))
|
let meanValue = run(
|
||||||
meanValue
|
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Beta({alpha: alpha, beta: beta}))),
|
||||||
-> unpackFloat
|
)
|
||||||
-> expect
|
meanValue->unpackFloat->expect->toBeCloseTo(1.0 /. (1.0 +. beta /. alpha)) // https://en.wikipedia.org/wiki/Beta_distribution#Mean
|
||||||
-> toBeCloseTo(1.0 /. (1.0 +. (beta /. alpha))) // https://en.wikipedia.org/wiki/Beta_distribution#Mean
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
// TODO: When we have our theory of validators we won't want this to be NaN but to be an error.
|
// TODO: When we have our theory of validators we won't want this to be NaN but to be an error.
|
||||||
test("of beta(0, 0)", () => {
|
test("of beta(0, 0)", () => {
|
||||||
let meanValue = run(FromDist(
|
let meanValue = run(
|
||||||
ToFloat(#Mean),
|
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Beta({alpha: 0.0, beta: 0.0}))),
|
||||||
GenericDist_Types.Symbolic(#Beta({alpha: 0.0, beta: 0.0}))
|
)
|
||||||
))
|
meanValue->unpackFloat->expect->ExpectJs.toBeFalsy
|
||||||
meanValue
|
|
||||||
-> unpackFloat
|
|
||||||
-> expect
|
|
||||||
-> ExpectJs.toBeFalsy
|
|
||||||
})
|
})
|
||||||
|
|
||||||
testAll("of lognormal distributions", list{(2.0, 4.0), (1e-7, 1e-2), (-1e6, 10.0), (1e3, -1e2), (-1e8, -1e4), (1e2, 1e-5)}, tup => {
|
testAll(
|
||||||
let (mu, sigma) = tup
|
"of lognormal distributions",
|
||||||
let meanValue = run(FromDist(
|
list{(2.0, 4.0), (1e-7, 1e-2), (-1e6, 10.0), (1e3, -1e2), (-1e8, -1e4), (1e2, 1e-5)},
|
||||||
ToFloat(#Mean),
|
tup => {
|
||||||
GenericDist_Types.Symbolic(#Lognormal({mu: mu, sigma: sigma}))
|
let (mu, sigma) = tup
|
||||||
))
|
let meanValue = run(
|
||||||
meanValue
|
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Lognormal({mu: mu, sigma: sigma}))),
|
||||||
-> unpackFloat
|
)
|
||||||
-> expect
|
meanValue->unpackFloat->expect->toBeCloseTo(Js.Math.exp(mu +. sigma ** 2.0 /. 2.0)) // https://brilliant.org/wiki/log-normal-distribution/
|
||||||
-> toBeCloseTo(Js.Math.exp(mu +. sigma ** 2.0 /. 2.0 )) // https://brilliant.org/wiki/log-normal-distribution/
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
testAll("of uniform distributions", list{(1e-5, 12.345), (-1e4, 1e4), (-1e16, -1e2), (5.3e3, 9e9)}, tup => {
|
testAll(
|
||||||
let (low, high) = tup
|
"of uniform distributions",
|
||||||
let meanValue = run(FromDist(
|
list{(1e-5, 12.345), (-1e4, 1e4), (-1e16, -1e2), (5.3e3, 9e9)},
|
||||||
ToFloat(#Mean),
|
tup => {
|
||||||
GenericDist_Types.Symbolic(#Uniform({low: low, high: high}))
|
let (low, high) = tup
|
||||||
))
|
let meanValue = run(
|
||||||
meanValue
|
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Uniform({low: low, high: high}))),
|
||||||
-> unpackFloat
|
)
|
||||||
-> expect
|
meanValue->unpackFloat->expect->toBeCloseTo((low +. high) /. 2.0) // https://en.wikipedia.org/wiki/Continuous_uniform_distribution#Moments
|
||||||
-> toBeCloseTo((low +. high) /. 2.0) // https://en.wikipedia.org/wiki/Continuous_uniform_distribution#Moments
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
test("of a float", () => {
|
test("of a float", () => {
|
||||||
let meanValue = run(FromDist(
|
let meanValue = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Float(7.7))))
|
||||||
ToFloat(#Mean),
|
meanValue->unpackFloat->expect->toBeCloseTo(7.7)
|
||||||
GenericDist_Types.Symbolic(#Float(7.7))
|
|
||||||
))
|
|
||||||
meanValue -> unpackFloat -> expect -> toBeCloseTo(7.7)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Normal distribution with sparklines", () => {
|
describe("Normal distribution with sparklines", () => {
|
||||||
|
|
||||||
let parameterWiseAdditionPdf = (n1: SymbolicDistTypes.normal, n2: SymbolicDistTypes.normal) => {
|
let parameterWiseAdditionPdf = (n1: SymbolicDistTypes.normal, n2: SymbolicDistTypes.normal) => {
|
||||||
let normalDistAtSumMeanConstr = SymbolicDist.Normal.add(n1, n2)
|
let normalDistAtSumMeanConstr = SymbolicDist.Normal.add(n1, n2)
|
||||||
let normalDistAtSumMean: SymbolicDistTypes.normal = switch normalDistAtSumMeanConstr {
|
let normalDistAtSumMean: SymbolicDistTypes.normal = switch normalDistAtSumMeanConstr {
|
||||||
| #Normal(params) => params
|
| #Normal(params) => params
|
||||||
}
|
}
|
||||||
x => SymbolicDist.Normal.pdf(x, normalDistAtSumMean)
|
x => SymbolicDist.Normal.pdf(x, normalDistAtSumMean)
|
||||||
}
|
}
|
||||||
|
@ -138,24 +122,25 @@ describe("Normal distribution with sparklines", () => {
|
||||||
|
|
||||||
test("mean=5 pdf", () => {
|
test("mean=5 pdf", () => {
|
||||||
let pdfNormalDistAtMean5 = x => SymbolicDist.Normal.pdf(x, normalDistAtMean5)
|
let pdfNormalDistAtMean5 = x => SymbolicDist.Normal.pdf(x, normalDistAtMean5)
|
||||||
let sparklineMean5 = fnImage(pdfNormalDistAtMean5, range20Float)
|
let sparklineMean5 = fnImage(pdfNormalDistAtMean5, range20Float)
|
||||||
Sparklines.create(sparklineMean5, ())
|
Sparklines.create(sparklineMean5, ())
|
||||||
-> expect
|
->expect
|
||||||
-> toEqual(`▁▂▃▆██▇▅▂▁▁▁▁▁▁▁▁▁▁▁`)
|
->toEqual(`▁▂▃▆██▇▅▂▁▁▁▁▁▁▁▁▁▁▁`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("parameter-wise addition of two normal distributions", () => {
|
test("parameter-wise addition of two normal distributions", () => {
|
||||||
let sparklineMean15 = normalDistAtMean5 -> parameterWiseAdditionPdf(normalDistAtMean10) -> fnImage(range20Float)
|
let sparklineMean15 =
|
||||||
|
normalDistAtMean5->parameterWiseAdditionPdf(normalDistAtMean10)->fnImage(range20Float)
|
||||||
Sparklines.create(sparklineMean15, ())
|
Sparklines.create(sparklineMean15, ())
|
||||||
-> expect
|
->expect
|
||||||
-> toEqual(`▁▁▁▁▁▁▁▁▁▂▃▄▆███▇▅▄▂`)
|
->toEqual(`▁▁▁▁▁▁▁▁▁▂▃▄▆███▇▅▄▂`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("mean=10 cdf", () => {
|
test("mean=10 cdf", () => {
|
||||||
let cdfNormalDistAtMean10 = x => SymbolicDist.Normal.cdf(x, normalDistAtMean10)
|
let cdfNormalDistAtMean10 = x => SymbolicDist.Normal.cdf(x, normalDistAtMean10)
|
||||||
let sparklineMean10 = fnImage(cdfNormalDistAtMean10, range20Float)
|
let sparklineMean10 = fnImage(cdfNormalDistAtMean10, range20Float)
|
||||||
Sparklines.create(sparklineMean10, ())
|
Sparklines.create(sparklineMean10, ())
|
||||||
-> expect
|
->expect
|
||||||
-> toEqual(`▁▁▁▁▁▁▁▁▂▄▅▇████████`)
|
->toEqual(`▁▁▁▁▁▁▁▁▂▄▅▇████████`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,8 +3,8 @@ open Expect
|
||||||
|
|
||||||
let makeTest = (~only=false, str, item1, item2) =>
|
let makeTest = (~only=false, str, item1, item2) =>
|
||||||
only
|
only
|
||||||
? 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("Lodash", () =>
|
describe("Lodash", () =>
|
||||||
describe("Lodash", () => {
|
describe("Lodash", () => {
|
||||||
|
|
|
@ -6,8 +6,7 @@ open Expect
|
||||||
let expectEvalToBe = (expr: string, answer: string) =>
|
let expectEvalToBe = (expr: string, answer: string) =>
|
||||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||||
|
|
||||||
let testEval = (expr, answer) =>
|
let testEval = (expr, answer) => test(expr, () => expectEvalToBe(expr, answer))
|
||||||
test(expr, () => expectEvalToBe(expr, answer))
|
|
||||||
|
|
||||||
describe("builtin", () => {
|
describe("builtin", () => {
|
||||||
// All MathJs operators and functions are available for string, number and boolean
|
// All MathJs operators and functions are available for string, number and boolean
|
||||||
|
|
|
@ -14,7 +14,8 @@ let testDescriptionParse = (desc, expr, answer) => test(desc, () => expectParseT
|
||||||
module MySkip = {
|
module MySkip = {
|
||||||
let testParse = (expr, answer) => Skip.test(expr, () => expectParseToBe(expr, answer))
|
let testParse = (expr, answer) => Skip.test(expr, () => expectParseToBe(expr, answer))
|
||||||
|
|
||||||
let testDescriptionParse = (desc, expr, answer) => Skip.test(desc, () => expectParseToBe(expr, answer))
|
let testDescriptionParse = (desc, expr, answer) =>
|
||||||
|
Skip.test(desc, () => expectParseToBe(expr, answer))
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("MathJs parse", () => {
|
describe("MathJs parse", () => {
|
||||||
|
@ -60,7 +61,8 @@ describe("MathJs parse", () => {
|
||||||
MySkip.testDescriptionParse("define", "# This is a comment", "???")
|
MySkip.testDescriptionParse("define", "# This is a comment", "???")
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("if statement", () => { // TODO Tertiary operator instead
|
describe("if statement", () => {
|
||||||
|
// TODO Tertiary operator instead
|
||||||
MySkip.testDescriptionParse("define", "if (true) { 1 } else { 0 }", "???")
|
MySkip.testDescriptionParse("define", "if (true) { 1 } else { 0 }", "???")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,7 +3,8 @@ open Reducer_TestHelpers
|
||||||
|
|
||||||
let testParseToBe = (expr, answer) => test(expr, () => expectParseToBe(expr, answer))
|
let testParseToBe = (expr, answer) => test(expr, () => expectParseToBe(expr, answer))
|
||||||
|
|
||||||
let testDescriptionParseToBe = (desc, expr, answer) => test(desc, () => expectParseToBe(expr, answer))
|
let testDescriptionParseToBe = (desc, expr, answer) =>
|
||||||
|
test(desc, () => expectParseToBe(expr, answer))
|
||||||
|
|
||||||
let testEvalToBe = (expr, answer) => test(expr, () => expectEvalToBe(expr, answer))
|
let testEvalToBe = (expr, answer) => test(expr, () => expectEvalToBe(expr, answer))
|
||||||
|
|
||||||
|
@ -44,13 +45,21 @@ describe("reducer using mathjs parse", () => {
|
||||||
})
|
})
|
||||||
describe("multi-line", () => {
|
describe("multi-line", () => {
|
||||||
testParseToBe("1; 2", "Ok((:$$bindExpression (:$$bindStatement (:$$bindings) 1) 2))")
|
testParseToBe("1; 2", "Ok((:$$bindExpression (:$$bindStatement (:$$bindings) 1) 2))")
|
||||||
testParseToBe("1+1; 2+1", "Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:add 1 1)) (:add 2 1)))")
|
testParseToBe(
|
||||||
|
"1+1; 2+1",
|
||||||
|
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:add 1 1)) (:add 2 1)))",
|
||||||
|
)
|
||||||
})
|
})
|
||||||
describe("assignment", () => {
|
describe("assignment", () => {
|
||||||
testParseToBe("x=1; x", "Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:$let :x 1)) :x))")
|
testParseToBe(
|
||||||
testParseToBe("x=1+1; x+1", "Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:$let :x (:add 1 1))) (:add :x 1)))")
|
"x=1; x",
|
||||||
|
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:$let :x 1)) :x))",
|
||||||
|
)
|
||||||
|
testParseToBe(
|
||||||
|
"x=1+1; x+1",
|
||||||
|
"Ok((:$$bindExpression (:$$bindStatement (:$$bindings) (:$let :x (:add 1 1))) (:add :x 1)))",
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("eval", () => {
|
describe("eval", () => {
|
||||||
|
@ -101,5 +110,9 @@ describe("test exceptions", () => {
|
||||||
"javascriptraise('div by 0')",
|
"javascriptraise('div by 0')",
|
||||||
"Error(JS Exception: Error: 'div by 0')",
|
"Error(JS Exception: Error: 'div by 0')",
|
||||||
)
|
)
|
||||||
testDescriptionEvalToBe("rescript exception", "rescriptraise()", "Error(TODO: unhandled rescript exception)")
|
testDescriptionEvalToBe(
|
||||||
|
"rescript exception",
|
||||||
|
"rescriptraise()",
|
||||||
|
"Error(TODO: unhandled rescript exception)",
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -111,7 +111,11 @@ describe("parse on distribution functions", () => {
|
||||||
})
|
})
|
||||||
describe("pointwise arithmetic expressions", () => {
|
describe("pointwise arithmetic expressions", () => {
|
||||||
testParse(~skip=true, "normal(5,2) .+ normal(5,1)", "Ok((:dotAdd (:normal 5 2) (:normal 5 1)))")
|
testParse(~skip=true, "normal(5,2) .+ normal(5,1)", "Ok((:dotAdd (:normal 5 2) (:normal 5 1)))")
|
||||||
testParse(~skip=true, "normal(5,2) .- normal(5,1)", "Ok((:dotSubtract (:normal 5 2) (:normal 5 1)))")
|
testParse(
|
||||||
|
~skip=true,
|
||||||
|
"normal(5,2) .- normal(5,1)",
|
||||||
|
"Ok((:dotSubtract (:normal 5 2) (:normal 5 1)))",
|
||||||
|
)
|
||||||
testParse("normal(5,2) .* normal(5,1)", "Ok((:dotMultiply (:normal 5 2) (:normal 5 1)))")
|
testParse("normal(5,2) .* normal(5,1)", "Ok((:dotMultiply (:normal 5 2) (:normal 5 1)))")
|
||||||
testParse("normal(5,2) ./ normal(5,1)", "Ok((:dotDivide (:normal 5 2) (:normal 5 1)))")
|
testParse("normal(5,2) ./ normal(5,1)", "Ok((:dotDivide (:normal 5 2) (:normal 5 1)))")
|
||||||
testParse("normal(5,2) .^ normal(5,1)", "Ok((:dotPow (:normal 5 2) (:normal 5 1)))")
|
testParse("normal(5,2) .^ normal(5,1)", "Ok((:dotPow (:normal 5 2) (:normal 5 1)))")
|
||||||
|
|
|
@ -3,9 +3,8 @@ open Expect
|
||||||
|
|
||||||
let makeTest = (~only=false, str, item1, item2) =>
|
let makeTest = (~only=false, str, item1, item2) =>
|
||||||
only
|
only
|
||||||
? 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 {toFloat, toDist, toString, toError, fmap} = module(DistributionOperation.Output)
|
let {toFloat, toDist, toString, toError, fmap} = module(DistributionOperation.Output)
|
||||||
|
|
||||||
|
@ -20,7 +19,9 @@ let run = DistributionOperation.run(~env)
|
||||||
let outputMap = fmap(~env)
|
let outputMap = fmap(~env)
|
||||||
let unreachableInTestFileMessage = "Should be impossible to reach (This error is in test file)"
|
let unreachableInTestFileMessage = "Should be impossible to reach (This error is in test file)"
|
||||||
let toExtFloat: option<float> => float = E.O.toExt(unreachableInTestFileMessage)
|
let toExtFloat: option<float> => float = E.O.toExt(unreachableInTestFileMessage)
|
||||||
let toExtDist: option<GenericDist_Types.genericDist> => GenericDist_Types.genericDist = E.O.toExt(unreachableInTestFileMessage)
|
let toExtDist: option<GenericDist_Types.genericDist> => GenericDist_Types.genericDist = E.O.toExt(
|
||||||
|
unreachableInTestFileMessage,
|
||||||
|
)
|
||||||
// let toExt: option<'a> => 'a = E.O.toExt(unreachableInTestFileMessage)
|
// let toExt: option<'a> => 'a = E.O.toExt(unreachableInTestFileMessage)
|
||||||
let unpackFloat = x => x -> toFloat -> toExtFloat
|
let unpackFloat = x => x->toFloat->toExtFloat
|
||||||
let unpackDist = y => y -> toDist -> toExtDist
|
let unpackDist = y => y->toDist->toExtDist
|
||||||
|
|
|
@ -3,8 +3,8 @@ open Expect
|
||||||
|
|
||||||
let makeTest = (~only=false, str, item1, item2) =>
|
let makeTest = (~only=false, str, item1, item2) =>
|
||||||
only
|
only
|
||||||
? 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 pointSetDist1: PointSetTypes.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]}
|
||||||
|
|
||||||
|
@ -21,7 +21,11 @@ let pointSetDist3: PointSetTypes.xyShape = {
|
||||||
describe("XYShapes", () => {
|
describe("XYShapes", () => {
|
||||||
describe("logScorePoint", () => {
|
describe("logScorePoint", () => {
|
||||||
makeTest("When identical", XYShape.logScorePoint(30, pointSetDist1, pointSetDist1), Some(0.0))
|
makeTest("When identical", XYShape.logScorePoint(30, pointSetDist1, pointSetDist1), Some(0.0))
|
||||||
makeTest("When similar", XYShape.logScorePoint(30, pointSetDist1, pointSetDist2), 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, pointSetDist1, pointSetDist3),
|
XYShape.logScorePoint(30, pointSetDist1, pointSetDist3),
|
||||||
|
|
|
@ -39,57 +39,52 @@ module Output: {
|
||||||
}
|
}
|
||||||
|
|
||||||
module Constructors: {
|
module Constructors: {
|
||||||
@genType
|
@genType
|
||||||
let mean: (~env: env, genericDist) => result<float, error>
|
let mean: (~env: env, genericDist) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
let sample: (~env: env, genericDist) => result<float, error>
|
let sample: (~env: env, genericDist) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
let cdf: (~env: env, genericDist, float) => result<float, error>
|
let cdf: (~env: env, genericDist, float) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
let inv: (~env: env, genericDist, float) => result<float, error>
|
let inv: (~env: env, genericDist, float) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
let pdf: (~env: env, genericDist, float) => result<float, error>
|
let pdf: (~env: env, genericDist, float) => result<float, error>
|
||||||
@genType
|
@genType
|
||||||
let normalize: (~env: env, genericDist) => result<genericDist, error>
|
let normalize: (~env: env, genericDist) => result<genericDist, error>
|
||||||
@genType
|
@genType
|
||||||
let toPointSet: (~env: env, genericDist) => result<genericDist, error>
|
let toPointSet: (~env: env, genericDist) => result<genericDist, error>
|
||||||
@genType
|
@genType
|
||||||
let toSampleSet: (~env: env, genericDist, int) => result<genericDist, error>
|
let toSampleSet: (~env: env, genericDist, int) => result<genericDist, error>
|
||||||
@genType
|
@genType
|
||||||
let truncate: (
|
let truncate: (~env: env, genericDist, option<float>, option<float>) => result<genericDist, error>
|
||||||
~env: env,
|
@genType
|
||||||
genericDist,
|
let inspect: (~env: env, genericDist) => result<genericDist, error>
|
||||||
option<float>,
|
@genType
|
||||||
option<float>,
|
let toString: (~env: env, genericDist) => result<string, error>
|
||||||
) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let toSparkline: (~env: env, genericDist, int) => result<string, error>
|
||||||
let inspect: (~env: env, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let algebraicAdd: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let toString: (~env: env, genericDist) => result<string, error>
|
@genType
|
||||||
@genType
|
let algebraicMultiply: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let toSparkline: (~env: env, genericDist, int) => result<string, error>
|
@genType
|
||||||
@genType
|
let algebraicDivide: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let algebraicAdd: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let algebraicSubtract: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let algebraicMultiply: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let algebraicLogarithm: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let algebraicDivide: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let algebraicPower: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let algebraicSubtract: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let pointwiseAdd: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let algebraicLogarithm: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let pointwiseMultiply: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let algebraicPower: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let pointwiseDivide: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let pointwiseAdd: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let pointwiseSubtract: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let pointwiseMultiply: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let pointwiseLogarithm: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let pointwiseDivide: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
@genType
|
||||||
@genType
|
let pointwisePower: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
||||||
let pointwiseSubtract: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
|
||||||
@genType
|
|
||||||
let pointwiseLogarithm: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
|
||||||
@genType
|
|
||||||
let pointwisePower: (~env: env, genericDist, genericDist) => result<genericDist, error>
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,11 @@ module DistributionOperation = {
|
||||||
type fromDist =
|
type fromDist =
|
||||||
| ToFloat(Operation.toFloat)
|
| ToFloat(Operation.toFloat)
|
||||||
| ToDist(toDist)
|
| ToDist(toDist)
|
||||||
| ToDistCombination(Operation.direction, Operation.arithmeticOperation, [#Dist(genericDist) | #Float(float)])
|
| ToDistCombination(
|
||||||
|
Operation.direction,
|
||||||
|
Operation.arithmeticOperation,
|
||||||
|
[#Dist(genericDist) | #Float(float)],
|
||||||
|
)
|
||||||
| ToString
|
| ToString
|
||||||
|
|
||||||
type singleParamaterFunction =
|
type singleParamaterFunction =
|
||||||
|
|
|
@ -15,7 +15,7 @@ module Error = {
|
||||||
type t = error
|
type t = error
|
||||||
|
|
||||||
let fromString = (s: string): t => Other(s)
|
let fromString = (s: string): t => Other(s)
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let toString = (x: t) => {
|
let toString = (x: t) => {
|
||||||
switch x {
|
switch x {
|
||||||
|
|
|
@ -100,7 +100,6 @@ let combineShapesContinuousContinuous = (
|
||||||
s1: PointSetTypes.xyShape,
|
s1: PointSetTypes.xyShape,
|
||||||
s2: PointSetTypes.xyShape,
|
s2: PointSetTypes.xyShape,
|
||||||
): PointSetTypes.xyShape => {
|
): PointSetTypes.xyShape => {
|
||||||
|
|
||||||
// if we add the two distributions, we should probably use normal filters.
|
// if we add the two distributions, we should probably use normal filters.
|
||||||
// if we multiply the two distributions, we should probably use lognormal filters.
|
// if we multiply the two distributions, we should probably use lognormal filters.
|
||||||
let t1m = toDiscretePointMassesFromTriangulars(s1)
|
let t1m = toDiscretePointMassesFromTriangulars(s1)
|
||||||
|
|
|
@ -235,18 +235,10 @@ module T = Dist({
|
||||||
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 2.0 /. 2.0
|
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 2.0 /. 2.0
|
||||||
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 2.0 /. 2.0 +. b *. p ** 3.0 /. 3.0
|
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 2.0 /. 2.0 +. b *. p ** 3.0 /. 3.0
|
||||||
|
|
||||||
Analysis.integrate(
|
Analysis.integrate(~indefiniteIntegralStepwise, ~indefiniteIntegralLinear, t)
|
||||||
~indefiniteIntegralStepwise,
|
|
||||||
~indefiniteIntegralLinear,
|
|
||||||
t,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
let variance = (t: t): float =>
|
let variance = (t: t): float =>
|
||||||
XYShape.Analysis.getVarianceDangerously(
|
XYShape.Analysis.getVarianceDangerously(t, mean, Analysis.getMeanOfSquares)
|
||||||
t,
|
|
||||||
mean,
|
|
||||||
Analysis.getMeanOfSquares,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
let downsampleEquallyOverX = (length, t): t =>
|
let downsampleEquallyOverX = (length, t): t =>
|
||||||
|
|
|
@ -212,8 +212,7 @@ module T = Dist({
|
||||||
let totalIntegralSum = discreteIntegralSum +. continuousIntegralSum
|
let totalIntegralSum = discreteIntegralSum +. continuousIntegralSum
|
||||||
|
|
||||||
let getMeanOfSquares = ({discrete, continuous}: t) => {
|
let getMeanOfSquares = ({discrete, continuous}: t) => {
|
||||||
let discreteMean =
|
let discreteMean = discrete |> Discrete.shapeMap(XYShape.T.square) |> Discrete.T.mean
|
||||||
discrete |> Discrete.shapeMap(XYShape.T.square) |> Discrete.T.mean
|
|
||||||
let continuousMean = continuous |> Continuous.Analysis.getMeanOfSquares
|
let continuousMean = continuous |> Continuous.Analysis.getMeanOfSquares
|
||||||
(discreteMean *. discreteIntegralSum +. continuousMean *. continuousIntegralSum) /.
|
(discreteMean *. discreteIntegralSum +. continuousMean *. continuousIntegralSum) /.
|
||||||
totalIntegralSum
|
totalIntegralSum
|
||||||
|
|
|
@ -207,4 +207,4 @@ let toSparkline = (t: t, bucketCount) =>
|
||||||
T.toContinuous(t)
|
T.toContinuous(t)
|
||||||
->E.O2.fmap(Continuous.downsampleEquallyOverX(bucketCount))
|
->E.O2.fmap(Continuous.downsampleEquallyOverX(bucketCount))
|
||||||
->E.O2.toResult("toContinous Error: Could not convert into continuous distribution")
|
->E.O2.toResult("toContinous Error: Could not convert into continuous distribution")
|
||||||
->E.R2.fmap(r => Continuous.getShape(r).ys->Sparklines.create())
|
->E.R2.fmap(r => Continuous.getShape(r).ys->Sparklines.create())
|
||||||
|
|
|
@ -14,10 +14,10 @@ type distributionType = [
|
||||||
| #CDF
|
| #CDF
|
||||||
]
|
]
|
||||||
|
|
||||||
type xyShape = XYShape.xyShape;
|
type xyShape = XYShape.xyShape
|
||||||
type interpolationStrategy = XYShape.interpolationStrategy;
|
type interpolationStrategy = XYShape.interpolationStrategy
|
||||||
type extrapolationStrategy = XYShape.extrapolationStrategy;
|
type extrapolationStrategy = XYShape.extrapolationStrategy
|
||||||
type interpolator = XYShape.extrapolationStrategy;
|
type interpolator = XYShape.extrapolationStrategy
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type rec continuousShape = {
|
type rec continuousShape = {
|
||||||
|
|
|
@ -81,7 +81,7 @@ module Triangular = {
|
||||||
low < medium && medium < high
|
low < medium && medium < high
|
||||||
? Ok(#Triangular({low: low, medium: medium, high: high}))
|
? Ok(#Triangular({low: low, medium: medium, high: high}))
|
||||||
: Error("Triangular values must be increasing order.")
|
: Error("Triangular values must be increasing order.")
|
||||||
let pdf = (x, t: t) => Jstat.Triangular.pdf(x, t.low, t.high, t.medium) // not obvious in jstat docs that high comes before medium?
|
let pdf = (x, t: t) => Jstat.Triangular.pdf(x, t.low, t.high, t.medium) // not obvious in jstat docs that high comes before medium?
|
||||||
let cdf = (x, t: t) => Jstat.Triangular.cdf(x, t.low, t.high, t.medium)
|
let cdf = (x, t: t) => Jstat.Triangular.cdf(x, t.low, t.high, t.medium)
|
||||||
let inv = (p, t: t) => Jstat.Triangular.inv(p, t.low, t.high, t.medium)
|
let inv = (p, t: t) => Jstat.Triangular.inv(p, t.low, t.high, t.medium)
|
||||||
let sample = (t: t) => Jstat.Triangular.sample(t.low, t.high, t.medium)
|
let sample = (t: t) => Jstat.Triangular.sample(t.low, t.high, t.medium)
|
||||||
|
@ -346,7 +346,11 @@ module T = {
|
||||||
| _ => #NoSolution
|
| _ => #NoSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
let toPointSetDist = (~xSelection=#ByWeight, sampleCount, d: symbolicDist): PointSetTypes.pointSetDist =>
|
let toPointSetDist = (
|
||||||
|
~xSelection=#ByWeight,
|
||||||
|
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]}))
|
||||||
| _ =>
|
| _ =>
|
||||||
|
|
|
@ -21,4 +21,4 @@ let toPointSetDist = (samplingInputs, environment, node: node) =>
|
||||||
let runFunction = (samplingInputs, environment, inputs, fn: ASTTypes.Function.t) => {
|
let runFunction = (samplingInputs, environment, inputs, fn: ASTTypes.Function.t) => {
|
||||||
let params = envs(samplingInputs, environment)
|
let params = envs(samplingInputs, environment)
|
||||||
ASTTypes.Function.run(params, inputs, fn)
|
ASTTypes.Function.run(params, inputs, fn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ let makeSymbolicFromTwoFloats = (name, fn) =>
|
||||||
~inputTypes=[#Float, #Float],
|
~inputTypes=[#Float, #Float],
|
||||||
~run=x =>
|
~run=x =>
|
||||||
switch x {
|
switch x {
|
||||||
| [#Float(a), #Float(b)] => fn(a, b) |> E.R.fmap(r => (#SymbolicDist(r)))
|
| [#Float(a), #Float(b)] => fn(a, b) |> E.R.fmap(r => #SymbolicDist(r))
|
||||||
| e => wrongInputsError(e)
|
| e => wrongInputsError(e)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -90,7 +90,8 @@ let floatFromDist = (
|
||||||
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) => PointSetDist.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) => {
|
||||||
|
@ -125,10 +126,15 @@ module Multimodal = {
|
||||||
->E.R.bind(TypeSystem.TypedValue.toArray)
|
->E.R.bind(TypeSystem.TypedValue.toArray)
|
||||||
->E.R.bind(r => r |> E.A.fmap(TypeSystem.TypedValue.toFloat) |> E.A.R.firstErrorOrOpen)
|
->E.R.bind(r => r |> E.A.fmap(TypeSystem.TypedValue.toFloat) |> E.A.R.firstErrorOrOpen)
|
||||||
|
|
||||||
E.R.merge(dists, weights) -> E.R.bind(((a, b)) =>
|
E.R.merge(dists, weights)->E.R.bind(((a, b)) =>
|
||||||
E.A.length(b) > E.A.length(a) ?
|
E.A.length(b) > E.A.length(a)
|
||||||
Error("Too many weights provided") :
|
? Error("Too many weights provided")
|
||||||
Ok(E.A.zipMaxLength(a, b) |> E.A.fmap(((a, b)) => (a |> E.O.toExn(""), b |> E.O.default(1.0))))
|
: Ok(
|
||||||
|
E.A.zipMaxLength(a, b) |> E.A.fmap(((a, b)) => (
|
||||||
|
a |> E.O.toExn(""),
|
||||||
|
b |> E.O.default(1.0),
|
||||||
|
)),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
| _ => Error("Needs items")
|
| _ => Error("Needs items")
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,11 +86,7 @@ module TypedValue = {
|
||||||
|> E.R.fmap(r => #Array(r))
|
|> E.R.fmap(r => #Array(r))
|
||||||
| (#Hash(named), #Hash(r)) =>
|
| (#Hash(named), #Hash(r)) =>
|
||||||
let keyValues =
|
let keyValues =
|
||||||
named |> E.A.fmap(((name, intendedType)) => (
|
named |> E.A.fmap(((name, intendedType)) => (name, intendedType, Hash.getByName(r, name)))
|
||||||
name,
|
|
||||||
intendedType,
|
|
||||||
Hash.getByName(r, name),
|
|
||||||
))
|
|
||||||
let typedHash =
|
let typedHash =
|
||||||
keyValues
|
keyValues
|
||||||
|> E.A.fmap(((name, intendedType, optionNode)) =>
|
|> E.A.fmap(((name, intendedType, optionNode)) =>
|
||||||
|
@ -180,11 +176,7 @@ module Function = {
|
||||||
_coerceInputNodes(evaluationParams, t.inputTypes, t.shouldCoerceTypes),
|
_coerceInputNodes(evaluationParams, t.inputTypes, t.shouldCoerceTypes),
|
||||||
)
|
)
|
||||||
|
|
||||||
let run = (
|
let run = (evaluationParams: ASTTypes.evaluationParams, inputNodes: inputNodes, t: t) =>
|
||||||
evaluationParams: ASTTypes.evaluationParams,
|
|
||||||
inputNodes: inputNodes,
|
|
||||||
t: t,
|
|
||||||
) =>
|
|
||||||
inputsToTypedValues(evaluationParams, inputNodes, t)->E.R.bind(t.run)
|
inputsToTypedValues(evaluationParams, inputNodes, t)->E.R.bind(t.run)
|
||||||
|> (
|
|> (
|
||||||
x =>
|
x =>
|
||||||
|
|
|
@ -179,14 +179,15 @@ module R = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module R2 = {
|
module R2 = {
|
||||||
let fmap = (a,b) => R.fmap(b,a)
|
let fmap = (a, b) => R.fmap(b, a)
|
||||||
let bind = (a, b) => R.bind(b, a)
|
let bind = (a, b) => R.bind(b, a)
|
||||||
|
|
||||||
//Converts result type to change error type only
|
//Converts result type to change error type only
|
||||||
let errMap = (a, map) => switch(a){
|
let errMap = (a, map) =>
|
||||||
|
switch a {
|
||||||
| Ok(r) => Ok(r)
|
| Ok(r) => Ok(r)
|
||||||
| Error(e) => map(e)
|
| Error(e) => map(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let safe_fn_of_string = (fn, s: string): option<'a> =>
|
let safe_fn_of_string = (fn, s: string): option<'a> =>
|
||||||
|
@ -300,7 +301,6 @@ module A = {
|
||||||
|> Rationale.Result.return
|
|> Rationale.Result.return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This zips while taking the longest elements of each array.
|
// This zips while taking the longest elements of each array.
|
||||||
let zipMaxLength = (array1, array2) => {
|
let zipMaxLength = (array1, array2) => {
|
||||||
let maxLength = Int.max(length(array1), length(array2))
|
let maxLength = Int.max(length(array1), length(array2))
|
||||||
|
@ -456,7 +456,6 @@ module A = {
|
||||||
let diff = (arr: array<float>): array<float> =>
|
let diff = (arr: array<float>): array<float> =>
|
||||||
Belt.Array.zipBy(arr, Belt.Array.sliceToEnd(arr, 1), (left, right) => right -. left)
|
Belt.Array.zipBy(arr, Belt.Array.sliceToEnd(arr, 1), (left, right) => right -. left)
|
||||||
|
|
||||||
|
|
||||||
exception RangeError(string)
|
exception RangeError(string)
|
||||||
let range = (min: float, max: float, n: int): array<float> =>
|
let range = (min: float, max: float, n: int): array<float> =>
|
||||||
switch n {
|
switch n {
|
||||||
|
@ -474,7 +473,7 @@ module A = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module A2 = {
|
module A2 = {
|
||||||
let fmap = (a,b) => A.fmap(b,a)
|
let fmap = (a, b) => A.fmap(b, a)
|
||||||
let joinWith = (a, b) => A.joinWith(b, a)
|
let joinWith = (a, b) => A.joinWith(b, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ module Exponential = {
|
||||||
@module("jstat") @scope("exponential") external pdf: (float, float) => float = "pdf"
|
@module("jstat") @scope("exponential") external pdf: (float, float) => float = "pdf"
|
||||||
@module("jstat") @scope("exponential") external cdf: (float, float) => float = "cdf"
|
@module("jstat") @scope("exponential") external cdf: (float, float) => float = "cdf"
|
||||||
@module("jstat") @scope("exponential") external inv: (float, float) => float = "inv"
|
@module("jstat") @scope("exponential") external inv: (float, float) => float = "inv"
|
||||||
@module("jstat") @scope("exponential") external sample: (float) => float = "sample"
|
@module("jstat") @scope("exponential") external sample: float => float = "sample"
|
||||||
@module("jstat") @scope("exponential") external mean: (float) => float = "mean"
|
@module("jstat") @scope("exponential") external mean: float => float = "mean"
|
||||||
}
|
}
|
||||||
|
|
||||||
module Cauchy = {
|
module Cauchy = {
|
||||||
|
@ -56,7 +56,6 @@ module Triangular = {
|
||||||
@module("jstat") @scope("triangular") external mean: (float, float, float) => float = "mean"
|
@module("jstat") @scope("triangular") external mean: (float, float, float) => float = "mean"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module Pareto = {
|
module Pareto = {
|
||||||
@module("jstat") @scope("pareto") external pdf: (float, float, float) => float = "pdf"
|
@module("jstat") @scope("pareto") external pdf: (float, float, float) => float = "pdf"
|
||||||
@module("jstat") @scope("pareto") external cdf: (float, float, float) => float = "cdf"
|
@module("jstat") @scope("pareto") external cdf: (float, float, float) => float = "cdf"
|
||||||
|
@ -66,20 +65,20 @@ module Pareto = {
|
||||||
module Poisson = {
|
module Poisson = {
|
||||||
@module("jstat") @scope("poisson") external pdf: (float, float) => float = "pdf"
|
@module("jstat") @scope("poisson") external pdf: (float, float) => float = "pdf"
|
||||||
@module("jstat") @scope("poisson") external cdf: (float, float) => float = "cdf"
|
@module("jstat") @scope("poisson") external cdf: (float, float) => float = "cdf"
|
||||||
@module("jstat") @scope("poisson") external sample: (float) => float = "sample"
|
@module("jstat") @scope("poisson") external sample: float => float = "sample"
|
||||||
@module("jstat") @scope("poisson") external mean: (float) => float = "mean"
|
@module("jstat") @scope("poisson") external mean: float => float = "mean"
|
||||||
}
|
}
|
||||||
|
|
||||||
module Weibull = {
|
module Weibull = {
|
||||||
@module("jstat") @scope("weibull") external pdf: (float, float, float) => float = "pdf"
|
@module("jstat") @scope("weibull") external pdf: (float, float, float) => float = "pdf"
|
||||||
@module("jstat") @scope("weibull") external cdf: (float, float,float ) => float = "cdf"
|
@module("jstat") @scope("weibull") external cdf: (float, float, float) => float = "cdf"
|
||||||
@module("jstat") @scope("weibull") external sample: (float,float) => float = "sample"
|
@module("jstat") @scope("weibull") external sample: (float, float) => float = "sample"
|
||||||
@module("jstat") @scope("weibull") external mean: (float,float) => float = "mean"
|
@module("jstat") @scope("weibull") external mean: (float, float) => float = "mean"
|
||||||
}
|
}
|
||||||
|
|
||||||
module Binomial = {
|
module Binomial = {
|
||||||
@module("jstat") @scope("binomial") external pdf: (float, float, float) => float = "pdf"
|
@module("jstat") @scope("binomial") external pdf: (float, float, float) => float = "pdf"
|
||||||
@module("jstat") @scope("binomial") external cdf: (float, float,float ) => float = "cdf"
|
@module("jstat") @scope("binomial") external cdf: (float, float, float) => float = "cdf"
|
||||||
}
|
}
|
||||||
|
|
||||||
@module("jstat") external sum: array<float> => float = "sum"
|
@module("jstat") external sum: array<float> => float = "sum"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user