First attempt at showing the use of a simple variable

This commit is contained in:
Ozzie Gooen 2020-07-23 15:59:46 +01:00
parent bfd9ca5533
commit 102a147b97
8 changed files with 90 additions and 41 deletions

View File

@ -133,7 +133,7 @@ module DemoDist = {
~unit,
(),
);
let inputs =
let inputs1 =
RenderTypes.DistPlusRenderer.make(
~samplingInputs={
sampleCount: Some(options.sampleCount),
@ -143,14 +143,37 @@ module DemoDist = {
~distPlusIngredients,
~shouldDownsample=options.downsampleTo |> E.O.isSome,
~recommendedLength=options.downsampleTo |> E.O.default(1000),
~inputVariables=
[|("p", `SymbolicDist(`Float(1.0)))|]
->Belt.Map.String.fromArray,
(),
);
let response = DistPlusRenderer.run(inputs);
switch (response) {
| Ok(distPlus) =>
let normalizedDistPlus = DistPlus.T.normalize(distPlus);
<DistPlusPlot distPlus=normalizedDistPlus />;
| Error(r) => r |> R.ste
let response1 = DistPlusRenderer.run(inputs1);
let inputs2 =
RenderTypes.DistPlusRenderer.make(
~samplingInputs={
sampleCount: Some(options.sampleCount),
outputXYPoints: Some(options.outputXYPoints),
kernelWidth: options.kernelWidth,
},
~distPlusIngredients,
~shouldDownsample=options.downsampleTo |> E.O.isSome,
~recommendedLength=options.downsampleTo |> E.O.default(1000),
~inputVariables=
[|("p", `SymbolicDist(`Float(2.0)))|]
->Belt.Map.String.fromArray,
(),
);
let response2 = DistPlusRenderer.run(inputs2);
switch (response1, response2) {
| (Ok(distPlus1), Ok(distPlus2)) =>
<>
<DistPlusPlot distPlus={DistPlus.T.normalize(distPlus1)} />
<DistPlusPlot distPlus={DistPlus.T.normalize(distPlus2)} />
</>
| (Error(r), _) => r |> R.ste
| (_, Error(r)) => r |> R.ste
};
| _ =>
"Nothing to show. Try to change the distribution description."

View File

@ -106,7 +106,6 @@ let init = {
showParams: false,
showPercentiles: true,
distributions: [
{yLog: false, xLog: false, isCumulative: false, height: 4},
{yLog: false, xLog: false, isCumulative: true, height: 1},
{yLog: false, xLog: false, isCumulative: false, height: 1},
],
};

View File

@ -37,6 +37,7 @@ let empty: DistTypes.continuousShape = {
let stepwiseToLinear = (t: t): t =>
make(~integralSumCache=t.integralSumCache, ~integralCache=t.integralCache, XYShape.Range.stepwiseToLinear(t.xyShape));
// Note: This results in a distribution with as many points as the sum of those in t1 and t2.
let combinePointwise =
(
~integralSumCachesFn=(_, _) => None,

View File

@ -1,3 +1,5 @@
type inputVars = Belt.Map.String.t(ExpressionTypes.ExpressionTree.node);
module MathJsonToMathJsAdt = {
type arg =
| Symbol(string)
@ -50,24 +52,33 @@ module MathJsonToMathJsAdt = {
module MathAdtToDistDst = {
open MathJsonToMathJsAdt;
let handleSymbol = (inputVars: inputVars, sym) => {
switch (Belt.Map.String.get(inputVars, sym)) {
| Some(s) => Ok(s)
| None => Error("Couldn't find.")
};
};
module MathAdtCleaner = {
let transformWithSymbol = (f: float, s: string) =>
switch (s) {
| "K"
| "k" => f *. 1000.
| "k" => Some(f *. 1000.)
| "M"
| "m" => f *. 1000000.
| "m" => Some(f *. 1000000.)
| "B"
| "b" => f *. 1000000000.
| "b" => Some(f *. 1000000000.)
| "T"
| "t" => f *. 1000000000000.
| _ => f
| "t" => Some(f *. 1000000000000.)
| _ => None
};
let rec run =
fun
| Fn({name: "multiply", args: [|Value(f), Symbol(s)|]}) =>
Value(transformWithSymbol(f, s))
| Fn({name: "multiply", args: [|Value(f), Symbol(s)|]}) as doNothing =>
transformWithSymbol(f, s)
|> E.O.fmap(r => Value(r))
|> E.O.default(doNothing)
| Fn({name: "unaryMinus", args: [|Value(f)|]}) => Value((-1.0) *. f)
| Fn({name, args}) => Fn({name, args: args |> E.A.fmap(run)})
| Array(args) => Array(args |> E.A.fmap(run))
@ -347,24 +358,26 @@ module MathAdtToDistDst = {
};
};
let rec nodeParser =
let rec nodeParser = inputVars =>
fun
| Value(f) => Ok(`SymbolicDist(`Float(f)))
| Fn({name, args}) => functionParser(nodeParser, name, args)
| Symbol(s) => handleSymbol(inputVars, s)
| Fn({name, args}) => functionParser(nodeParser(inputVars), name, args)
| _ => {
Error("This type not currently supported");
};
let topLevel =
let topLevel = inputVars =>
fun
| Value(_) as r => nodeParser(r)
| Fn(_) as r => nodeParser(r)
| Value(_) as r => nodeParser(inputVars, r)
| Fn(_) as r => nodeParser(inputVars, r)
| Array(_) => Error("Array not valid as top level")
| Symbol(_) => Error("Symbol not valid as top level")
| Symbol(s) => handleSymbol(inputVars, s)
| Object(_) => Error("Object not valid as top level");
let run = (r): result(ExpressionTypes.ExpressionTree.node, string) =>
r |> MathAdtCleaner.run |> topLevel;
let run =
(inputVars, r): result(ExpressionTypes.ExpressionTree.node, string) =>
r |> MathAdtCleaner.run |> topLevel(inputVars);
};
/* The MathJs parser doesn't support '.+' syntax, but we want it because it
@ -374,7 +387,7 @@ module MathAdtToDistDst = {
*/
let pointwiseToRightLogShift = Js.String.replaceByRe([%re "/\.\+/g"], ">>>");
let fromString = str => {
let fromString2 = (inputVars: inputVars, str) => {
/* We feed the user-typed string into Mathjs.parseMath,
which returns a JSON with (hopefully) a single-element array.
This array element is the top-level node of a nested-object tree
@ -384,7 +397,6 @@ let fromString = str => {
Inside of this function, MathAdtToDistDst is called whenever a distribution function is encountered.
*/
let mathJsToJson = str |> pointwiseToRightLogShift |> Mathjs.parseMath;
Js.log(mathJsToJson);
let mathJsParse =
E.R.bind(mathJsToJson, r => {
switch (MathJsonToMathJsAdt.run(r)) {
@ -394,6 +406,10 @@ let fromString = str => {
});
Js.log(mathJsParse);
let value = E.R.bind(mathJsParse, MathAdtToDistDst.run);
let value = E.R.bind(mathJsParse, MathAdtToDistDst.run(inputVars));
value;
};
let fromString = (str, vars: inputVars) => {
fromString2(vars, str);
};

View File

@ -8,10 +8,13 @@ let run = (inputs: RenderTypes.DistPlusRenderer.inputs) => {
(),
)
|> DistPlus.T.normalize;
// let symbolicDist: ExpressionTypes.ExpressionTree.node = `SymbolicDist(`Float(30.0));
// inputVariables: [|("p", symbolicDist)|] -> Belt.Map.String.fromArray,
let output =
ShapeRenderer.run({
samplingInputs: inputs.samplingInputs,
guesstimatorString: inputs.distPlusIngredients.guesstimatorString,
inputVariables: inputs.inputVariables,
symbolicInputs: {
length: inputs.recommendedLength,
},

View File

@ -1,3 +1,5 @@
module MS = Belt.Map.String;
module ShapeRenderer = {
module Sampling = {
type inputs = {
@ -54,16 +56,18 @@ module ShapeRenderer = {
samplingInputs: Sampling.inputs,
symbolicInputs: Symbolic.inputs,
guesstimatorString: string,
inputVariables: MS.t(ExpressionTypes.ExpressionTree.node),
};
type outputs = {
symbolic: option(Belt.Result.t(Symbolic.outputs, string)),
sampling: option(Sampling.outputs),
};
let methodUsed = ({symbolic, sampling}:outputs) => switch(symbolic, sampling){
let methodUsed = ({symbolic, sampling}: outputs) =>
switch (symbolic, sampling) {
| (Some(Ok(_)), _) => `Symbolic
| (_, Some({shape: Some(_)})) => `Sampling
| _ => `None
}
};
let getShape = (r: outputs) =>
switch (r.symbolic, r.sampling) {
| (Some(Ok({shape})), _) => Some(shape)
@ -86,6 +90,7 @@ module DistPlusRenderer = {
samplingInputs: ShapeRenderer.Sampling.inputs,
recommendedLength: int,
shouldDownsample: bool,
inputVariables: MS.t(ExpressionTypes.ExpressionTree.node),
};
module Ingredients = {
let make =
@ -107,6 +112,7 @@ module DistPlusRenderer = {
~recommendedLength=defaultRecommendedLength,
~shouldDownsample=defaultShouldDownsample,
~distPlusIngredients,
~inputVariables=[||]->Belt.Map.String.fromArray,
(),
)
: inputs => {
@ -114,14 +120,18 @@ module DistPlusRenderer = {
samplingInputs,
recommendedLength,
shouldDownsample,
inputVariables,
};
type outputs = {
shapeRenderOutputs: ShapeRenderer.Combined.outputs,
distPlus: option(DistTypes.distPlus)
}
distPlus: option(DistTypes.distPlus),
};
module Outputs = {
let distplus = (t:outputs) => t.distPlus
let shapeRenderOutputs = (t:outputs) => t.shapeRenderOutputs
let make = (shapeRenderOutputs, distPlus) => {shapeRenderOutputs, distPlus};
}
let distplus = (t: outputs) => t.distPlus;
let shapeRenderOutputs = (t: outputs) => t.shapeRenderOutputs;
let make = (shapeRenderOutputs, distPlus) => {
shapeRenderOutputs,
distPlus,
};
};
};

View File

@ -14,9 +14,9 @@ let formatString = str => {
str |> formatMessyArray;
};
let runSymbolic = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
let run = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
let str = formatString(inputs.guesstimatorString);
let graph = MathJsParser.fromString(str);
let graph = MathJsParser.fromString(str, inputs.inputVariables);
graph
|> E.R.bind(_, g =>
ExpressionTree.toShape(
@ -33,7 +33,3 @@ let runSymbolic = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
|> E.R.fmap(RenderTypes.ShapeRenderer.Symbolic.make(g))
);
};
let run = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
runSymbolic(inputs);
};

View File

@ -32,6 +32,7 @@ module Triangular = {
module Normal = {
type t = normal;
let make = (mean, stdev):t => {mean, stdev};
let pdf = (x, t: t) => Jstat.normal##pdf(x, t.mean, t.stdev);
let cdf = (x, t: t) => Jstat.normal##cdf(x, t.mean, t.stdev);