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

View File

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

View File

@ -37,6 +37,7 @@ let empty: DistTypes.continuousShape = {
let stepwiseToLinear = (t: t): t => let stepwiseToLinear = (t: t): t =>
make(~integralSumCache=t.integralSumCache, ~integralCache=t.integralCache, XYShape.Range.stepwiseToLinear(t.xyShape)); 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 = let combinePointwise =
( (
~integralSumCachesFn=(_, _) => None, ~integralSumCachesFn=(_, _) => None,

View File

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

View File

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

View File

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

View File

@ -14,9 +14,9 @@ let formatString = str => {
str |> formatMessyArray; str |> formatMessyArray;
}; };
let runSymbolic = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => { let run = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
let str = formatString(inputs.guesstimatorString); let str = formatString(inputs.guesstimatorString);
let graph = MathJsParser.fromString(str); let graph = MathJsParser.fromString(str, inputs.inputVariables);
graph graph
|> E.R.bind(_, g => |> E.R.bind(_, g =>
ExpressionTree.toShape( ExpressionTree.toShape(
@ -33,7 +33,3 @@ let runSymbolic = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
|> E.R.fmap(RenderTypes.ShapeRenderer.Symbolic.make(g)) |> 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 = { module Normal = {
type t = 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 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); let cdf = (x, t: t) => Jstat.normal##cdf(x, t.mean, t.stdev);