diff --git a/src/components/DistBuilder3.re b/src/components/DistBuilder3.re index 8cc29538..818705ef 100644 --- a/src/components/DistBuilder3.re +++ b/src/components/DistBuilder3.re @@ -37,7 +37,14 @@ module DemoDist = { let parsed1 = MathJsParser.fromString(guesstimatorString); let shape = switch (parsed1) { - | Ok(r) => Some(ExpressionTree.toShape(10000, r)) + | Ok(r) => + Some( + ExpressionTree.toShape( + 10000, + {sampleCount: 10000, outputXYPoints: 10000, kernelWidth: None}, + r, + ), + ) | _ => None }; diff --git a/src/components/Drawer.re b/src/components/Drawer.re index 58ec97b3..fd83f47e 100644 --- a/src/components/Drawer.re +++ b/src/components/Drawer.re @@ -161,7 +161,6 @@ module Convert = { let canvasShapeToContinuousShape = (~canvasShape: Types.canvasShape, ~canvasElement: Dom.element) : Types.continuousShape => { - let xs = canvasShape.xValues; let hs = canvasShape.hs; let rectangle: Types.rectangle = @@ -170,19 +169,19 @@ module Convert = { let paddingFactorY = CanvasContext.paddingFactorX(rectangle.height); let windowScrollY: float = [%raw "window.scrollY"]; - let y0Line = bottom+.windowScrollY-.paddingFactorY; - let ys = E.A.fmap( h => y0Line -. h, hs); - + let y0Line = bottom +. windowScrollY -. paddingFactorY; + let ys = E.A.fmap(h => y0Line -. h, hs); + let xyShape: Types.xyShape = {xs, ys}; let continuousShape: Types.continuousShape = { xyShape, interpolation: `Linear, knownIntegralSum: None, }; - + let integral = XYShape.Analysis.integrateContinuousShape(continuousShape); let ys = E.A.fmap(y => y /. integral, ys); - + let continuousShape: Types.continuousShape = { xyShape: { xs, @@ -389,7 +388,12 @@ module Draw = { let numSamples = 3000; 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 = switch (normalShape) { | Mixed(_) => {xs: [||], ys: [||]} @@ -668,10 +672,7 @@ module State = { Convert.canvasShapeToContinuousShape(~canvasShape, ~canvasElement); /* create a cdf from a pdf */ - let _pdf = - Continuous.T.normalize( - pdf, - ); + let _pdf = Continuous.T.normalize(pdf); let cdf = Continuous.T.integral(~cache=None, _pdf); let xs = [||]; diff --git a/src/distPlus/expressionTree/ExpressionTree.re b/src/distPlus/expressionTree/ExpressionTree.re index e7d16386..82eb9d3c 100644 --- a/src/distPlus/expressionTree/ExpressionTree.re +++ b/src/distPlus/expressionTree/ExpressionTree.re @@ -1,9 +1,13 @@ open ExpressionTypes.ExpressionTree; -let toShape = (sampleCount: int, node: node) => { +let toShape = (intendedShapeLength: int, samplingInputs, node: node) => { let renderResult = `Render(`Normalize(node)) - |> ExpressionTreeEvaluator.toLeaf({sampleCount: sampleCount, evaluateNode: ExpressionTreeEvaluator.toLeaf}); + |> ExpressionTreeEvaluator.toLeaf({ + samplingInputs, + intendedShapeLength, + evaluateNode: ExpressionTreeEvaluator.toLeaf, + }); switch (renderResult) { | Ok(`RenderedDist(rs)) => diff --git a/src/distPlus/expressionTree/ExpressionTreeEvaluator.re b/src/distPlus/expressionTree/ExpressionTreeEvaluator.re index 33aa8b41..798ccaf6 100644 --- a/src/distPlus/expressionTree/ExpressionTreeEvaluator.re +++ b/src/distPlus/expressionTree/ExpressionTreeEvaluator.re @@ -4,8 +4,6 @@ open ExpressionTypes.ExpressionTree; type t = node; type tResult = node => result(node, string); -type renderParams = {sampleCount: int}; - /* 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. For instance, normal(0, 1) + normal(1, 1) -> normal(1, 2). @@ -51,15 +49,23 @@ module AlgebraicCombination = { |> E.R.bind( _, ((a, b)) => { - let samples = tryCombination(evaluationParams.sampleCount, algebraicOp, a, b); + let samples = + tryCombination( + evaluationParams.samplingInputs.sampleCount, + algebraicOp, + a, + b, + ); let shape = samples |> E.O.fmap( Samples.T.fromSamples( ~samplingInputs={ - sampleCount: Some(evaluationParams.sampleCount), - outputXYPoints: None, - kernelWidth: None, + sampleCount: + Some(evaluationParams.samplingInputs.sampleCount), + outputXYPoints: + Some(evaluationParams.samplingInputs.outputXYPoints), + kernelWidth: evaluationParams.samplingInputs.kernelWidth, }, ), ) @@ -235,7 +241,7 @@ module Render = { | `SymbolicDist(d) => Ok( `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 diff --git a/src/distPlus/expressionTree/ExpressionTypes.re b/src/distPlus/expressionTree/ExpressionTypes.re index 18cab285..b36548e3 100644 --- a/src/distPlus/expressionTree/ExpressionTypes.re +++ b/src/distPlus/expressionTree/ExpressionTypes.re @@ -16,8 +16,15 @@ module ExpressionTree = { | `FloatFromDist(distToFloatOperation, node) ]; - type evaluationParams = { + type samplingInputs = { sampleCount: int, + outputXYPoints: int, + kernelWidth: option(float), + }; + + type evaluationParams = { + samplingInputs, + intendedShapeLength: int, evaluateNode: (evaluationParams, node) => Belt.Result.t(node, string), }; @@ -28,18 +35,22 @@ module ExpressionTree = { evaluateNode(evaluationParams, `Render(r)); 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 - | `SymbolicDist(_) => true - | `RenderedDist(_) => true - | _ => false; + let renderable = + fun + | `SymbolicDist(_) => true + | `RenderedDist(_) => true + | _ => false; - let mapRenderable = (renderedFn, symFn, item: node) => switch(item) { - | `SymbolicDist(s) => Some(symFn(s)) - | `RenderedDist(r) => Some(renderedFn(r)) - | _ => None - } + let mapRenderable = (renderedFn, symFn, item: node) => + switch (item) { + | `SymbolicDist(s) => Some(symFn(s)) + | `RenderedDist(r) => Some(renderedFn(r)) + | _ => None + }; }; type simplificationResult = [ diff --git a/src/distPlus/renderers/ShapeRenderer.re b/src/distPlus/renderers/ShapeRenderer.re index b439240b..1a4aad2b 100644 --- a/src/distPlus/renderers/ShapeRenderer.re +++ b/src/distPlus/renderers/ShapeRenderer.re @@ -14,14 +14,24 @@ let formatString = str => { str |> formatMessyArray; }; -let runSymbolic = (guesstimatorString, length) => { - let str = formatString(guesstimatorString); +let runSymbolic = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) => { + let str = formatString(inputs.guesstimatorString); let graph = MathJsParser.fromString(str); graph |> E.R.fmap(g => RenderTypes.ShapeRenderer.Symbolic.make( 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 = (inputs: RenderTypes.ShapeRenderer.Combined.inputs) : RenderTypes.ShapeRenderer.Combined.outputs => { - let symbolic = - runSymbolic(inputs.guesstimatorString, inputs.symbolicInputs.length); + let symbolic = runSymbolic(inputs); let sampling = switch (symbolic) { | Ok(_) => None