property test framework installed but not used; describe(means) section of unit tests filled out
This commit is contained in:
parent
e42ac0b58d
commit
0a5a8a5198
|
@ -13,6 +13,9 @@ Other:
|
||||||
yarn start # listens to files and recompiles at every mutation
|
yarn start # listens to files and recompiles at every mutation
|
||||||
yarn test
|
yarn test
|
||||||
yarn test:watch # keeps an active session and runs all tests at every mutation
|
yarn test:watch # keeps an active session and runs all tests at every mutation
|
||||||
|
|
||||||
|
# where o := open in osx and o := xdg-open in linux,
|
||||||
|
yarn coverage; o _coverage/index.html # produces coverage report and opens it in browser
|
||||||
```
|
```
|
||||||
|
|
||||||
# TODO: clean up this README.md
|
# TODO: clean up this README.md
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
open Jest
|
open Jest
|
||||||
open Expect
|
open Expect
|
||||||
|
open FastCheck
|
||||||
|
// open Arbitrary
|
||||||
|
open Property.Sync
|
||||||
|
|
||||||
let env: DistributionOperation.env = {
|
let env: DistributionOperation.env = {
|
||||||
sampleCount: 100,
|
sampleCount: 100,
|
||||||
xyPointLength: 100,
|
xyPointLength: 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
let normalDist5: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 5.0, stdev: 2.0}))
|
let mkNormal = (mean, stdev) => GenericDist_Types.Symbolic(#Normal({mean: mean, stdev: stdev}))
|
||||||
let normalDist10: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 10.0, stdev: 2.0}))
|
let normalDist5: GenericDist_Types.genericDist = mkNormal(5.0, 2.0)
|
||||||
let normalDist20: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 20.0, stdev: 2.0}))
|
let normalDist10: GenericDist_Types.genericDist = mkNormal(10.0, 2.0)
|
||||||
|
let normalDist20: GenericDist_Types.genericDist = mkNormal(20.0, 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}))
|
||||||
|
|
||||||
let {toFloat, toDist, toString, toError} = module(DistributionOperation.Output)
|
let {toFloat, toDist, toString, toError} = module(DistributionOperation.Output)
|
||||||
|
@ -19,18 +23,99 @@ let outputMap = fmap(~env)
|
||||||
let toExt: option<'a> => 'a = E.O.toExt(
|
let toExt: option<'a> => 'a = E.O.toExt(
|
||||||
"Should be impossible to reach (This error is in test file)",
|
"Should be impossible to reach (This error is in test file)",
|
||||||
)
|
)
|
||||||
|
let unpackFloat = x => x -> toFloat -> toExt
|
||||||
|
|
||||||
describe("normalize", () => {
|
describe("normalize", () => {
|
||||||
test("has no impact on normal dist", () => {
|
test("has no impact on normal dist", () => {
|
||||||
let result = run(FromDist(ToDist(Normalize), normalDist5))
|
let result = run(FromDist(ToDist(Normalize), normalDist5))
|
||||||
expect(result)->toEqual(Dist(normalDist5))
|
expect(result)->toEqual(Dist(normalDist5))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Test is vapid while I figure out how to get jest to work with fast-check
|
||||||
|
// monitor situation here maybe https://github.com/TheSpyder/rescript-fast-check/issues/8 ?
|
||||||
|
test("all normals are already normalized", () => {
|
||||||
|
expect(assert_(
|
||||||
|
property2(
|
||||||
|
Arbitrary.double(()),
|
||||||
|
Arbitrary.double(()),
|
||||||
|
(mean, stdev) => {
|
||||||
|
// open! Expect.Operators
|
||||||
|
open GenericDist_Types.Operation
|
||||||
|
run(FromDist(ToDist(Normalize), mkNormal(mean, stdev))) == DistributionOperation.Dist(mkNormal(mean, stdev))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)) -> toEqual(())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("mean", () => {
|
describe("mean", () => {
|
||||||
test("for a normal distribution", () => {
|
test("of a normal distribution", () => { // should be property
|
||||||
let result = DistributionOperation.run(~env, FromDist(ToFloat(#Mean), normalDist5))
|
run(FromDist(ToFloat(#Mean), normalDist5)) -> unpackFloat -> expect -> toBeCloseTo(5.0)
|
||||||
expect(result)->toEqual(Float(5.0))
|
})
|
||||||
|
|
||||||
|
test("of an exponential distribution at a small rate", () => { // should be property
|
||||||
|
let rate = 1e-7
|
||||||
|
let theMean = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Exponential({rate: rate}))))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo(1.0 /. rate) // https://en.wikipedia.org/wiki/Exponential_distribution#Mean,_variance,_moments,_and_median
|
||||||
|
})
|
||||||
|
|
||||||
|
test("of an exponential distribution at a larger rate", () => {
|
||||||
|
let rate = 10.0
|
||||||
|
let theMean = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Exponential({rate: rate}))))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo(1.0 /. rate) // https://en.wikipedia.org/wiki/Exponential_distribution#Mean,_variance,_moments,_and_median
|
||||||
|
})
|
||||||
|
|
||||||
|
// test("of a cauchy distribution", () => {
|
||||||
|
// let result = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Cauchy({local: 1.0, scale: 1.0}))))
|
||||||
|
// expect(result) -> toEqual(Error("Cauchy distributions may have no mean value."))
|
||||||
|
// })
|
||||||
|
|
||||||
|
test("of a triangular distribution", () => { // should be property
|
||||||
|
let theMean = run(FromDist(
|
||||||
|
ToFloat(#Mean),
|
||||||
|
GenericDist_Types.Symbolic(#Triangular({low: - 5.0, medium: 1e-3, high: 10.0}))
|
||||||
|
))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo((-5.0 +. 1e-3 +. 10.0) /. 3.0) // https://www.statology.org/triangular-distribution/
|
||||||
|
})
|
||||||
|
|
||||||
|
test("of a beta distribution with alpha much smaller than beta", () => { // should be property
|
||||||
|
let theMean = run(FromDist(
|
||||||
|
ToFloat(#Mean),
|
||||||
|
GenericDist_Types.Symbolic(#Beta({alpha: 2e-4, beta: 64.0}))
|
||||||
|
))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo(1.0 /. (1.0 +. (64.0 /. 2e-4))) // https://en.wikipedia.org/wiki/Beta_distribution#Mean
|
||||||
|
})
|
||||||
|
|
||||||
|
test("of a beta distribution with alpha much larger than beta", () => { // should be property
|
||||||
|
let theMean = run(FromDist(
|
||||||
|
ToFloat(#Mean),
|
||||||
|
GenericDist_Types.Symbolic(#Beta({alpha: 128.0, beta: 1.0}))
|
||||||
|
))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo(1.0 /. (1.0 +. (1.0 /. 128.0))) // https://en.wikipedia.org/wiki/Beta_distribution#Mean
|
||||||
|
})
|
||||||
|
|
||||||
|
test("of a lognormal", () => { // should be property
|
||||||
|
let theMean = run(FromDist(
|
||||||
|
ToFloat(#Mean),
|
||||||
|
GenericDist_Types.Symbolic(#Lognormal({mu: 2.0, sigma: 4.0}))
|
||||||
|
))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo(Js.Math.exp(2.0 +. 4.0 ** 2.0 /. 2.0 )) // https://brilliant.org/wiki/log-normal-distribution/
|
||||||
|
})
|
||||||
|
|
||||||
|
test("of a uniform", () => {
|
||||||
|
let theMean = run(FromDist(
|
||||||
|
ToFloat(#Mean),
|
||||||
|
GenericDist_Types.Symbolic(#Uniform({low: 1e-5, high: 12.345}))
|
||||||
|
))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo((1e-5 +. 12.345) /. 2.0) // https://en.wikipedia.org/wiki/Continuous_uniform_distribution#Moments
|
||||||
|
})
|
||||||
|
|
||||||
|
test("of a float", () => {
|
||||||
|
let theMean = run(FromDist(
|
||||||
|
ToFloat(#Mean),
|
||||||
|
GenericDist_Types.Symbolic(#Float(7.7))
|
||||||
|
))
|
||||||
|
theMean -> unpackFloat -> expect -> toBeCloseTo(7.7)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
"rationale",
|
"rationale",
|
||||||
"bisect_ppx"
|
"bisect_ppx"
|
||||||
],
|
],
|
||||||
|
"bs-dev-dependencies": [
|
||||||
|
"rescript-fast-check"
|
||||||
|
],
|
||||||
"gentypeconfig": {
|
"gentypeconfig": {
|
||||||
"language": "typescript",
|
"language": "typescript",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
"docsify": "^4.12.2",
|
"docsify": "^4.12.2",
|
||||||
"gentype": "^4.3.0",
|
"gentype": "^4.3.0",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
|
"rescript-fast-check": "^1.1.1",
|
||||||
"moduleserve": "0.9.1",
|
"moduleserve": "0.9.1",
|
||||||
"ts-jest": "^27.1.4",
|
"ts-jest": "^27.1.4",
|
||||||
"ts-loader": "^9.2.8",
|
"ts-loader": "^9.2.8",
|
||||||
|
|
|
@ -55,7 +55,7 @@ module Exponential = {
|
||||||
rate: rate,
|
rate: rate,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
: Error("Exponential distributions mean must be larger than 0")
|
: Error("Exponential distributions rate must be larger than 0.")
|
||||||
let pdf = (x, t: t) => Jstat.Exponential.pdf(x, t.rate)
|
let pdf = (x, t: t) => Jstat.Exponential.pdf(x, t.rate)
|
||||||
let cdf = (x, t: t) => Jstat.Exponential.cdf(x, t.rate)
|
let cdf = (x, t: t) => Jstat.Exponential.cdf(x, t.rate)
|
||||||
let inv = (p, t: t) => Jstat.Exponential.inv(p, t.rate)
|
let inv = (p, t: t) => Jstat.Exponential.inv(p, t.rate)
|
||||||
|
@ -71,7 +71,7 @@ module Cauchy = {
|
||||||
let cdf = (x, t: t) => Jstat.Cauchy.cdf(x, t.local, t.scale)
|
let cdf = (x, t: t) => Jstat.Cauchy.cdf(x, t.local, t.scale)
|
||||||
let inv = (p, t: t) => Jstat.Cauchy.inv(p, t.local, t.scale)
|
let inv = (p, t: t) => Jstat.Cauchy.inv(p, t.local, t.scale)
|
||||||
let sample = (t: t) => Jstat.Cauchy.sample(t.local, t.scale)
|
let sample = (t: t) => Jstat.Cauchy.sample(t.local, t.scale)
|
||||||
let mean = (_: t) => Error("Cauchy distributions have no mean value.")
|
let mean = (_: t) => Error("Cauchy distributions may have no mean value.")
|
||||||
let toString = ({local, scale}: t) => j`Cauchy($local, $scale)`
|
let toString = ({local, scale}: t) => j`Cauchy($local, $scale)`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +80,8 @@ module Triangular = {
|
||||||
let make = (low, medium, high): result<symbolicDist, string> =>
|
let make = (low, medium, high): result<symbolicDist, string> =>
|
||||||
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)
|
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)
|
||||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -8392,6 +8392,13 @@ extglob@^2.0.4:
|
||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
|
fast-check@^2.17.0:
|
||||||
|
version "2.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.24.0.tgz#39f85586862108a4de6394c5196ebcf8b76b6c8b"
|
||||||
|
integrity sha512-iNXbN90lbabaCUfnW5jyXYPwMJLFYl09eJDkXA9ZoidFlBK63gNRvcKxv+8D1OJ1kIYjwBef4bO/K3qesUeWLQ==
|
||||||
|
dependencies:
|
||||||
|
pure-rand "^5.0.1"
|
||||||
|
|
||||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3, fast-deep-equal@~3.1.3:
|
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3, fast-deep-equal@~3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
||||||
|
@ -13524,6 +13531,11 @@ pure-color@^1.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
||||||
integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=
|
integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=
|
||||||
|
|
||||||
|
pure-rand@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-5.0.1.tgz#97a287b4b4960b2a3448c0932bf28f2405cac51d"
|
||||||
|
integrity sha512-ksWccjmXOHU2gJBnH0cK1lSYdvSZ0zLoCMSz/nTGh6hDvCSgcRxDyIcOBD6KNxFz3xhMPm/T267Tbe2JRymKEQ==
|
||||||
|
|
||||||
q@^1.1.2:
|
q@^1.1.2:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||||
|
@ -14712,6 +14724,13 @@ requires-port@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
|
rescript-fast-check@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/rescript-fast-check/-/rescript-fast-check-1.1.1.tgz#ef153cb01254b2f01a738faf85b73327d423d5e1"
|
||||||
|
integrity sha512-wxeW0TsL/prkRvEYGbhEiLaLKmYJaECyDcKEWh65hDqP2i76lARzVW3QmYujSYK4OnjAC70dln3X6UC/2m2Huw==
|
||||||
|
dependencies:
|
||||||
|
fast-check "^2.17.0"
|
||||||
|
|
||||||
rescript@^9.1.4:
|
rescript@^9.1.4:
|
||||||
version "9.1.4"
|
version "9.1.4"
|
||||||
resolved "https://registry.npmjs.org/rescript/-/rescript-9.1.4.tgz"
|
resolved "https://registry.npmjs.org/rescript/-/rescript-9.1.4.tgz"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user