Added symbolic functions and tests for reducer interface distribution code
This commit is contained in:
parent
28eba9fa74
commit
18d742b63c
|
@ -0,0 +1,26 @@
|
||||||
|
open Jest
|
||||||
|
open Reducer_TestHelpers
|
||||||
|
|
||||||
|
let makeTest = (str, result) => test(str, () => expectEvalToBe(str, result))
|
||||||
|
|
||||||
|
describe("eval", () => {
|
||||||
|
Only.describe("expressions", () => {
|
||||||
|
makeTest("normal(5,2)", "Ok(Normal(5,2))")
|
||||||
|
makeTest("lognormal(5,2)", "Ok(Lognormal(5,2))")
|
||||||
|
makeTest("mean(normal(5,2))", "Ok(5)")
|
||||||
|
makeTest("mean(lognormal(1,2))", "Ok(20.085536923187668)")
|
||||||
|
makeTest("normalize(normal(5,2))", "Ok(Normal(5,2))")
|
||||||
|
makeTest("toPointSet(normal(5,2))", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("toSampleSet(normal(5,2), 100)", "Ok(Sample Set Distribution)")
|
||||||
|
makeTest("add(normal(5,2), normal(10,2))", "Ok(Normal(15,2.8284271247461903))")
|
||||||
|
makeTest("add(normal(5,2), lognormal(10,2))", "Ok(Sample Set Distribution)")
|
||||||
|
makeTest("dotAdd(normal(5,2), lognormal(10,2))", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("dotAdd(normal(5,2), 3)", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("add(normal(5,2), 3)", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("add(3, normal(5,2))", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("3+normal(5,2)", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("add(3, 3)", "Ok(6)")
|
||||||
|
makeTest("truncateLeft(normal(5,2), 3)", "Ok(Point Set Distribution)")
|
||||||
|
makeTest("mean(add(3, normal(5,2)))", "Ok(8.004619792609384)")
|
||||||
|
})
|
||||||
|
})
|
|
@ -74,11 +74,54 @@ let genericOutputToReducerValue = (o: GenericDist_GenericOperation.outputType):
|
||||||
| GenDistError(Other(s)) => Error(RETodo(s))
|
| GenDistError(Other(s)) => Error(RETodo(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module SymbolicConstructor = {
|
||||||
|
let oneFloat = name =>
|
||||||
|
switch name {
|
||||||
|
| "exponential" => Ok(SymbolicDist.Exponential.make)
|
||||||
|
| _ => Error("impossible path")
|
||||||
|
}
|
||||||
|
|
||||||
|
let twoFloat = name =>
|
||||||
|
switch name {
|
||||||
|
| "normal" => Ok(SymbolicDist.Normal.make)
|
||||||
|
| "uniform" => Ok(SymbolicDist.Uniform.make)
|
||||||
|
| "beta" => Ok(SymbolicDist.Beta.make)
|
||||||
|
| "lognormal" => Ok(SymbolicDist.Lognormal.make)
|
||||||
|
| _ => Error("impossible path")
|
||||||
|
}
|
||||||
|
|
||||||
|
let threeFloat = name =>
|
||||||
|
switch name {
|
||||||
|
| "triangular" => Ok(SymbolicDist.Triangular.make)
|
||||||
|
| _ => Error("impossible path")
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbolicResultToOutput = (
|
||||||
|
symbolicResult: result<SymbolicDistTypes.symbolicDist, string>,
|
||||||
|
): option<GenericDist_GenericOperation.outputType> =>
|
||||||
|
switch symbolicResult {
|
||||||
|
| Ok(r) => Some(Dist(Symbolic(r)))
|
||||||
|
| Error(r) => Some(GenDistError(Other(r)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
|
let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
|
||||||
GenericDist_GenericOperation.outputType,
|
GenericDist_GenericOperation.outputType,
|
||||||
> => {
|
> => {
|
||||||
let (fnName, args) = call
|
let (fnName, args) = call
|
||||||
switch (fnName, args) {
|
switch (fnName, args) {
|
||||||
|
| ("exponential" as fnName, [EvNumber(f1)]) =>
|
||||||
|
SymbolicConstructor.oneFloat(fnName)
|
||||||
|
->E.R.bind(r => r(f1))
|
||||||
|
->SymbolicConstructor.symbolicResultToOutput
|
||||||
|
| (("normal" | "uniform" | "beta" | "lognormal") as fnName, [EvNumber(f1), EvNumber(f2)]) =>
|
||||||
|
SymbolicConstructor.twoFloat(fnName)
|
||||||
|
->E.R.bind(r => r(f1, f2))
|
||||||
|
->SymbolicConstructor.symbolicResultToOutput
|
||||||
|
| ("triangular" as fnName, [EvNumber(f1), EvNumber(f2), EvNumber(f3)]) =>
|
||||||
|
SymbolicConstructor.threeFloat(fnName)
|
||||||
|
->E.R.bind(r => r(f1, f2, f3))
|
||||||
|
->SymbolicConstructor.symbolicResultToOutput
|
||||||
| ("sample", [EvDistribution(dist)]) => toFloatFn(#Sample, dist)
|
| ("sample", [EvDistribution(dist)]) => toFloatFn(#Sample, dist)
|
||||||
| ("mean", [EvDistribution(dist)]) => toFloatFn(#Mean, dist)
|
| ("mean", [EvDistribution(dist)]) => toFloatFn(#Mean, dist)
|
||||||
| ("normalize", [EvDistribution(dist)]) => toDistFn(Normalize, dist)
|
| ("normalize", [EvDistribution(dist)]) => toDistFn(Normalize, dist)
|
||||||
|
@ -88,20 +131,21 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
|
||||||
| ("inv", [EvDistribution(dist), EvNumber(float)]) => toFloatFn(#Inv(float), dist)
|
| ("inv", [EvDistribution(dist), EvNumber(float)]) => toFloatFn(#Inv(float), dist)
|
||||||
| ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) =>
|
||||||
toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist)
|
toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist)
|
||||||
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) => toDistFn(Truncate(Some(float), None), dist)
|
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) =>
|
||||||
|
toDistFn(Truncate(Some(float), None), dist)
|
||||||
| ("truncateRight", [EvDistribution(dist), EvNumber(float)]) =>
|
| ("truncateRight", [EvDistribution(dist), EvNumber(float)]) =>
|
||||||
toDistFn(Truncate(None, Some(float)), dist)
|
toDistFn(Truncate(None, Some(float)), dist)
|
||||||
| ("truncate", [EvDistribution(dist), EvNumber(float1), EvNumber(float2)]) =>
|
| ("truncate", [EvDistribution(dist), EvNumber(float1), EvNumber(float2)]) =>
|
||||||
toDistFn(Truncate(Some(float1), Some(float2)), dist)
|
toDistFn(Truncate(Some(float1), Some(float2)), dist)
|
||||||
| (("add" | "multiply" | "subtract" | "divide" | "exponentiate") as arithmetic, [a, b] as args) =>
|
| (("add" | "multiply" | "subtract" | "divide" | "exponentiate") as arithmetic, [a, b] as args) =>
|
||||||
catchAndConvertTwoArgsToDists(args) -> E.O2.fmap(((fst, snd)) =>
|
catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||||
twoDiststoDistFn(Algebraic, arithmetic, fst, snd)
|
twoDiststoDistFn(Algebraic, arithmetic, fst, snd)
|
||||||
)
|
)
|
||||||
| (
|
| (
|
||||||
("dotAdd" | "dotMultiply" | "dotSubtract" | "dotDivide" | "dotExponentiate") as arithmetic,
|
("dotAdd" | "dotMultiply" | "dotSubtract" | "dotDivide" | "dotExponentiate") as arithmetic,
|
||||||
[a, b] as args,
|
[a, b] as args,
|
||||||
) =>
|
) =>
|
||||||
catchAndConvertTwoArgsToDists(args) -> E.O2.fmap(((fst, snd)) =>
|
catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||||
twoDiststoDistFn(Pointwise, arithmetic, fst, snd)
|
twoDiststoDistFn(Pointwise, arithmetic, fst, snd)
|
||||||
)
|
)
|
||||||
| _ => None
|
| _ => None
|
||||||
|
@ -109,5 +153,5 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatch = call => {
|
let dispatch = call => {
|
||||||
dispatchToGenericOutput(call) -> E.O2.fmap(genericOutputToReducerValue)
|
dispatchToGenericOutput(call)->E.O2.fmap(genericOutputToReducerValue)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user