Attached inputs to editor

This commit is contained in:
Ozzie Gooen 2020-07-12 23:54:52 +01:00
parent e5f38af43e
commit 2da6f00211
6 changed files with 75 additions and 37 deletions

View File

@ -37,7 +37,14 @@ module DemoDist = {
let parsed1 = MathJsParser.fromString(guesstimatorString); let parsed1 = MathJsParser.fromString(guesstimatorString);
let shape = let shape =
switch (parsed1) { switch (parsed1) {
| Ok(r) => Some(ExpressionTree.toShape(10000, r)) | Ok(r) =>
Some(
ExpressionTree.toShape(
10000,
{sampleCount: 10000, outputXYPoints: 10000, kernelWidth: None},
r,
),
)
| _ => None | _ => None
}; };

View File

@ -161,7 +161,6 @@ module Convert = {
let canvasShapeToContinuousShape = let canvasShapeToContinuousShape =
(~canvasShape: Types.canvasShape, ~canvasElement: Dom.element) (~canvasShape: Types.canvasShape, ~canvasElement: Dom.element)
: Types.continuousShape => { : Types.continuousShape => {
let xs = canvasShape.xValues; let xs = canvasShape.xValues;
let hs = canvasShape.hs; let hs = canvasShape.hs;
let rectangle: Types.rectangle = let rectangle: Types.rectangle =
@ -170,19 +169,19 @@ module Convert = {
let paddingFactorY = CanvasContext.paddingFactorX(rectangle.height); let paddingFactorY = CanvasContext.paddingFactorX(rectangle.height);
let windowScrollY: float = [%raw "window.scrollY"]; let windowScrollY: float = [%raw "window.scrollY"];
let y0Line = bottom+.windowScrollY-.paddingFactorY; let y0Line = bottom +. windowScrollY -. paddingFactorY;
let ys = E.A.fmap( h => y0Line -. h, hs); let ys = E.A.fmap(h => y0Line -. h, hs);
let xyShape: Types.xyShape = {xs, ys}; let xyShape: Types.xyShape = {xs, ys};
let continuousShape: Types.continuousShape = { let continuousShape: Types.continuousShape = {
xyShape, xyShape,
interpolation: `Linear, interpolation: `Linear,
knownIntegralSum: None, knownIntegralSum: None,
}; };
let integral = XYShape.Analysis.integrateContinuousShape(continuousShape); let integral = XYShape.Analysis.integrateContinuousShape(continuousShape);
let ys = E.A.fmap(y => y /. integral, ys); let ys = E.A.fmap(y => y /. integral, ys);
let continuousShape: Types.continuousShape = { let continuousShape: Types.continuousShape = {
xyShape: { xyShape: {
xs, xs,
@ -389,7 +388,12 @@ module Draw = {
let numSamples = 3000; let numSamples = 3000;
let normal: SymbolicTypes.symbolicDist = `Normal({mean, stdev}); let normal: SymbolicTypes.symbolicDist = `Normal({mean, stdev});
let normalShape = ExpressionTree.toShape(numSamples, `SymbolicDist(normal)); let normalShape =
ExpressionTree.toShape(
numSamples,
{sampleCount: 10000, outputXYPoints: 10000, kernelWidth: None},
`SymbolicDist(normal),
);
let xyShape: Types.xyShape = let xyShape: Types.xyShape =
switch (normalShape) { switch (normalShape) {
| Mixed(_) => {xs: [||], ys: [||]} | Mixed(_) => {xs: [||], ys: [||]}
@ -668,10 +672,7 @@ module State = {
Convert.canvasShapeToContinuousShape(~canvasShape, ~canvasElement); Convert.canvasShapeToContinuousShape(~canvasShape, ~canvasElement);
/* create a cdf from a pdf */ /* create a cdf from a pdf */
let _pdf = let _pdf = Continuous.T.normalize(pdf);
Continuous.T.normalize(
pdf,
);
let cdf = Continuous.T.integral(~cache=None, _pdf); let cdf = Continuous.T.integral(~cache=None, _pdf);
let xs = [||]; let xs = [||];

View File

@ -1,9 +1,13 @@
open ExpressionTypes.ExpressionTree; open ExpressionTypes.ExpressionTree;
let toShape = (sampleCount: int, node: node) => { let toShape = (intendedShapeLength: int, samplingInputs, node: node) => {
let renderResult = let renderResult =
`Render(`Normalize(node)) `Render(`Normalize(node))
|> ExpressionTreeEvaluator.toLeaf({sampleCount: sampleCount, evaluateNode: ExpressionTreeEvaluator.toLeaf}); |> ExpressionTreeEvaluator.toLeaf({
samplingInputs,
intendedShapeLength,
evaluateNode: ExpressionTreeEvaluator.toLeaf,
});
switch (renderResult) { switch (renderResult) {
| Ok(`RenderedDist(rs)) => | Ok(`RenderedDist(rs)) =>

View File

@ -4,8 +4,6 @@ open ExpressionTypes.ExpressionTree;
type t = node; type t = node;
type tResult = node => result(node, string); type tResult = node => result(node, string);
type renderParams = {sampleCount: int};
/* Given two random variables A and B, this returns the distribution /* Given two random variables A and B, this returns the distribution
of a new variable that is the result of the operation on A and B. of a new variable that is the result of the operation on A and B.
For instance, normal(0, 1) + normal(1, 1) -> normal(1, 2). For instance, normal(0, 1) + normal(1, 1) -> normal(1, 2).
@ -51,15 +49,23 @@ module AlgebraicCombination = {
|> E.R.bind( |> E.R.bind(
_, _,
((a, b)) => { ((a, b)) => {
let samples = tryCombination(evaluationParams.sampleCount, algebraicOp, a, b); let samples =
tryCombination(
evaluationParams.samplingInputs.sampleCount,
algebraicOp,
a,
b,
);
let shape = let shape =
samples samples
|> E.O.fmap( |> E.O.fmap(
Samples.T.fromSamples( Samples.T.fromSamples(
~samplingInputs={ ~samplingInputs={
sampleCount: Some(evaluationParams.sampleCount), sampleCount:
outputXYPoints: None, Some(evaluationParams.samplingInputs.sampleCount),
kernelWidth: None, outputXYPoints:
Some(evaluationParams.samplingInputs.outputXYPoints),
kernelWidth: evaluationParams.samplingInputs.kernelWidth,
}, },
), ),
) )
@ -235,7 +241,7 @@ module Render = {
| `SymbolicDist(d) => | `SymbolicDist(d) =>
Ok( Ok(
`RenderedDist( `RenderedDist(
SymbolicDist.T.toShape(evaluationParams.sampleCount, d), SymbolicDist.T.toShape(evaluationParams.intendedShapeLength, d),
), ),
) )
| `RenderedDist(_) as t => Ok(t) // already a rendered shape, we're done here | `RenderedDist(_) as t => Ok(t) // already a rendered shape, we're done here

View File

@ -16,8 +16,15 @@ module ExpressionTree = {
| `FloatFromDist(distToFloatOperation, node) | `FloatFromDist(distToFloatOperation, node)
]; ];
type evaluationParams = { type samplingInputs = {
sampleCount: int, sampleCount: int,
outputXYPoints: int,
kernelWidth: option(float),
};
type evaluationParams = {
samplingInputs,
intendedShapeLength: int,
evaluateNode: (evaluationParams, node) => Belt.Result.t(node, string), evaluateNode: (evaluationParams, node) => Belt.Result.t(node, string),
}; };
@ -28,18 +35,22 @@ module ExpressionTree = {
evaluateNode(evaluationParams, `Render(r)); evaluateNode(evaluationParams, `Render(r));
let evaluateAndRetry = (evaluationParams, fn, node) => let evaluateAndRetry = (evaluationParams, fn, node) =>
node |> evaluationParams.evaluateNode(evaluationParams) |> E.R.bind(_, fn(evaluationParams)); node
|> evaluationParams.evaluateNode(evaluationParams)
|> E.R.bind(_, fn(evaluationParams));
let renderable = fun let renderable =
| `SymbolicDist(_) => true fun
| `RenderedDist(_) => true | `SymbolicDist(_) => true
| _ => false; | `RenderedDist(_) => true
| _ => false;
let mapRenderable = (renderedFn, symFn, item: node) => switch(item) { let mapRenderable = (renderedFn, symFn, item: node) =>
| `SymbolicDist(s) => Some(symFn(s)) switch (item) {
| `RenderedDist(r) => Some(renderedFn(r)) | `SymbolicDist(s) => Some(symFn(s))
| _ => None | `RenderedDist(r) => Some(renderedFn(r))
} | _ => None
};
}; };
type simplificationResult = [ type simplificationResult = [

View File

@ -14,14 +14,24 @@ let formatString = str => {
str |> formatMessyArray; str |> formatMessyArray;
}; };
let runSymbolic = (guesstimatorString, length) => { let runSymbolic = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => {
let str = formatString(guesstimatorString); let str = formatString(inputs.guesstimatorString);
let graph = MathJsParser.fromString(str); let graph = MathJsParser.fromString(str);
graph graph
|> E.R.fmap(g => |> E.R.fmap(g =>
RenderTypes.ShapeRenderer.Symbolic.make( RenderTypes.ShapeRenderer.Symbolic.make(
g, g,
ExpressionTree.toShape(length, g), ExpressionTree.toShape(
inputs.symbolicInputs.length,
{
sampleCount:
inputs.samplingInputs.sampleCount |> E.O.default(10000),
outputXYPoints:
inputs.samplingInputs.outputXYPoints |> E.O.default(10000),
kernelWidth: inputs.samplingInputs.kernelWidth,
},
g,
),
) )
); );
}; };
@ -29,8 +39,7 @@ let runSymbolic = (guesstimatorString, length) => {
let run = let run =
(inputs: RenderTypes.ShapeRenderer.Combined.inputs) (inputs: RenderTypes.ShapeRenderer.Combined.inputs)
: RenderTypes.ShapeRenderer.Combined.outputs => { : RenderTypes.ShapeRenderer.Combined.outputs => {
let symbolic = let symbolic = runSymbolic(inputs);
runSymbolic(inputs.guesstimatorString, inputs.symbolicInputs.length);
let sampling = let sampling =
switch (symbolic) { switch (symbolic) {
| Ok(_) => None | Ok(_) => None