Gradually adding more functions to Functions.re

This commit is contained in:
Ozzie Gooen 2020-08-10 22:06:31 +01:00
parent 5d7ffdf2bc
commit f3841a961c
5 changed files with 92 additions and 66 deletions

View File

@ -31,7 +31,7 @@ export class CodeEditor extends React.Component {
}}
setOptions={{
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
enableLiveAutocompletion: true,
enableSnippets: true,
}}
/>

View File

@ -95,26 +95,28 @@ module VerticalScaling = {
let operationToLeaf =
(evaluationParams: evaluationParams, scaleOp, t, scaleBy) => {
// scaleBy has to be a single float, otherwise we'll return an error.
let fn = (secondary,main) => Operation.Scale.toFn(scaleOp)(main, secondary);
let fn = (secondary, main) =>
Operation.Scale.toFn(scaleOp, main, secondary);
let integralSumCacheFn = Operation.Scale.toIntegralSumCacheFn(scaleOp);
let integralCacheFn = Operation.Scale.toIntegralCacheFn(scaleOp);
let renderedShape = Render.render(evaluationParams, t);
let s = switch (renderedShape, scaleBy) {
| (Ok(`RenderedDist(rs)), `SymbolicDist(`Float(scaleBy))) =>
Ok(
`RenderedDist(
Shape.T.mapY(
~integralSumCacheFn=integralSumCacheFn(scaleBy),
~integralCacheFn=integralCacheFn(scaleBy),
~fn=fn(scaleBy),
rs,
let s =
switch (renderedShape, scaleBy) {
| (Ok(`RenderedDist(rs)), `SymbolicDist(`Float(scaleBy))) =>
Ok(
`RenderedDist(
Shape.T.mapY(
~integralSumCacheFn=integralSumCacheFn(scaleBy),
~integralCacheFn=integralCacheFn(scaleBy),
~fn=fn(scaleBy),
rs,
),
),
),
)
| (Error(e1), _) => Error(e1)
| (_, _) => Error("Can only scale by float values.")
};
)
| (Error(e1), _) => Error(e1)
| (_, _) => Error("Can only scale by float values.")
};
s;
};
};
@ -265,9 +267,7 @@ module FloatFromDist = {
// TODO: This forces things to be floats
let callableFunction = (evaluationParams, name, args) => {
args
|> E.A.fmap(a =>
Render.render(evaluationParams, a) |> E.R.bind(_, Render.toFloat)
)
|> E.A.fmap(a => evaluationParams.evaluateNode(evaluationParams, a))
|> E.A.R.firstErrorOrOpen
|> E.R.bind(_, Functions.fnn(evaluationParams, name));
};
@ -299,11 +299,11 @@ module Render = {
This function is used mainly to turn a parse tree into a single RenderedDist
that can then be displayed to the user. */
let rec toLeaf =
(
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
node: t,
)
: result(t, string) => {
(
evaluationParams: ExpressionTypes.ExpressionTree.evaluationParams,
node: t,
)
: result(t, string) => {
switch (node) {
// Leaf nodes just stay leaf nodes
| `SymbolicDist(_)

View File

@ -31,6 +31,10 @@ module ExpressionTree = {
| `FunctionCall(string, array(node))
];
// Have nil as option
let getFloat = (node:node) => node |> fun
| `RenderedDist(Discrete({xyShape: {xs: [|x|], ys: [|1.0|]}})) => Some(x)
| `SymbolicDist(`Float(x)) => Some(x)
| _ => None
type samplingInputs = {
sampleCount: int,
@ -87,6 +91,7 @@ module ExpressionTree = {
|> evaluationParams.evaluateNode(evaluationParams)
|> E.R.bind(_, fn(evaluationParams));
module Render = {
type t = node;

View File

@ -1,21 +1,17 @@
type node = ExpressionTypes.ExpressionTree.node;
let toOkSym = r => Ok(`SymbolicDist(r));
let getFloat = ExpressionTypes.ExpressionTree.getFloat;
let twoFloats = (fn, n1: node, n2: node): result(node, string) =>
switch (n1, n2) {
| (`SymbolicDist(`Float(a)), `SymbolicDist(`Float(b))) => fn(a, b)
| _ => Error("Variables have wrong type")
switch (getFloat(n1), getFloat(n2)) {
| (Some(a), Some(b)) => fn(a, b)
| _ => Error("Function needed two floats, missing them.")
};
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)
switch (getFloat(n1), getFloat(n2), getFloat(n3)) {
| (Some(a), Some(b), Some(c)) => fn(a, b, c)
| _ => Error("Variables have wrong type")
};
@ -35,18 +31,15 @@ let apply3 = (fn, args: array(node)): result(node, string) =>
| _ => Error("Needs 3 args")
};
let to_: (float, float) => result(node, string) = (low, high) => switch(low,high){
| (low,high)
when low <= 0.0 && low < high => {
Ok(`SymbolicDist(SymbolicDist.Normal.from90PercentCI(low, high)));
}
| (low,high)
when low < high => {
Ok(`SymbolicDist(SymbolicDist.Lognormal.from90PercentCI(low, high)));
}
| (low,high) =>
Error("Low value must be less than high value.")
}
let to_: (float, float) => result(node, string) =
(low, high) =>
switch (low, high) {
| (low, high) when low <= 0.0 && low < high =>
Ok(`SymbolicDist(SymbolicDist.Normal.from90PercentCI(low, high)))
| (low, high) when low < high =>
Ok(`SymbolicDist(SymbolicDist.Lognormal.from90PercentCI(low, high)))
| (low, high) => Error("Low value must be less than high value.")
};
// Possible setup:
// let normal = {"inputs": [`float, `float], "outputs": [`float]};
@ -86,16 +79,57 @@ let fnn =
| _ => Error("Needs 3 valid arguments")
}
| ("triangular", _) =>
switch (args) {
| [|
`SymbolicDist(`Float(a)),
`SymbolicDist(`Float(b)),
`SymbolicDist(`Float(c)),
|] =>
switch (args |> E.A.fmap(getFloat)) {
| [|Some(a), Some(b), Some(c)|] =>
SymbolicDist.Triangular.make(a, b, c)
|> E.R.fmap(r => `SymbolicDist(r))
| _ => Error("Needs 3 valid arguments")
}
| ("to", _) => apply2(twoFloats(to_), args)
| ("pdf", _) => switch(args){
| [|fst,snd|] => {
switch(PTypes.SamplingDistribution.renderIfIsNotSamplingDistribution(evaluationParams,fst),getFloat(snd)){
| (Ok(fst), Some(flt)) => Ok(`FloatFromDist(`Pdf(flt), fst))
| _ => Error("Incorrect arguments")
}
}
| _ => Error("Needs two args")
}
| ("inv", _) => switch(args){
| [|fst,snd|] => {
switch(PTypes.SamplingDistribution.renderIfIsNotSamplingDistribution(evaluationParams,fst),getFloat(snd)){
| (Ok(fst), Some(flt)) => Ok(`FloatFromDist(`Inv(flt), fst))
| _ => Error("Incorrect arguments")
}
}
| _ => Error("Needs two args")
}
| ("cdf", _) => switch(args){
| [|fst,snd|] => {
switch(PTypes.SamplingDistribution.renderIfIsNotSamplingDistribution(evaluationParams,fst),getFloat(snd)){
| (Ok(fst), Some(flt)) => Ok(`FloatFromDist(`Cdf(flt), fst))
| _ => Error("Incorrect arguments")
}
}
| _ => Error("Needs two args")
}
| ("mean", _) => switch(args){
| [|fst|] => {
switch(PTypes.SamplingDistribution.renderIfIsNotSamplingDistribution(evaluationParams,fst)){
| (Ok(fst)) => Ok(`FloatFromDist(`Mean,fst))
| _ => Error("Incorrect arguments")
}
}
| _ => Error("Needs two args")
}
| ("sample", _) => switch(args){
| [|fst|] => {
switch(PTypes.SamplingDistribution.renderIfIsNotSamplingDistribution(evaluationParams,fst)){
| (Ok(fst)) => Ok(`FloatFromDist(`Sample,fst))
| _ => Error("Incorrect arguments")
}
}
| _ => Error("Needs two args")
}
| _ => Error("Function " ++ name ++ " not found")
};

View File

@ -236,14 +236,6 @@ module MathAdtToDistDst = {
)
| ("scaleLog", [|d, `SymbolicDist(`Float(v))|]) =>
Ok(`VerticalScaling((`Log, d, `SymbolicDist(`Float(v)))))
| ("pdf", [|d, `SymbolicDist(`Float(v))|]) =>
toOkFloatFromDist((`Pdf(v), d))
| ("cdf", [|d, `SymbolicDist(`Float(v))|]) =>
toOkFloatFromDist((`Cdf(v), d))
| ("inv", [|d, `SymbolicDist(`Float(v))|]) =>
toOkFloatFromDist((`Inv(v), d))
| ("mean", [|d|]) => toOkFloatFromDist((`Mean, d))
| ("sample", [|d|]) => toOkFloatFromDist((`Sample, d))
| _ => Error("This type not currently supported")
}
});
@ -294,12 +286,7 @@ module MathAdtToDistDst = {
| "scaleMultiply"
| "scaleExp"
| "scaleLog"
| "truncate"
| "mean"
| "inv"
| "sample"
| "cdf"
| "pdf" => operationParser(name, parseArgs())
| "truncate" => operationParser(name, parseArgs())
| name =>
parseArgs()
|> E.R.fmap((args: array(ExpressionTypes.ExpressionTree.node)) =>