Added back HardcodedFunctions.re
This commit is contained in:
parent
f955a9f642
commit
68ac17e872
258
src/distPlus/typeSystem/HardcodedFunctions.re
Normal file
258
src/distPlus/typeSystem/HardcodedFunctions.re
Normal file
|
@ -0,0 +1,258 @@
|
|||
open TypeSystem;
|
||||
|
||||
let wrongInputsError = (r: array(typedValue)) => {
|
||||
let inputs = r |> E.A.fmap(TypedValue.toString) |>Js.String.concatMany(_, ",");
|
||||
Js.log3("Inputs were", inputs, r);
|
||||
Error("Wrong inputs. The inputs were:" ++ inputs);
|
||||
};
|
||||
|
||||
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)))
|
||||
| (_, _) => Error("Low value must be less than high value.")
|
||||
};
|
||||
|
||||
let makeSymbolicFromTwoFloats = (name, fn) =>
|
||||
Function.T.make(
|
||||
~name,
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`Float, `Float|],
|
||||
~run=
|
||||
fun
|
||||
| [|`Float(a), `Float(b)|] => Ok(`SymbolicDist(fn(a, b)))
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
);
|
||||
|
||||
let makeSymbolicFromOneFloat = (name, fn) =>
|
||||
Function.T.make(
|
||||
~name,
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`Float|],
|
||||
~run=
|
||||
fun
|
||||
| [|`Float(a)|] => Ok(`SymbolicDist(fn(a)))
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
);
|
||||
|
||||
let makeDistFloat = (name, fn) =>
|
||||
Function.T.make(
|
||||
~name,
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`SamplingDistribution, `Float|],
|
||||
~run=
|
||||
fun
|
||||
| [|`SamplingDist(a), `Float(b)|] => fn(a, b)
|
||||
| [|`RenderedDist(a), `Float(b)|] => fn(`RenderedDist(a), b)
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
);
|
||||
|
||||
let makeRenderedDistFloat = (name, fn) =>
|
||||
Function.T.make(
|
||||
~name,
|
||||
~outputType=`RenderedDistribution,
|
||||
~inputTypes=[|`RenderedDistribution, `Float|],
|
||||
~shouldCoerceTypes=true,
|
||||
~run=
|
||||
fun
|
||||
| [|`RenderedDist(a), `Float(b)|] => fn(a, b)
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
);
|
||||
|
||||
let makeDist = (name, fn) =>
|
||||
Function.T.make(
|
||||
~name,
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`SamplingDistribution|],
|
||||
~run=
|
||||
fun
|
||||
| [|`SamplingDist(a)|] => fn(a)
|
||||
| [|`RenderedDist(a)|] => fn(`RenderedDist(a))
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
);
|
||||
|
||||
let floatFromDist =
|
||||
(
|
||||
distToFloatOp: ExpressionTypes.distToFloatOperation,
|
||||
t: TypeSystem.samplingDist,
|
||||
)
|
||||
: result(node, string) => {
|
||||
switch (t) {
|
||||
| `SymbolicDist(s) =>
|
||||
SymbolicDist.T.operate(distToFloatOp, s)
|
||||
|> E.R.bind(_, v => Ok(`SymbolicDist(`Float(v))))
|
||||
| `RenderedDist(rs) =>
|
||||
Shape.operate(distToFloatOp, rs) |> (v => Ok(`SymbolicDist(`Float(v))))
|
||||
};
|
||||
};
|
||||
|
||||
let verticalScaling = (scaleOp, rs, 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 integralSumCacheFn = Operation.Scale.toIntegralSumCacheFn(scaleOp);
|
||||
let integralCacheFn = Operation.Scale.toIntegralCacheFn(scaleOp);
|
||||
Ok(
|
||||
`RenderedDist(
|
||||
Shape.T.mapY(
|
||||
~integralSumCacheFn=integralSumCacheFn(scaleBy),
|
||||
~integralCacheFn=integralCacheFn(scaleBy),
|
||||
~fn=fn(scaleBy),
|
||||
rs,
|
||||
),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
module Multimodal = {
|
||||
let getByNameResult = ExpressionTypes.ExpressionTree.Hash.getByNameResult;
|
||||
|
||||
let _paramsToDistsAndWeights = (r: array(typedValue)) =>
|
||||
switch (r) {
|
||||
| [|`Hash(r)|] =>
|
||||
let dists =
|
||||
getByNameResult(r, "dists")
|
||||
->E.R.bind(TypeSystem.TypedValue.toArray)
|
||||
->E.R.bind(r =>
|
||||
r
|
||||
|> E.A.fmap(TypeSystem.TypedValue.toDist)
|
||||
|> E.A.R.firstErrorOrOpen
|
||||
);
|
||||
let weights =
|
||||
getByNameResult(r, "weights")
|
||||
->E.R.bind(TypeSystem.TypedValue.toArray)
|
||||
->E.R.bind(r =>
|
||||
r
|
||||
|> E.A.fmap(TypeSystem.TypedValue.toFloat)
|
||||
|> E.A.R.firstErrorOrOpen
|
||||
);
|
||||
|
||||
E.R.merge(dists, weights)
|
||||
|> E.R.fmap(((a, b)) =>
|
||||
E.A.zipMaxLength(a, b)
|
||||
|> E.A.fmap(((a, b)) =>
|
||||
(a |> E.O.toExn(""), b |> E.O.default(1.0))
|
||||
)
|
||||
);
|
||||
| _ => Error("Needs items")
|
||||
};
|
||||
let _runner: array(typedValue) => result(node, string) =
|
||||
r => {
|
||||
let paramsToDistsAndWeights =
|
||||
_paramsToDistsAndWeights(r)
|
||||
|> E.R.fmap(
|
||||
E.A.fmap(((dist, weight)) =>
|
||||
`FunctionCall((
|
||||
"scaleMultiply",
|
||||
[|dist, `SymbolicDist(`Float(weight))|],
|
||||
))
|
||||
),
|
||||
);
|
||||
let pointwiseSum: result(node, string) =
|
||||
paramsToDistsAndWeights->E.R.bind(
|
||||
E.R.errorIfCondition(E.A.isEmpty, "Needs one input"),
|
||||
)
|
||||
|> E.R.fmap(r =>
|
||||
r
|
||||
|> Js.Array.sliceFrom(1)
|
||||
|> E.A.fold_left(
|
||||
(acc, x) => {`PointwiseCombination((`Add, acc, x))},
|
||||
E.A.unsafe_get(r, 0),
|
||||
)
|
||||
);
|
||||
pointwiseSum;
|
||||
};
|
||||
|
||||
let _function =
|
||||
Function.T.make(
|
||||
~name="multimodal",
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|
|
||||
`Hash([|
|
||||
("dists", `Array(`SamplingDistribution)),
|
||||
("weights", `Array(`Float)),
|
||||
|]),
|
||||
|],
|
||||
~run=_runner,
|
||||
(),
|
||||
);
|
||||
};
|
||||
|
||||
let all = [|
|
||||
makeSymbolicFromTwoFloats("normal", SymbolicDist.Normal.make),
|
||||
makeSymbolicFromTwoFloats("uniform", SymbolicDist.Uniform.make),
|
||||
makeSymbolicFromTwoFloats("beta", SymbolicDist.Beta.make),
|
||||
makeSymbolicFromTwoFloats("lognormal", SymbolicDist.Lognormal.make),
|
||||
makeSymbolicFromTwoFloats(
|
||||
"lognormalFromMeanAndStdDev",
|
||||
SymbolicDist.Lognormal.fromMeanAndStdev,
|
||||
),
|
||||
makeSymbolicFromOneFloat("exponential", SymbolicDist.Exponential.make),
|
||||
Function.T.make(
|
||||
~name="to",
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`Float, `Float|],
|
||||
~run=
|
||||
fun
|
||||
| [|`Float(a), `Float(b)|] => to_(a, b)
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
),
|
||||
Function.T.make(
|
||||
~name="triangular",
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`Float, `Float, `Float|],
|
||||
~run=
|
||||
fun
|
||||
| [|`Float(a), `Float(b), `Float(c)|] =>
|
||||
SymbolicDist.Triangular.make(a, b, c)
|
||||
|> E.R.fmap(r => `SymbolicDist(r))
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
),
|
||||
makeDistFloat("pdf", (dist, float) => floatFromDist(`Pdf(float), dist)),
|
||||
makeDistFloat("inv", (dist, float) => floatFromDist(`Inv(float), dist)),
|
||||
makeDistFloat("cdf", (dist, float) => floatFromDist(`Cdf(float), dist)),
|
||||
makeDist("mean", dist => floatFromDist(`Mean, dist)),
|
||||
makeDist("sample", dist => floatFromDist(`Sample, dist)),
|
||||
Function.T.make(
|
||||
~name="render",
|
||||
~outputType=`RenderedDistribution,
|
||||
~inputTypes=[|`RenderedDistribution|],
|
||||
~run=
|
||||
fun
|
||||
| [|`RenderedDist(c)|] => Ok(`RenderedDist(c))
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
),
|
||||
Function.T.make(
|
||||
~name="normalize",
|
||||
~outputType=`SamplingDistribution,
|
||||
~inputTypes=[|`SamplingDistribution|],
|
||||
~run=
|
||||
fun
|
||||
| [|`SamplingDist(`SymbolicDist(c))|] => Ok(`SymbolicDist(c))
|
||||
| [|`SamplingDist(`RenderedDist(c))|] =>
|
||||
Ok(`RenderedDist(Shape.T.normalize(c)))
|
||||
| e => wrongInputsError(e),
|
||||
(),
|
||||
),
|
||||
makeRenderedDistFloat("scaleExp", (dist, float) =>
|
||||
verticalScaling(`Exponentiate, dist, float)
|
||||
),
|
||||
makeRenderedDistFloat("scaleMultiply", (dist, float) =>
|
||||
verticalScaling(`Multiply, dist, float)
|
||||
),
|
||||
makeRenderedDistFloat("scaleLog", (dist, float) =>
|
||||
verticalScaling(`Log, dist, float)
|
||||
),
|
||||
Multimodal._function
|
||||
|];
|
Loading…
Reference in New Issue
Block a user