Added simple exponentiation

This commit is contained in:
Ozzie Gooen 2020-07-31 14:02:29 +01:00
parent bcbbcf0f43
commit e266e6557c
6 changed files with 54 additions and 35 deletions

View File

@ -45,11 +45,8 @@ let toDiscretePointMassesFromTriangulars =
if (inverse) { if (inverse) {
for (i in 1 to n - 2) { for (i in 1 to n - 2) {
Belt.Array.set( Belt.Array.set(masses, i - 1, (xs[i + 1] -. xs[i - 1]) *. ys[i] /. 2.)
masses, |> ignore;
i - 1,
(xs[i + 1] -. xs[i - 1]) *. ys[i] /. 2.,
) |> ignore;
// this only works when the whole triange is either on the left or on the right of zero // this only works when the whole triange is either on the left or on the right of zero
let a = xs[i - 1]; let a = xs[i - 1];
@ -80,14 +77,12 @@ let toDiscretePointMassesFromTriangulars =
} else { } else {
for (i in 1 to n - 2) { for (i in 1 to n - 2) {
// area of triangle = width * height / 2 // area of triangle = width * height / 2
Belt.Array.set( Belt.Array.set(masses, i - 1, (xs[i + 1] -. xs[i - 1]) *. ys[i] /. 2.)
masses, |> ignore;
i - 1,
(xs[i + 1] -. xs[i - 1]) *. ys[i] /. 2.,
) |> ignore;
// means of triangle = (a + b + c) / 3 // means of triangle = (a + b + c) / 3
Belt.Array.set(means, i - 1, (xs[i - 1] +. xs[i] +. xs[i + 1]) /. 3.) |> ignore; Belt.Array.set(means, i - 1, (xs[i - 1] +. xs[i] +. xs[i + 1]) /. 3.)
|> ignore;
// variance of triangle = (a^2 + b^2 + c^2 - ab - ac - bc) / 18 // variance of triangle = (a^2 + b^2 + c^2 - ab - ac - bc) / 18
Belt.Array.set( Belt.Array.set(
@ -102,7 +97,8 @@ let toDiscretePointMassesFromTriangulars =
-. xsProdN2[i - 1] -. xsProdN2[i - 1]
) )
/. 18., /. 18.,
) |> ignore; )
|> ignore;
(); ();
}; };
{n: n - 2, masses, means, variances}; {n: n - 2, masses, means, variances};
@ -134,8 +130,10 @@ let combineShapesContinuousContinuous =
| `Subtract => ((m1, m2) => m1 -. m2) | `Subtract => ((m1, m2) => m1 -. m2)
| `Multiply => ((m1, m2) => m1 *. m2) | `Multiply => ((m1, m2) => m1 *. m2)
| `Divide => ((m1, mInv2) => m1 *. mInv2) | `Divide => ((m1, mInv2) => m1 *. mInv2)
| `Exponentiate => ((m1, mInv2) => m1 ** mInv2)
}; // note: here, mInv2 = mean(1 / t2) ~= 1 / mean(t2) }; // note: here, mInv2 = mean(1 / t2) ~= 1 / mean(t2)
// TODO: I don't know what the variances are for exponentatiation
// converts the variances and means of the two inputs into the variance of the output // converts the variances and means of the two inputs into the variance of the output
let combineVariancesFn = let combineVariancesFn =
switch (op) { switch (op) {
@ -144,6 +142,8 @@ let combineShapesContinuousContinuous =
| `Multiply => ( | `Multiply => (
(v1, v2, m1, m2) => v1 *. v2 +. v1 *. m2 ** 2. +. v2 *. m1 ** 2. (v1, v2, m1, m2) => v1 *. v2 +. v1 *. m2 ** 2. +. v2 *. m1 ** 2.
) )
| `Exponentiate =>
((v1, v2, m1, m2) => v1 *. v2 +. v1 *. m2 ** 2. +. v2 *. m1 ** 2.);
| `Divide => ( | `Divide => (
(v1, vInv2, m1, mInv2) => (v1, vInv2, m1, mInv2) =>
v1 *. vInv2 +. v1 *. mInv2 ** 2. +. vInv2 *. m1 ** 2. v1 *. vInv2 +. v1 *. mInv2 ** 2. +. vInv2 *. m1 ** 2.
@ -225,9 +225,12 @@ let toDiscretePointMassesFromDiscrete =
}; };
let combineShapesContinuousDiscrete = let combineShapesContinuousDiscrete =
(op: ExpressionTypes.algebraicOperation, continuousShape: DistTypes.xyShape, discreteShape: DistTypes.xyShape) (
op: ExpressionTypes.algebraicOperation,
continuousShape: DistTypes.xyShape,
discreteShape: DistTypes.xyShape,
)
: DistTypes.xyShape => { : DistTypes.xyShape => {
let t1n = continuousShape |> XYShape.T.length; let t1n = continuousShape |> XYShape.T.length;
let t2n = discreteShape |> XYShape.T.length; let t2n = discreteShape |> XYShape.T.length;
@ -248,15 +251,19 @@ let combineShapesContinuousDiscrete =
Belt.Array.set( Belt.Array.set(
dxyShape, dxyShape,
i, i,
(fn(continuousShape.xs[i], discreteShape.xs[j]), (
continuousShape.ys[i] *. discreteShape.ys[j]), fn(continuousShape.xs[i], discreteShape.xs[j]),
) |> ignore; continuousShape.ys[i] *. discreteShape.ys[j],
),
)
|> ignore;
(); ();
}; };
Belt.Array.set(outXYShapes, j, dxyShape) |> ignore; Belt.Array.set(outXYShapes, j, dxyShape) |> ignore;
(); ();
} }
| `Multiply | `Multiply
| `Exponentiate
| `Divide => | `Divide =>
for (j in 0 to t2n - 1) { for (j in 0 to t2n - 1) {
// creates a new continuous shape for each one of the discrete points, and collects them in outXYShapes. // creates a new continuous shape for each one of the discrete points, and collects them in outXYShapes.
@ -266,8 +273,12 @@ let combineShapesContinuousDiscrete =
Belt.Array.set( Belt.Array.set(
dxyShape, dxyShape,
i, i,
(fn(continuousShape.xs[i], discreteShape.xs[j]), continuousShape.ys[i] *. discreteShape.ys[j] /. discreteShape.xs[j]), (
) |> ignore; fn(continuousShape.xs[i], discreteShape.xs[j]),
{continuousShape.ys[i] *. discreteShape.ys[j] /. discreteShape.xs[j]}
),
)
|> ignore;
(); ();
}; };
Belt.Array.set(outXYShapes, j, dxyShape) |> ignore; Belt.Array.set(outXYShapes, j, dxyShape) |> ignore;
@ -278,7 +289,10 @@ let combineShapesContinuousDiscrete =
outXYShapes outXYShapes
|> E.A.fmap(XYShape.T.fromZippedArray) |> E.A.fmap(XYShape.T.fromZippedArray)
|> E.A.fold_left( |> E.A.fold_left(
XYShape.PointwiseCombination.combine((+.), XYShape.PointwiseCombination.combine(
XYShape.XtoY.continuousInterpolator(`Linear, `UseZero)), (+.),
XYShape.T.empty); XYShape.XtoY.continuousInterpolator(`Linear, `UseZero),
),
XYShape.T.empty,
);
}; };

View File

@ -151,7 +151,7 @@ module PointwiseCombination = {
}; };
}; };
let pointwiseMultiply = (evaluationParams: evaluationParams, t1: t, t2: t) => { let pointwiseCombine = (fn, evaluationParams: evaluationParams, t1: t, t2: t) => {
// TODO: construct a function that we can easily sample from, to construct // TODO: construct a function that we can easily sample from, to construct
// a RenderedDist. Use the xMin and xMax of the rendered shapes to tell the sampling function where to look. // a RenderedDist. Use the xMin and xMax of the rendered shapes to tell the sampling function where to look.
// TODO: This should work for symbolic distributions too! // TODO: This should work for symbolic distributions too!
@ -176,7 +176,8 @@ module PointwiseCombination = {
) => { ) => {
switch (pointwiseOp) { switch (pointwiseOp) {
| `Add => pointwiseAdd(evaluationParams, t1, t2) | `Add => pointwiseAdd(evaluationParams, t1, t2)
| `Multiply => pointwiseMultiply(evaluationParams, t1, t2) | `Multiply => pointwiseCombine(( *. ),evaluationParams, t1, t2)
| `Exponentiate => pointwiseCombine(( *. ),evaluationParams, t1, t2)
}; };
}; };
}; };
@ -279,7 +280,7 @@ module Render = {
| `SymbolicDist(d) => | `SymbolicDist(d) =>
Ok( Ok(
`RenderedDist( `RenderedDist(
SymbolicDist.T.toShape(1234, d), SymbolicDist.T.toShape(evaluationParams.samplingInputs.shapeLength, 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

@ -1,5 +1,5 @@
type algebraicOperation = [ | `Add | `Multiply | `Subtract | `Divide]; type algebraicOperation = [ | `Add | `Multiply | `Subtract | `Divide | `Exponentiate];
type pointwiseOperation = [ | `Add | `Multiply]; type pointwiseOperation = [ | `Add | `Multiply | `Exponentiate];
type scaleOperation = [ | `Multiply | `Exponentiate | `Log]; type scaleOperation = [ | `Multiply | `Exponentiate | `Log];
type distToFloatOperation = [ type distToFloatOperation = [
| `Pdf(float) | `Pdf(float)

View File

@ -177,11 +177,12 @@ module MathAdtToDistDst = {
}; };
}; };
// Error("Dotwise exponentiation needs two operands")
let operationParser = let operationParser =
( (
name: string, name: string,
args: result(array(ExpressionTypes.ExpressionTree.node), string), args: result(array(ExpressionTypes.ExpressionTree.node), string),
) => { ):result(ExpressionTypes.ExpressionTree.node,string) => {
let toOkAlgebraic = r => Ok(`AlgebraicCombination(r)); let toOkAlgebraic = r => Ok(`AlgebraicCombination(r));
let toOkPointwise = r => Ok(`PointwiseCombination(r)); let toOkPointwise = r => Ok(`PointwiseCombination(r));
let toOkTruncate = r => Ok(`Truncate(r)); let toOkTruncate = r => Ok(`Truncate(r));
@ -195,6 +196,8 @@ module MathAdtToDistDst = {
| ("subtract", _) => Error("Subtraction needs two operands") | ("subtract", _) => Error("Subtraction needs two operands")
| ("multiply", [|l, r|]) => toOkAlgebraic((`Multiply, l, r)) | ("multiply", [|l, r|]) => toOkAlgebraic((`Multiply, l, r))
| ("multiply", _) => Error("Multiplication needs two operands") | ("multiply", _) => Error("Multiplication needs two operands")
| ("pow", [|l,r|]) => toOkAlgebraic((`Exponentiate, l, r))
| ("pow", _) => Error("Exponentiation needs two operands")
| ("dotMultiply", [|l, r|]) => toOkPointwise((`Multiply, l, r)) | ("dotMultiply", [|l, r|]) => toOkPointwise((`Multiply, l, r))
| ("dotMultiply", _) => | ("dotMultiply", _) =>
Error("Dotwise multiplication needs two operands") Error("Dotwise multiplication needs two operands")
@ -203,7 +206,6 @@ module MathAdtToDistDst = {
Error("Dotwise addition needs two operands") Error("Dotwise addition needs two operands")
| ("divide", [|l, r|]) => toOkAlgebraic((`Divide, l, r)) | ("divide", [|l, r|]) => toOkAlgebraic((`Divide, l, r))
| ("divide", _) => Error("Division needs two operands") | ("divide", _) => Error("Division needs two operands")
| ("pow", _) => Error("Exponentiation is not yet supported.")
| ("leftTruncate", [|d, `SymbolicDist(`Float(lc))|]) => | ("leftTruncate", [|d, `SymbolicDist(`Float(lc))|]) =>
toOkTruncate((Some(lc), None, d)) toOkTruncate((Some(lc), None, d))
| ("leftTruncate", _) => | ("leftTruncate", _) =>

View File

@ -7,6 +7,7 @@ module Algebraic = {
| `Add => (+.) | `Add => (+.)
| `Subtract => (-.) | `Subtract => (-.)
| `Multiply => ( *. ) | `Multiply => ( *. )
| `Exponentiate => ( ** )
| `Divide => (/.); | `Divide => (/.);
let applyFn = (t, f1, f2) => { let applyFn = (t, f1, f2) => {
@ -21,6 +22,7 @@ module Algebraic = {
| `Add => "+" | `Add => "+"
| `Subtract => "-" | `Subtract => "-"
| `Multiply => "*" | `Multiply => "*"
| `Exponentiate => ( "**" )
| `Divide => "/"; | `Divide => "/";
let format = (a, b, c) => b ++ " " ++ toString(a) ++ " " ++ c; let format = (a, b, c) => b ++ " " ++ toString(a) ++ " " ++ c;

View File

@ -125,7 +125,7 @@ module Internals = {
let inputsToShape = (inputs: inputs) => { let inputsToShape = (inputs: inputs) => {
MathJsParser.fromString(inputs.guesstimatorString) MathJsParser.fromString(inputs.guesstimatorString)
|> E.R.bind(_, g => runProgram(inputs, g)) |> E.R.bind(_, g => runProgram(inputs, g))
|> E.R.bind(_, r => E.A.last(r) |> E.O.toResult("No rendered lines")); |> E.R.bind(_, r => E.A.last(r) |> E.O.toResult("No rendered lines") |> E.R.fmap(Shape.T.normalize));
}; };
let outputToDistPlus = (inputs: Inputs.inputs, shape: DistTypes.shape) => { let outputToDistPlus = (inputs: Inputs.inputs, shape: DistTypes.shape) => {