New functions use new syntax

This commit is contained in:
Ozzie Gooen 2020-07-30 13:54:35 +01:00
parent d3766f7a7f
commit 43704743af
4 changed files with 103 additions and 76 deletions

View File

@ -259,6 +259,7 @@ module FloatFromDist = {
}; };
}; };
// TODO: This forces things to be floats
let callableFunction = (evaluationParams, name, args) => { let callableFunction = (evaluationParams, name, args) => {
let b = let b =
args args
@ -267,7 +268,7 @@ let callableFunction = (evaluationParams, name, args) => {
|> E.R.bind(_, Render.toFloat) |> E.R.bind(_, Render.toFloat)
) )
|> E.A.R.firstErrorOrOpen; |> E.A.R.firstErrorOrOpen;
b |> E.R.bind(_, Functions.fnn("normal")); b |> E.R.bind(_, Functions.fnn(name));
}; };
module Render = { module Render = {

View File

@ -8,20 +8,75 @@ let twoFloats = (fn, n1: node, n2: node): result(node, string) =>
| _ => Error("Variables have wrong type") | _ => Error("Variables have wrong type")
}; };
let threeFloats = (fn, n1: node, n2: node, n3: node): result(node, string) =>
switch (n1, n2, n3) {
| (
`SymbolicDist(`Float(a)),
`SymbolicDist(`Float(b)),
`SymbolicDist(`Float(c)),
) =>
fn(a, b, c)
| _ => Error("Variables have wrong type")
};
let twoFloatsToOkSym = fn => twoFloats((f1, f2) => fn(f1, f2) |> toOkSym); let twoFloatsToOkSym = fn => twoFloats((f1, f2) => fn(f1, f2) |> toOkSym);
let threeFloats = fn => threeFloats((f1, f2, f3) => fn(f1, f2, f3));
let apply2 = (fn, args): result(node, string) => let apply2 = (fn, args): result(node, string) =>
switch (args) { switch (args) {
| [|a, b|] => fn(a, b) | [|a, b|] => fn(a, b)
| _ => Error("Needs 2 args") | _ => Error("Needs 2 args")
}; };
let apply3 = (fn, args: array(node)): result(node, string) =>
switch (args) {
| [|a, b, c|] => fn(a, b, c)
| _ => Error("Needs 3 args")
};
let to_: array(node) => result(node, string) =
fun
| [|`SymbolicDist(`Float(low)), `SymbolicDist(`Float(high))|]
when low <= 0.0 && low < high => {
Ok(`SymbolicDist(SymbolicDist.Normal.from90PercentCI(low, high)));
}
| [|`SymbolicDist(`Float(low)), `SymbolicDist(`Float(high))|]
when low < high => {
Ok(`SymbolicDist(SymbolicDist.Lognormal.from90PercentCI(low, high)));
}
| [|`SymbolicDist(`Float(_)), `SymbolicDist(_)|] =>
Error("Low value must be less than high value.")
| _ => Error("Requires 2 variables");
let fnn = (name, args: array(node)) => { let fnn = (name, args: array(node)) => {
switch (name) { switch (name) {
| "normal" => apply2(twoFloatsToOkSym(SymbolicDist.Normal.make), args) | "normal" => apply2(twoFloatsToOkSym(SymbolicDist.Normal.make), args)
| "uniform" => apply2(twoFloatsToOkSym(SymbolicDist.Uniform.make), args) | "uniform" => apply2(twoFloatsToOkSym(SymbolicDist.Uniform.make), args)
| "beta" => apply2(twoFloatsToOkSym(SymbolicDist.Beta.make), args) | "beta" => apply2(twoFloatsToOkSym(SymbolicDist.Beta.make), args)
| "cauchy" => apply2(twoFloatsToOkSym(SymbolicDist.Cauchy.make), args) | "cauchy" => apply2(twoFloatsToOkSym(SymbolicDist.Cauchy.make), args)
| "lognormal" => apply2(twoFloatsToOkSym(SymbolicDist.Lognormal.make), args)
| "lognormalFromMeanAndStdDev" => apply2(twoFloatsToOkSym(SymbolicDist.Lognormal.fromMeanAndStdev), args)
| "exponential" =>
switch (args) {
| [|
`SymbolicDist(`Float(a)),
|] =>
Ok(`SymbolicDist(SymbolicDist.Exponential.make(a)));
| _ => Error("Needs 3 valid arguments")
}
| "triangular" =>
switch (args) {
| [|
`SymbolicDist(`Float(a)),
`SymbolicDist(`Float(b)),
`SymbolicDist(`Float(c)),
|] =>
SymbolicDist.Triangular.make(a, b, c)
|> E.R.fmap(r => `SymbolicDist(r))
| _ => Error("Needs 3 valid arguments")
}
| "to" => to_(args)
| _ => Error("Function not found") | _ => Error("Function not found")
}; };
}; };

View File

@ -93,56 +93,26 @@ module MathAdtToDistDst = {
); );
}; };
let lognormal: let lognormal = (args, parseArgs, nodeParser) =>
array(arg) => result(ExpressionTypes.ExpressionTree.node, string) = switch (args) {
fun | [|Object(o)|] =>
| [|Value(mu), Value(sigma)|] => let g = s =>
Ok(`SymbolicDist(`Lognormal({mu, sigma}))) Js.Dict.get(o, s) |> E.O.toResult("") |> E.R.bind(_, nodeParser);
| [|Object(o)|] => {
let g = Js.Dict.get(o);
switch (g("mean"), g("stdev"), g("mu"), g("sigma")) { switch (g("mean"), g("stdev"), g("mu"), g("sigma")) {
| (Some(Value(mean)), Some(Value(stdev)), _, _) => | (Ok(mean), Ok(stdev), _, _) =>
Ok( Ok(
`SymbolicDist( `CallableFunction(("lognormalFromMeanAndStdDev", [|mean, stdev|])),
SymbolicDist.Lognormal.fromMeanAndStdev(mean, stdev), )
), | (_, _, Ok(mu), Ok(sigma)) =>
Ok(`CallableFunction(("lognormal", [|mu, sigma|])))
| _ => Error("Lognormal distribution needs either mean and stdev or mu and sigma")
};
| _ =>
parseArgs()
|> E.R.fmap((args: array(ExpressionTypes.ExpressionTree.node)) =>
`CallableFunction(("lognormal", args))
) )
| (_, _, Some(Value(mu)), Some(Value(sigma))) =>
Ok(`SymbolicDist(`Lognormal({mu, sigma})))
| _ => Error("Lognormal distribution would need mean and stdev")
}; };
}
| _ => Error("Wrong number of variables in lognormal distribution");
let to_: array(arg) => result(ExpressionTypes.ExpressionTree.node, string) =
fun
| [|Value(low), Value(high)|] when low <= 0.0 && low < high => {
Ok(`SymbolicDist(SymbolicDist.Normal.from90PercentCI(low, high)));
}
| [|Value(low), Value(high)|] when low < high => {
Ok(
`SymbolicDist(SymbolicDist.Lognormal.from90PercentCI(low, high)),
);
}
| [|Value(_), Value(_)|] =>
Error("Low value must be less than high value.")
| _ => Error("Wrong number of variables in lognormal distribution");
let exponential:
array(arg) => result(ExpressionTypes.ExpressionTree.node, string) =
fun
| [|Value(rate)|] => Ok(`SymbolicDist(`Exponential({rate: rate})))
| _ => Error("Wrong number of variables in Exponential distribution");
let triangular:
array(arg) => result(ExpressionTypes.ExpressionTree.node, string) =
fun
| [|Value(low), Value(medium), Value(high)|]
when low < medium && medium < high =>
Ok(`SymbolicDist(`Triangular({low, medium, high})))
| [|Value(_), Value(_), Value(_)|] =>
Error("Triangular values must be increasing order")
| _ => Error("Wrong number of variables in triangle distribution");
let multiModal = let multiModal =
( (
@ -150,15 +120,6 @@ module MathAdtToDistDst = {
weights: option(array(float)), weights: option(array(float)),
) => { ) => {
let weights = weights |> E.O.default([||]); let weights = weights |> E.O.default([||]);
/*let dists: =
args
|> E.A.fmap(
fun
| Ok(a) => a
| Error(e) => Error(e)
);*/
let firstWithError = args |> Belt.Array.getBy(_, Belt.Result.isError); let firstWithError = args |> Belt.Array.getBy(_, Belt.Result.isError);
let withoutErrors = args |> E.A.fmap(E.R.toOption) |> E.A.O.concatSomes; let withoutErrors = args |> E.A.fmap(E.R.toOption) |> E.A.O.concatSomes;
@ -249,17 +210,22 @@ module MathAdtToDistDst = {
}; };
let functionParser = (nodeParser, name, args) => { let functionParser = (nodeParser, name, args) => {
let parseArgs = () => let parseArray = ags =>
args |> E.A.fmap(nodeParser) |> E.A.R.firstErrorOrOpen; ags |> E.A.fmap(nodeParser) |> E.A.R.firstErrorOrOpen;
let parseArgs = () => parseArray(args);
switch (name) { switch (name) {
| "normal" | "uniform" | "beta" | "caucy" => | "normal"
| "uniform"
| "beta"
| "triangular"
| "to"
| "exponential"
| "cauchy" =>
parseArgs() parseArgs()
|> E.R.fmap( |> E.R.fmap((args: array(ExpressionTypes.ExpressionTree.node)) =>
(
args: array(ExpressionTypes.ExpressionTree.node),
) =>
`CallableFunction((name, args)) `CallableFunction((name, args))
) )
| "lognormal" => lognormal(args, parseArgs, nodeParser)
| "mm" => | "mm" =>
let weights = let weights =
args args

View File

@ -2,8 +2,12 @@ open SymbolicTypes;
module Exponential = { module Exponential = {
type t = exponential; type t = exponential;
let make = (rate): symbolicDist => let make = (rate:float): symbolicDist =>
`Exponential({rate}); `Exponential(
{
rate:rate
},
);
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);
@ -14,8 +18,7 @@ module Exponential = {
module Cauchy = { module Cauchy = {
type t = cauchy; type t = cauchy;
let make = (local, scale): symbolicDist => let make = (local, scale): symbolicDist => `Cauchy({local, scale});
`Cauchy({local,scale});
let pdf = (x, t: t) => Jstat.cauchy##pdf(x, t.local, t.scale); let pdf = (x, t: t) => Jstat.cauchy##pdf(x, t.local, t.scale);
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);
@ -26,8 +29,10 @@ module Cauchy = {
module Triangular = { module Triangular = {
type t = triangular; type t = triangular;
let make = (low, medium, high): symbolicDist => let make = (low, medium, high): result(symbolicDist, string) =>
`Triangular({low, medium, high}); low < medium && medium < high
? Ok(`Triangular({low, medium, high}))
: 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);
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);
@ -82,7 +87,7 @@ module Normal = {
module Beta = { module Beta = {
type t = beta; type t = beta;
let make = (alpha, beta) => `Beta({alpha, beta}) let make = (alpha, beta) => `Beta({alpha, beta});
let pdf = (x, t: t) => Jstat.beta##pdf(x, t.alpha, t.beta); let pdf = (x, t: t) => Jstat.beta##pdf(x, t.alpha, t.beta);
let cdf = (x, t: t) => Jstat.beta##cdf(x, t.alpha, t.beta); let cdf = (x, t: t) => Jstat.beta##cdf(x, t.alpha, t.beta);
let inv = (p, t: t) => Jstat.beta##inv(p, t.alpha, t.beta); let inv = (p, t: t) => Jstat.beta##inv(p, t.alpha, t.beta);
@ -93,7 +98,7 @@ module Beta = {
module Lognormal = { module Lognormal = {
type t = lognormal; type t = lognormal;
let make = (mu, sigma) => `Lognormal({mu, sigma}) let make = (mu, sigma) => `Lognormal({mu, sigma});
let pdf = (x, t: t) => Jstat.lognormal##pdf(x, t.mu, t.sigma); let pdf = (x, t: t) => Jstat.lognormal##pdf(x, t.mu, t.sigma);
let cdf = (x, t: t) => Jstat.lognormal##cdf(x, t.mu, t.sigma); let cdf = (x, t: t) => Jstat.lognormal##cdf(x, t.mu, t.sigma);
let inv = (p, t: t) => Jstat.lognormal##inv(p, t.mu, t.sigma); let inv = (p, t: t) => Jstat.lognormal##inv(p, t.mu, t.sigma);
@ -140,7 +145,7 @@ module Lognormal = {
module Uniform = { module Uniform = {
type t = uniform; type t = uniform;
let make = (low, high) => `Uniform({low, high}) let make = (low, high) => `Uniform({low, high});
let pdf = (x, t: t) => Jstat.uniform##pdf(x, t.low, t.high); let pdf = (x, t: t) => Jstat.uniform##pdf(x, t.low, t.high);
let cdf = (x, t: t) => Jstat.uniform##cdf(x, t.low, t.high); let cdf = (x, t: t) => Jstat.uniform##cdf(x, t.low, t.high);
let inv = (p, t: t) => Jstat.uniform##inv(p, t.low, t.high); let inv = (p, t: t) => Jstat.uniform##inv(p, t.low, t.high);
@ -156,7 +161,7 @@ module Uniform = {
module Float = { module Float = {
type t = float; type t = float;
let make = t => `Float(t) let make = t => `Float(t);
let pdf = (x, t: t) => x == t ? 1.0 : 0.0; let pdf = (x, t: t) => x == t ? 1.0 : 0.0;
let cdf = (x, t: t) => x >= t ? 1.0 : 0.0; let cdf = (x, t: t) => x >= t ? 1.0 : 0.0;
let inv = (p, t: t) => p < t ? 0.0 : 1.0; let inv = (p, t: t) => p < t ? 0.0 : 1.0;