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