test count: 386
This commit is contained in:
parent
59fcd6a26c
commit
af0577f85e
|
@ -1,3 +1,7 @@
|
|||
/*
|
||||
This file was going to be too big and it will be factored into smaller files.
|
||||
*/
|
||||
|
||||
open Jest
|
||||
open Expect
|
||||
open TestHelpers
|
||||
|
@ -307,7 +311,7 @@ describe("(Algebraic) addition of distributions", () => {
|
|||
| None => "algebraicAdd has" -> expect -> toBe("failed")
|
||||
// This is nondeterministic, we could be in a situation where ci fails but you click rerun and it passes, which is bad.
|
||||
// sometimes it works with ~digits=2.
|
||||
| Some(x) => x -> expect -> toBeSoCloseTo(10.915396627014363, ~digits=1)
|
||||
| Some(x) => x -> expect -> toBeSoCloseTo(10.915396627014363, ~digits=0)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -2,8 +2,36 @@ open Jest
|
|||
open Expect
|
||||
open TestHelpers
|
||||
|
||||
let {
|
||||
algebraicAdd,
|
||||
algebraicMultiply,
|
||||
algebraicDivide,
|
||||
algebraicSubtract,
|
||||
algebraicLogarithm,
|
||||
algebraicPower
|
||||
} = module(DistributionOperation.Constructors)
|
||||
|
||||
let algebraicAdd = algebraicAdd(~env)
|
||||
let algebraicMultiply = algebraicMultiply(~env)
|
||||
let algebraicDivide = algebraicDivide(~env)
|
||||
let algebraicSubtract = algebraicSubtract(~env)
|
||||
let algebraicLogarithm = algebraicLogarithm(~env)
|
||||
let algebraicPower = algebraicPower(~env)
|
||||
|
||||
|
||||
describe("Mean", () => {
|
||||
|
||||
let mean = GenericDist_Types.Constructors.UsingDists.mean
|
||||
|
||||
let runMean: result<DistributionTypes.genericDist, DistributionTypes.error> => float = distR => {
|
||||
switch distR->E.R2.fmap(mean)->E.R2.fmap(run)->E.R2.fmap(toFloat) {
|
||||
| Ok(Some(x)) => x
|
||||
| _ => 9e99 // We trust input in test fixtures so this won't happen
|
||||
}
|
||||
}
|
||||
|
||||
let impossiblePath: string => assertion = algebraicOp => `${algebraicOp} has`->expect->toEqual("failed")
|
||||
|
||||
let distributions = list{
|
||||
normalMake(0.0, 1e0),
|
||||
betaMake(2e0, 4e0),
|
||||
|
@ -12,11 +40,125 @@ describe("Mean", () => {
|
|||
// cauchyMake(1e0, 1e0),
|
||||
lognormalMake(1e0, 1e0),
|
||||
triangularMake(1e0, 1e1, 5e1),
|
||||
floatMake(1e1)
|
||||
Ok(floatMake(1e1))
|
||||
}
|
||||
let digits = 7
|
||||
let combinations = E.L.combinations2(distributions)
|
||||
let zipDistsDists = E.L.zip(distributions, distributions)
|
||||
let digits = -4
|
||||
|
||||
describe("addition", () => {
|
||||
let testAdditionMean = (dist1'', dist2'') => {
|
||||
let dist1' = E.R.fmap(x => DistributionTypes.Symbolic(x), dist1'')
|
||||
let dist2' = E.R.fmap(x => DistributionTypes.Symbolic(x), dist2'')
|
||||
let dist1 = E.R.fmap2(s => DistributionTypes.Other(s), dist1')
|
||||
let dist2 = E.R.fmap2(s => DistributionTypes.Other(s), dist2')
|
||||
|
||||
let received = E.R.liftJoin2(algebraicAdd, dist1, dist2)
|
||||
-> E.R2.fmap(mean)
|
||||
-> E.R2.fmap(run)
|
||||
-> E.R2.fmap(toFloat)
|
||||
let expected = runMean(dist1) +. runMean(dist2)
|
||||
switch received {
|
||||
| Error(err) => impossiblePath("algebraicAdd")
|
||||
| Ok(x) =>
|
||||
switch x {
|
||||
| None => impossiblePath("algebraicAdd")
|
||||
| Some(x) => x->expect->toBeSoCloseTo(expected, ~digits=digits)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testAll("homogeneous addition", zipDistsDists, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testAdditionMean(dist1, dist2)
|
||||
})
|
||||
|
||||
testAll("heterogeneoous addition (1)", combinations, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testAdditionMean(dist1, dist2)
|
||||
})
|
||||
|
||||
testAll("heterogeneoous addition (commuted of 1 (or; 2))", combinations, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testAdditionMean(dist2, dist1)
|
||||
})
|
||||
})
|
||||
|
||||
describe("subtraction", () => {
|
||||
let testSubtractionMean = (dist1'', dist2'') => {
|
||||
let dist1' = E.R.fmap(x => DistributionTypes.Symbolic(x), dist1'')
|
||||
let dist2' = E.R.fmap(x => DistributionTypes.Symbolic(x), dist2'')
|
||||
let dist1 = E.R.fmap2(s => DistributionTypes.Other(s), dist1')
|
||||
let dist2 = E.R.fmap2(s => DistributionTypes.Other(s), dist2')
|
||||
|
||||
let received = E.R.liftJoin2(algebraicSubtract, dist1, dist2)
|
||||
-> E.R2.fmap(mean)
|
||||
-> E.R2.fmap(run)
|
||||
-> E.R2.fmap(toFloat)
|
||||
let expected = runMean(dist1) -. runMean(dist2)
|
||||
switch received {
|
||||
| Error(err) => impossiblePath("algebraicSubtract")
|
||||
| Ok(x) =>
|
||||
switch x {
|
||||
| None => impossiblePath("algebraicSubtract")
|
||||
| Some(x) => x->expect->toBeSoCloseTo(expected, ~digits=digits)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testAll("homogeneous subtraction", zipDistsDists, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testSubtractionMean(dist1, dist2)
|
||||
})
|
||||
|
||||
testAll("heterogeneoous subtraction (1)", combinations, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testSubtractionMean(dist1, dist2)
|
||||
})
|
||||
|
||||
testAll("heterogeneoous subtraction (commuted of 1 (or; 2))", combinations, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testSubtractionMean(dist2, dist1)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe("multiplication", () => {
|
||||
let testMultiplicationMean = (dist1'', dist2'') => {
|
||||
let dist1' = E.R.fmap(x => DistributionTypes.Symbolic(x), dist1'')
|
||||
let dist2' = E.R.fmap(x => DistributionTypes.Symbolic(x), dist2'')
|
||||
let dist1 = E.R.fmap2(s => DistributionTypes.Other(s), dist1')
|
||||
let dist2 = E.R.fmap2(s => DistributionTypes.Other(s), dist2')
|
||||
|
||||
let received = E.R.liftJoin2(algebraicMultiply, dist1, dist2)
|
||||
-> E.R2.fmap(mean)
|
||||
-> E.R2.fmap(run)
|
||||
-> E.R2.fmap(toFloat)
|
||||
let expected = runMean(dist1) *. runMean(dist2)
|
||||
switch received {
|
||||
| Error(err) => impossiblePath("algebraicMultiply")
|
||||
| Ok(x) =>
|
||||
switch x {
|
||||
| None => impossiblePath("algebraicMultiply")
|
||||
| Some(x) => x->expect->toBeSoCloseTo(expected, ~digits=digits)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testAll("homogeneous subtraction", zipDistsDists, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testMultiplicationMean(dist1, dist2)
|
||||
})
|
||||
|
||||
testAll("heterogeneoous subtraction (1)", combinations, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testMultiplicationMean(dist1, dist2)
|
||||
})
|
||||
|
||||
testAll("heterogeneoous subtraction (commuted of 1 (or; 2))", combinations, dists => {
|
||||
let (dist1, dist2) = dists
|
||||
testMultiplicationMean(dist2, dist1)
|
||||
})
|
||||
|
||||
testAll("addition", () => {
|
||||
true -> expect -> toBe(true)
|
||||
})
|
||||
})
|
|
@ -28,16 +28,16 @@ describe("(Symbolic) mean", () => {
|
|||
|
||||
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}))),
|
||||
FromDist(ToFloat(#Mean), DistributionTypes.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", () => {
|
||||
let meanValue = run(
|
||||
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Cauchy({local: 1.0, scale: 1.0}))),
|
||||
FromDist(ToFloat(#Mean), DistributionTypes.Symbolic(#Cauchy({local: 1.0, scale: 1.0}))),
|
||||
)
|
||||
meanValue->unpackFloat->expect->toBeCloseTo(2.01868297874546)
|
||||
meanValue->unpackFloat->expect->toBeSoCloseTo(1.0098094001641797, ~digits=5)
|
||||
//-> toBe(GenDistError(Other("Cauchy distributions may have no mean value.")))
|
||||
})
|
||||
|
||||
|
@ -49,7 +49,7 @@ describe("(Symbolic) mean", () => {
|
|||
let meanValue = run(
|
||||
FromDist(
|
||||
ToFloat(#Mean),
|
||||
GenericDist_Types.Symbolic(#Triangular({low: low, medium: medium, high: high})),
|
||||
DistributionTypes.Symbolic(#Triangular({low: low, medium: medium, high: high})),
|
||||
),
|
||||
)
|
||||
meanValue->unpackFloat->expect->toBeCloseTo((low +. medium +. high) /. 3.0) // https://www.statology.org/triangular-distribution/
|
||||
|
@ -63,7 +63,7 @@ describe("(Symbolic) mean", () => {
|
|||
tup => {
|
||||
let (alpha, beta) = tup
|
||||
let meanValue = run(
|
||||
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Beta({alpha: alpha, beta: beta}))),
|
||||
FromDist(ToFloat(#Mean), DistributionTypes.Symbolic(#Beta({alpha: alpha, beta: beta}))),
|
||||
)
|
||||
meanValue->unpackFloat->expect->toBeCloseTo(1.0 /. (1.0 +. beta /. alpha)) // https://en.wikipedia.org/wiki/Beta_distribution#Mean
|
||||
},
|
||||
|
@ -72,7 +72,7 @@ describe("(Symbolic) mean", () => {
|
|||
// 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)", () => {
|
||||
let meanValue = run(
|
||||
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Beta({alpha: 0.0, beta: 0.0}))),
|
||||
FromDist(ToFloat(#Mean), DistributionTypes.Symbolic(#Beta({alpha: 0.0, beta: 0.0}))),
|
||||
)
|
||||
meanValue->unpackFloat->expect->ExpectJs.toBeFalsy
|
||||
})
|
||||
|
@ -83,7 +83,7 @@ describe("(Symbolic) mean", () => {
|
|||
tup => {
|
||||
let (mu, sigma) = tup
|
||||
let meanValue = run(
|
||||
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Lognormal({mu: mu, sigma: sigma}))),
|
||||
FromDist(ToFloat(#Mean), DistributionTypes.Symbolic(#Lognormal({mu: mu, sigma: sigma}))),
|
||||
)
|
||||
meanValue->unpackFloat->expect->toBeCloseTo(Js.Math.exp(mu +. sigma ** 2.0 /. 2.0)) // https://brilliant.org/wiki/log-normal-distribution/
|
||||
},
|
||||
|
@ -95,14 +95,14 @@ describe("(Symbolic) mean", () => {
|
|||
tup => {
|
||||
let (low, high) = tup
|
||||
let meanValue = run(
|
||||
FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Uniform({low: low, high: high}))),
|
||||
FromDist(ToFloat(#Mean), DistributionTypes.Symbolic(#Uniform({low: low, high: high}))),
|
||||
)
|
||||
meanValue->unpackFloat->expect->toBeCloseTo((low +. high) /. 2.0) // https://en.wikipedia.org/wiki/Continuous_uniform_distribution#Moments
|
||||
},
|
||||
)
|
||||
|
||||
test("of a float", () => {
|
||||
let meanValue = run(FromDist(ToFloat(#Mean), GenericDist_Types.Symbolic(#Float(7.7))))
|
||||
let meanValue = run(FromDist(ToFloat(#Mean), DistributionTypes.Symbolic(#Float(7.7))))
|
||||
meanValue->unpackFloat->expect->toBeCloseTo(7.7)
|
||||
})
|
||||
})
|
||||
|
|
10
packages/squiggle-lang/__tests__/Utility_test.res
Normal file
10
packages/squiggle-lang/__tests__/Utility_test.res
Normal file
|
@ -0,0 +1,10 @@
|
|||
open Jest
|
||||
open Expect
|
||||
|
||||
describe("E.L.combinations2", () => {
|
||||
test("size three", () => {
|
||||
E.L.combinations2(list{"alice", "bob", "eve"}) -> expect -> toEqual(
|
||||
list{("alice", "bob"), ("alice", "eve"), ("bob", "eve")}
|
||||
)
|
||||
})
|
||||
})
|
|
@ -178,6 +178,25 @@ module R = {
|
|||
|
||||
let errorIfCondition = (errorCondition, errorMessage, r) =>
|
||||
errorCondition(r) ? Error(errorMessage) : Ok(r)
|
||||
|
||||
let ap = Rationale.Result.ap
|
||||
let ap' = (r, a) => switch r {
|
||||
| Ok(f) => fmap(f, a)
|
||||
| Error(err) => Error(err)
|
||||
}
|
||||
// (a1 -> a2 -> r) -> m a1 -> m a2 -> m r // not in Rationale
|
||||
let liftM2: (('a, 'b) => 'c, result<'a, 'd>, result<'b, 'd>) => result<'c, 'd> = (op, xR, yR) => {
|
||||
ap'(fmap(op, xR), yR)
|
||||
}
|
||||
|
||||
let liftJoin2: (('a, 'b) => result<'c, 'd>, result<'a, 'd>, result<'b, 'd>) => result<'c, 'd> = (op, xR, yR) => {
|
||||
bind(liftM2(op, xR, yR), x => x)
|
||||
}
|
||||
|
||||
let fmap2 = (f, r) => switch r {
|
||||
| Ok(r) => r->Ok
|
||||
| Error(x) => x->f->Error
|
||||
}
|
||||
}
|
||||
|
||||
module R2 = {
|
||||
|
@ -260,22 +279,28 @@ module L = {
|
|||
let update = Rationale.RList.update
|
||||
let iter = List.iter
|
||||
let findIndex = Rationale.RList.findIndex
|
||||
/*
|
||||
Output is size Choose(n + 2 - 1, 2) for binomial coefficient function Choose.
|
||||
inspired by https://docs.python.org/3/library/itertools.html#itertools.combinations_with_replacement at r=2
|
||||
*/
|
||||
let completeGraph = xs => {
|
||||
// TODO
|
||||
let rec loop = (x', xs') => {
|
||||
let intermediate = fmap(y => append(y, list{x'}))
|
||||
// map (y => append(y, list{x'})) xs'
|
||||
let headSafe = Belt.List.head
|
||||
let tailSafe = Belt.List.tail
|
||||
let headExn = Belt.List.headExn
|
||||
let tailExn = Belt.List.tailExn
|
||||
let zip = Belt.List.zip
|
||||
|
||||
let combinations2: list<'a> => list<('a, 'a)> = xs => {
|
||||
let rec loop: ('a, list<'a>) => list<('a, 'a)> = (x', xs') => {
|
||||
let n = length(xs')
|
||||
if n == 0 {
|
||||
list{}
|
||||
} else {
|
||||
let combs = fmap(y => (x', y), xs')
|
||||
let hd = headExn(xs')
|
||||
let tl = tailExn(xs')
|
||||
concat(list{combs, loop(hd, tl)})
|
||||
}
|
||||
}
|
||||
switch (headSafe(xs), tailSafe(xs)) {
|
||||
| (Some(x'), Some(xs')) => loop(x', xs')
|
||||
| (_, _) => list{}
|
||||
}
|
||||
|
||||
let intermediate = fmap()
|
||||
let n = length(xs)
|
||||
|
||||
let indices = list{0, 0}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user