diff --git a/src/distPlus/symbolic/SymbolicDist.re b/src/distPlus/symbolic/SymbolicDist.re index 15ce2861..bfe4cc6e 100644 --- a/src/distPlus/symbolic/SymbolicDist.re +++ b/src/distPlus/symbolic/SymbolicDist.re @@ -279,7 +279,7 @@ module T = { | `Error(string) | `NoSolution ]; - let attemptAlgebraicOperation = + let attemptAnalyticalOperation = ( d1: symbolicDist, d2: symbolicDist, diff --git a/src/distPlus/symbolic/SymbolicTypes.re b/src/distPlus/symbolic/SymbolicTypes.re index b0d92d41..2dbb95db 100644 --- a/src/distPlus/symbolic/SymbolicTypes.re +++ b/src/distPlus/symbolic/SymbolicTypes.re @@ -95,8 +95,8 @@ module DistToFloat = { let format = (operation, value) => switch (operation) { - | `Pdf(f) => {j|pdf(x=$f,$value) |j} - | `Inv(f) => {j|inv(x=$f,$value) |j} + | `Pdf(f) => {j|pdf(x=$f,$value)|j} + | `Inv(f) => {j|inv(x=$f,$value)|j} | `Sample => "sample($value)" | `Mean => "mean($value)" }; @@ -110,6 +110,13 @@ module Scale = { | `Exponentiate => ( ** ) | `Log => ((a, b) => log(a) /. log(b)); + let format = (operation:t, value, scaleBy) => + switch (operation) { + | `Multiply => {j|scaleMultiply($value, $scaleBy) |j} + | `Exponentiate => {j|ScaleExponentiate($value, $scaleBy) |j} + | `Log => {j|ScaleLog($value, $scaleBy) |j} + }; + let toKnownIntegralSumFn = fun | `Multiply => ((a, b) => Some(a *. b)) diff --git a/src/distPlus/symbolic/TreeNode.re b/src/distPlus/symbolic/TreeNode.re index c29505e5..155b9169 100644 --- a/src/distPlus/symbolic/TreeNode.re +++ b/src/distPlus/symbolic/TreeNode.re @@ -5,6 +5,7 @@ type leaf = [ | `SymbolicDist(SymbolicTypes.symbolicDist) | `RenderedDist(DistTypes.shape) ]; + /* TreeNodes are either Data (i.e. symbolic or rendered distributions) or Operations. Operations always refer to two child nodes.*/ type treeNode = [ | `Leaf(leaf) | `Operation(operation)] and operation = [ @@ -19,25 +20,29 @@ and operation = [ module Operation = { type t = operation; + let truncateToString = + (left: option(float), right: option(float), nodeToString) => { + let left = left |> E.O.dimap(Js.Float.toString, () => "-inf"); + let right = right |> E.O.dimap(Js.Float.toString, () => "inf"); + {j|truncate($nodeToString, $left, $right)|j}; + }; + let toString = nodeToString => fun | `AlgebraicCombination(op, t1, t2) => SymbolicTypes.Algebraic.format(op, nodeToString(t1), nodeToString(t2)) | `PointwiseCombination(op, t1, t2) => SymbolicTypes.Pointwise.format(op, nodeToString(t1), nodeToString(t2)) - | `VerticalScaling(_scaleOp, t, scaleBy) => - nodeToString(t) ++ " @ " ++ nodeToString(scaleBy) + | `VerticalScaling(scaleOp, t, scaleBy) => + SymbolicTypes.Scale.format( + scaleOp, + nodeToString(t), + nodeToString(scaleBy), + ) | `Normalize(t) => "normalize(" ++ nodeToString(t) ++ ")" | `FloatFromDist(floatFromDistOp, t) => SymbolicTypes.DistToFloat.format(floatFromDistOp, nodeToString(t)) - | `Truncate(lc, rc, t) => - "truncate(" - ++ nodeToString(t) - ++ ", " - ++ E.O.dimap(Js.Float.toString, () => "-inf", lc) - ++ ", " - ++ E.O.dimap(Js.Float.toString, () => "inf", rc) - ++ ")" + | `Truncate(lc, rc, t) => truncateToString(lc, rc, nodeToString(t)) | `Render(t) => nodeToString(t); }; @@ -70,7 +75,7 @@ module TreeNode = { `Leaf(`SymbolicDist(d2)), ), ) as t => - switch (SymbolicDist.T.attemptAlgebraicOperation(d1, d2, operation)) { + switch (SymbolicDist.T.attemptAnalyticalOperation(d1, d2, operation)) { | `AnalyticalSolution(symbolicDist) => Ok(`Leaf(`SymbolicDist(symbolicDist))) | `Error(er) => Error(er)