Pulled out XYShape to be more separate
This commit is contained in:
parent
60b760f0cd
commit
a2729f34cb
|
@ -1,7 +1,7 @@
|
||||||
import {runAll} from '../rescript/ProgramEvaluator.gen';
|
import {runAll} from '../rescript/ProgramEvaluator.gen';
|
||||||
import type { Inputs_SamplingInputs_t as SamplingInputs, exportEnv, exportType, exportDistribution} from '../rescript/ProgramEvaluator.gen';
|
import type { Inputs_SamplingInputs_t as SamplingInputs, exportEnv, exportType, exportDistribution} from '../rescript/ProgramEvaluator.gen';
|
||||||
export type { SamplingInputs, exportEnv, exportDistribution }
|
export type { SamplingInputs, exportEnv, exportDistribution }
|
||||||
export type {t as DistPlus} from '../rescript/pointSetDist/DistPlus.gen';
|
export type {t as DistPlus} from '../rescript/OldInterpreter/DistPlus.gen';
|
||||||
|
|
||||||
export let defaultSamplingInputs : SamplingInputs = {
|
export let defaultSamplingInputs : SamplingInputs = {
|
||||||
sampleCount : 10000,
|
sampleCount : 10000,
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
type genericDist =
|
||||||
|
| PointSet(PointSetTypes.pointSetDist)
|
||||||
|
| SampleSet(array<float>)
|
||||||
|
| Symbolic(SymbolicDistTypes.symbolicDist)
|
||||||
|
|
||||||
|
type error =
|
||||||
|
| NotYetImplemented
|
||||||
|
| Unreachable
|
||||||
|
| DistributionVerticalShiftIsInvalid
|
||||||
|
| Other(string)
|
||||||
|
|
||||||
|
module Operation = {
|
||||||
|
type direction =
|
||||||
|
| Algebraic
|
||||||
|
| Pointwise
|
||||||
|
|
||||||
|
type arithmeticOperation = [
|
||||||
|
| #Add
|
||||||
|
| #Multiply
|
||||||
|
| #Subtract
|
||||||
|
| #Divide
|
||||||
|
| #Exponentiate
|
||||||
|
| #Logarithm
|
||||||
|
]
|
||||||
|
|
||||||
|
let arithmeticToFn = (arithmetic: arithmeticOperation) =>
|
||||||
|
switch arithmetic {
|
||||||
|
| #Add => \"+."
|
||||||
|
| #Multiply => \"*."
|
||||||
|
| #Subtract => \"-."
|
||||||
|
| #Exponentiate => \"**"
|
||||||
|
| #Divide => \"/."
|
||||||
|
| #Logarithm => (a, b) => log(a) /. log(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type toFloat = [
|
||||||
|
| #Cdf(float)
|
||||||
|
| #Inv(float)
|
||||||
|
| #Pdf(float)
|
||||||
|
| #Mean
|
||||||
|
| #Sample
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
module DistributionOperation = {
|
||||||
|
type toDist =
|
||||||
|
| Normalize
|
||||||
|
| ToPointSet
|
||||||
|
| ToSampleSet(int)
|
||||||
|
| Truncate(option<float>, option<float>)
|
||||||
|
| Inspect
|
||||||
|
|
||||||
|
type toFloatArray = Sample(int)
|
||||||
|
|
||||||
|
type fromDist =
|
||||||
|
| ToFloat(Operation.toFloat)
|
||||||
|
| ToDist(toDist)
|
||||||
|
| ToDistCombination(Operation.direction, Operation.arithmeticOperation, [#Dist(genericDist) | #Float(float)])
|
||||||
|
| ToString
|
||||||
|
|
||||||
|
type singleParamaterFunction =
|
||||||
|
| FromDist(fromDist)
|
||||||
|
| FromFloat(fromDist)
|
||||||
|
|
||||||
|
type genericFunctionCallInfo =
|
||||||
|
| FromDist(fromDist, genericDist)
|
||||||
|
| FromFloat(fromDist, float)
|
||||||
|
| Mixture(array<(genericDist, float)>)
|
||||||
|
|
||||||
|
let distCallToString = (distFunction: fromDist): string =>
|
||||||
|
switch distFunction {
|
||||||
|
| ToFloat(#Cdf(r)) => `cdf(${E.Float.toFixed(r)})`
|
||||||
|
| ToFloat(#Inv(r)) => `inv(${E.Float.toFixed(r)})`
|
||||||
|
| ToFloat(#Mean) => `mean`
|
||||||
|
| ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})`
|
||||||
|
| ToFloat(#Sample) => `sample`
|
||||||
|
| ToDist(Normalize) => `normalize`
|
||||||
|
| ToDist(ToPointSet) => `toPointSet`
|
||||||
|
| ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})`
|
||||||
|
| ToDist(Truncate(_, _)) => `truncate`
|
||||||
|
| ToDist(Inspect) => `inspect`
|
||||||
|
| ToString => `toString`
|
||||||
|
| ToDistCombination(Algebraic, _, _) => `algebraic`
|
||||||
|
| ToDistCombination(Pointwise, _, _) => `pointwise`
|
||||||
|
}
|
||||||
|
|
||||||
|
let toString = (d: genericFunctionCallInfo): string =>
|
||||||
|
switch d {
|
||||||
|
| FromDist(f, _) | FromFloat(f, _) => distCallToString(f)
|
||||||
|
| Mixture(_) => `mixture`
|
||||||
|
}
|
||||||
|
}
|
|
@ -118,13 +118,14 @@ let combineShapesContinuousContinuous = (
|
||||||
| #Logarithm => (m1, m2) => log(m1) /. log(m2)
|
| #Logarithm => (m1, m2) => log(m1) /. log(m2)
|
||||||
} // 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
|
// TODO: I don't know what the variances are for exponentatiation or logarithms
|
||||||
// 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 = switch op {
|
let combineVariancesFn = switch op {
|
||||||
| #Add => (v1, v2, _, _) => v1 +. v2
|
| #Add => (v1, v2, _, _) => v1 +. v2
|
||||||
| #Subtract => (v1, v2, _, _) => v1 +. v2
|
| #Subtract => (v1, v2, _, _) => v1 +. v2
|
||||||
| #Multiply => (v1, v2, m1, m2) => v1 *. v2 +. v1 *. m2 ** 2. +. v2 *. m1 ** 2.
|
| #Multiply => (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.
|
| #Exponentiate => (v1, v2, m1, m2) => v1 *. v2 +. v1 *. m2 ** 2. +. v2 *. m1 ** 2.
|
||||||
|
| #Logarithm => (v1, v2, m1, m2) => v1 *. v2 +. v1 *. m2 ** 2. +. v2 *. m1 ** 2.
|
||||||
| #Divide => (v1, vInv2, m1, mInv2) => v1 *. vInv2 +. v1 *. mInv2 ** 2. +. vInv2 *. m1 ** 2.
|
| #Divide => (v1, vInv2, m1, mInv2) => v1 *. vInv2 +. v1 *. mInv2 ** 2. +. vInv2 *. m1 ** 2.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,47 @@
|
||||||
open Distributions
|
open Distributions
|
||||||
|
|
||||||
type t = PointSetTypes.continuousShape
|
type t = PointSetTypes.continuousShape
|
||||||
|
|
||||||
|
module Analysis = {
|
||||||
|
let integrate = (
|
||||||
|
~indefiniteIntegralStepwise=(p, h1) => h1 *. p,
|
||||||
|
~indefiniteIntegralLinear=(p, a, b) => a *. p +. b *. p ** 2.0 /. 2.0,
|
||||||
|
t: t,
|
||||||
|
): float => {
|
||||||
|
let xs = t.xyShape.xs
|
||||||
|
let ys = t.xyShape.ys
|
||||||
|
|
||||||
|
E.A.reducei(xs, 0.0, (acc, _x, i) => {
|
||||||
|
let areaUnderIntegral = // TODO Take this switch statement out of the loop body
|
||||||
|
switch (t.interpolation, i) {
|
||||||
|
| (_, 0) => 0.0
|
||||||
|
| (#Stepwise, _) =>
|
||||||
|
indefiniteIntegralStepwise(xs[i], ys[i - 1]) -.
|
||||||
|
indefiniteIntegralStepwise(xs[i - 1], ys[i - 1])
|
||||||
|
| (#Linear, _) =>
|
||||||
|
let x1 = xs[i - 1]
|
||||||
|
let x2 = xs[i]
|
||||||
|
if x1 == x2 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
let h1 = ys[i - 1]
|
||||||
|
let h2 = ys[i]
|
||||||
|
let b = (h1 -. h2) /. (x1 -. x2)
|
||||||
|
let a = h1 -. b *. x1
|
||||||
|
indefiniteIntegralLinear(x2, a, b) -. indefiniteIntegralLinear(x1, a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
acc +. areaUnderIntegral
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let getMeanOfSquares = (t: t) => {
|
||||||
|
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 3.0 /. 3.0 +. b *. p ** 4.0 /. 4.0
|
||||||
|
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 3.0 /. 3.0
|
||||||
|
integrate(~indefiniteIntegralStepwise, ~indefiniteIntegralLinear, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let getShape = (t: t) => t.xyShape
|
let getShape = (t: t) => t.xyShape
|
||||||
let interpolation = (t: t) => t.interpolation
|
let interpolation = (t: t) => t.interpolation
|
||||||
let make = (~interpolation=#Linear, ~integralSumCache=None, ~integralCache=None, xyShape): t => {
|
let make = (~interpolation=#Linear, ~integralSumCache=None, ~integralCache=None, xyShape): t => {
|
||||||
|
@ -194,7 +235,7 @@ module T = Dist({
|
||||||
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 2.0 /. 2.0
|
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 2.0 /. 2.0
|
||||||
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 2.0 /. 2.0 +. b *. p ** 3.0 /. 3.0
|
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 2.0 /. 2.0 +. b *. p ** 3.0 /. 3.0
|
||||||
|
|
||||||
XYShape.Analysis.integrateContinuousShape(
|
Analysis.integrate(
|
||||||
~indefiniteIntegralStepwise,
|
~indefiniteIntegralStepwise,
|
||||||
~indefiniteIntegralLinear,
|
~indefiniteIntegralLinear,
|
||||||
t,
|
t,
|
||||||
|
@ -204,7 +245,7 @@ module T = Dist({
|
||||||
XYShape.Analysis.getVarianceDangerously(
|
XYShape.Analysis.getVarianceDangerously(
|
||||||
t,
|
t,
|
||||||
mean,
|
mean,
|
||||||
XYShape.Analysis.getMeanOfSquaresContinuousShape,
|
Analysis.getMeanOfSquares,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -209,8 +209,9 @@ module T = Dist({
|
||||||
let s = getShape(t)
|
let s = getShape(t)
|
||||||
E.A.reducei(s.xs, 0.0, (acc, x, i) => acc +. x *. s.ys[i])
|
E.A.reducei(s.xs, 0.0, (acc, x, i) => acc +. x *. s.ys[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
let variance = (t: t): float => {
|
let variance = (t: t): float => {
|
||||||
let getMeanOfSquares = t => t |> shapeMap(XYShape.Analysis.squareXYShape) |> mean
|
let getMeanOfSquares = t => t |> shapeMap(XYShape.T.square) |> mean
|
||||||
XYShape.Analysis.getVarianceDangerously(t, mean, getMeanOfSquares)
|
XYShape.Analysis.getVarianceDangerously(t, mean, getMeanOfSquares)
|
||||||
}
|
}
|
||||||
})
|
})
|
|
@ -213,8 +213,8 @@ module T = Dist({
|
||||||
|
|
||||||
let getMeanOfSquares = ({discrete, continuous}: t) => {
|
let getMeanOfSquares = ({discrete, continuous}: t) => {
|
||||||
let discreteMean =
|
let discreteMean =
|
||||||
discrete |> Discrete.shapeMap(XYShape.Analysis.squareXYShape) |> Discrete.T.mean
|
discrete |> Discrete.shapeMap(XYShape.T.square) |> Discrete.T.mean
|
||||||
let continuousMean = continuous |> XYShape.Analysis.getMeanOfSquaresContinuousShape
|
let continuousMean = continuous |> Continuous.Analysis.getMeanOfSquares
|
||||||
(discreteMean *. discreteIntegralSum +. continuousMean *. continuousIntegralSum) /.
|
(discreteMean *. discreteIntegralSum +. continuousMean *. continuousIntegralSum) /.
|
||||||
totalIntegralSum
|
totalIntegralSum
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,21 +14,10 @@ type distributionType = [
|
||||||
| #CDF
|
| #CDF
|
||||||
]
|
]
|
||||||
|
|
||||||
type xyShape = {
|
type xyShape = XYShape.xyShape;
|
||||||
xs: array<float>,
|
type interpolationStrategy = XYShape.interpolationStrategy;
|
||||||
ys: array<float>,
|
type extrapolationStrategy = XYShape.extrapolationStrategy;
|
||||||
}
|
type interpolator = XYShape.extrapolationStrategy;
|
||||||
|
|
||||||
type interpolationStrategy = [
|
|
||||||
| #Stepwise
|
|
||||||
| #Linear
|
|
||||||
]
|
|
||||||
type extrapolationStrategy = [
|
|
||||||
| #UseZero
|
|
||||||
| #UseOutermostPoints
|
|
||||||
]
|
|
||||||
|
|
||||||
type interpolator = (xyShape, int, float) => float
|
|
||||||
|
|
||||||
type rec continuousShape = {
|
type rec continuousShape = {
|
||||||
xyShape: xyShape,
|
xyShape: xyShape,
|
||||||
|
|
|
@ -1,4 +1,18 @@
|
||||||
open PointSetTypes
|
type xyShape = {
|
||||||
|
xs: array<float>,
|
||||||
|
ys: array<float>,
|
||||||
|
}
|
||||||
|
|
||||||
|
type interpolationStrategy = [
|
||||||
|
| #Stepwise
|
||||||
|
| #Linear
|
||||||
|
]
|
||||||
|
type extrapolationStrategy = [
|
||||||
|
| #UseZero
|
||||||
|
| #UseOutermostPoints
|
||||||
|
]
|
||||||
|
|
||||||
|
type interpolator = (xyShape, int, float) => float
|
||||||
|
|
||||||
let interpolate = (xMin: float, xMax: float, yMin: float, yMax: float, xIntended: float): float => {
|
let interpolate = (xMin: float, xMax: float, yMin: float, yMax: float, xIntended: float): float => {
|
||||||
let minProportion = (xMax -. xIntended) /. (xMax -. xMin)
|
let minProportion = (xMax -. xIntended) /. (xMax -. xMin)
|
||||||
|
@ -25,6 +39,7 @@ module T = {
|
||||||
let xTotalRange = (t: t) => maxX(t) -. minX(t)
|
let xTotalRange = (t: t) => maxX(t) -. minX(t)
|
||||||
let mapX = (fn, t: t): t => {xs: E.A.fmap(fn, t.xs), ys: t.ys}
|
let mapX = (fn, t: t): t => {xs: E.A.fmap(fn, t.xs), ys: t.ys}
|
||||||
let mapY = (fn, t: t): t => {xs: t.xs, ys: E.A.fmap(fn, t.ys)}
|
let mapY = (fn, t: t): t => {xs: t.xs, ys: E.A.fmap(fn, t.ys)}
|
||||||
|
let square = mapX(x => x ** 2.0)
|
||||||
let zip = ({xs, ys}: t) => Belt.Array.zip(xs, ys)
|
let zip = ({xs, ys}: t) => Belt.Array.zip(xs, ys)
|
||||||
let fromArray = ((xs, ys)): t => {xs: xs, ys: ys}
|
let fromArray = ((xs, ys)): t => {xs: xs, ys: ys}
|
||||||
let fromArrays = (xs, ys): t => {xs: xs, ys: ys}
|
let fromArrays = (xs, ys): t => {xs: xs, ys: ys}
|
||||||
|
@ -126,8 +141,8 @@ module XtoY = {
|
||||||
/* Returns a between-points-interpolating function that can be used with PointwiseCombination.combine.
|
/* Returns a between-points-interpolating function that can be used with PointwiseCombination.combine.
|
||||||
Interpolation can either be stepwise (using the value on the left) or linear. Extrapolation can be `UseZero or `UseOutermostPoints. */
|
Interpolation can either be stepwise (using the value on the left) or linear. Extrapolation can be `UseZero or `UseOutermostPoints. */
|
||||||
let continuousInterpolator = (
|
let continuousInterpolator = (
|
||||||
interpolation: PointSetTypes.interpolationStrategy,
|
interpolation: interpolationStrategy,
|
||||||
extrapolation: PointSetTypes.extrapolationStrategy,
|
extrapolation: extrapolationStrategy,
|
||||||
): interpolator =>
|
): interpolator =>
|
||||||
switch (interpolation, extrapolation) {
|
switch (interpolation, extrapolation) {
|
||||||
| (#Linear, #UseZero) =>
|
| (#Linear, #UseZero) =>
|
||||||
|
@ -392,49 +407,9 @@ let logScorePoint = (sampleCount, t1, t2) =>
|
||||||
|> E.O.fmap(Pairs.y)
|
|> E.O.fmap(Pairs.y)
|
||||||
|
|
||||||
module Analysis = {
|
module Analysis = {
|
||||||
let integrateContinuousShape = (
|
|
||||||
~indefiniteIntegralStepwise=(p, h1) => h1 *. p,
|
|
||||||
~indefiniteIntegralLinear=(p, a, b) => a *. p +. b *. p ** 2.0 /. 2.0,
|
|
||||||
t: PointSetTypes.continuousShape,
|
|
||||||
): float => {
|
|
||||||
let xs = t.xyShape.xs
|
|
||||||
let ys = t.xyShape.ys
|
|
||||||
|
|
||||||
E.A.reducei(xs, 0.0, (acc, _x, i) => {
|
|
||||||
let areaUnderIntegral = // TODO Take this switch statement out of the loop body
|
|
||||||
switch (t.interpolation, i) {
|
|
||||||
| (_, 0) => 0.0
|
|
||||||
| (#Stepwise, _) =>
|
|
||||||
indefiniteIntegralStepwise(xs[i], ys[i - 1]) -.
|
|
||||||
indefiniteIntegralStepwise(xs[i - 1], ys[i - 1])
|
|
||||||
| (#Linear, _) =>
|
|
||||||
let x1 = xs[i - 1]
|
|
||||||
let x2 = xs[i]
|
|
||||||
if x1 == x2 {
|
|
||||||
0.0
|
|
||||||
} else {
|
|
||||||
let h1 = ys[i - 1]
|
|
||||||
let h2 = ys[i]
|
|
||||||
let b = (h1 -. h2) /. (x1 -. x2)
|
|
||||||
let a = h1 -. b *. x1
|
|
||||||
indefiniteIntegralLinear(x2, a, b) -. indefiniteIntegralLinear(x1, a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acc +. areaUnderIntegral
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let getMeanOfSquaresContinuousShape = (t: PointSetTypes.continuousShape) => {
|
|
||||||
let indefiniteIntegralLinear = (p, a, b) => a *. p ** 3.0 /. 3.0 +. b *. p ** 4.0 /. 4.0
|
|
||||||
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 3.0 /. 3.0
|
|
||||||
integrateContinuousShape(~indefiniteIntegralStepwise, ~indefiniteIntegralLinear, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
let getVarianceDangerously = (t: 't, mean: 't => float, getMeanOfSquares: 't => float): float => {
|
let getVarianceDangerously = (t: 't, mean: 't => float, getMeanOfSquares: 't => float): float => {
|
||||||
let meanSquared = mean(t) ** 2.0
|
let meanSquared = mean(t) ** 2.0
|
||||||
let meanOfSquares = getMeanOfSquares(t)
|
let meanOfSquares = getMeanOfSquares(t)
|
||||||
meanOfSquares -. meanSquared
|
meanOfSquares -. meanSquared
|
||||||
}
|
}
|
||||||
|
|
||||||
let squareXYShape = T.mapX(x => x ** 2.0)
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user