Merge pull request #295 from quantified-uncertainty/add-isNormalized

Added isNormalized function, for testing
This commit is contained in:
Ozzie Gooen 2022-04-15 16:30:56 -04:00 committed by GitHub
commit fe2be53d04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 61 additions and 3 deletions

View File

@ -28,6 +28,7 @@ import {
Constructors_cdf, Constructors_cdf,
Constructors_inv, Constructors_inv,
Constructors_normalize, Constructors_normalize,
Constructors_isNormalized,
Constructors_toPointSet, Constructors_toPointSet,
Constructors_toSampleSet, Constructors_toSampleSet,
Constructors_truncate, Constructors_truncate,
@ -189,6 +190,10 @@ export class Distribution {
return Constructors_inv({ env: this.env }, this.t, n); return Constructors_inv({ env: this.env }, this.t, n);
} }
isNormalized(): result<boolean, distributionError> {
return Constructors_isNormalized({ env: this.env }, this.t);
}
normalize(): result<Distribution, distributionError> { normalize(): result<Distribution, distributionError> {
return this.mapResultDist( return this.mapResultDist(
Constructors_normalize({ env: this.env }, this.t) Constructors_normalize({ env: this.env }, this.t)

View File

@ -13,6 +13,7 @@ type outputType =
| Dist(genericDist) | Dist(genericDist)
| Float(float) | Float(float)
| String(string) | String(string)
| Bool(bool)
| GenDistError(error) | GenDistError(error)
/* /*
@ -66,6 +67,18 @@ module OutputLocal = {
| e => Error(toErrorOrUnreachable(e)) | e => Error(toErrorOrUnreachable(e))
} }
let toBool = (t: t) =>
switch t {
| Bool(d) => Some(d)
| _ => None
}
let toBoolR = (t: t): result<bool, error> =>
switch t {
| Bool(r) => Ok(r)
| e => Error(toErrorOrUnreachable(e))
}
//This is used to catch errors in other switch statements. //This is used to catch errors in other switch statements.
let fromResult = (r: result<t, error>): outputType => let fromResult = (r: result<t, error>): outputType =>
switch r { switch r {
@ -107,8 +120,8 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
(), (),
)->OutputLocal.toDistR )->OutputLocal.toDistR
let fromDistFn = (subFnName: GenericDist_Types.Operation.fromDist, dist: genericDist) => let fromDistFn = (subFnName: GenericDist_Types.Operation.fromDist, dist: genericDist) => {
switch subFnName { let response = switch subFnName {
| ToFloat(distToFloatOperation) => | ToFloat(distToFloatOperation) =>
GenericDist.toFloatOperation(dist, ~toPointSetFn, ~distToFloatOperation) GenericDist.toFloatOperation(dist, ~toPointSetFn, ~distToFloatOperation)
->E.R2.fmap(r => Float(r)) ->E.R2.fmap(r => Float(r))
@ -123,6 +136,7 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
Dist(dist) Dist(dist)
} }
| ToDist(Normalize) => dist->GenericDist.normalize->Dist | ToDist(Normalize) => dist->GenericDist.normalize->Dist
| ToBool(IsNormalized) => dist->GenericDist.isNormalized->Bool
| ToDist(Truncate(leftCutoff, rightCutoff)) => | ToDist(Truncate(leftCutoff, rightCutoff)) =>
GenericDist.truncate(~toPointSetFn, ~leftCutoff, ~rightCutoff, dist, ()) GenericDist.truncate(~toPointSetFn, ~leftCutoff, ~rightCutoff, dist, ())
->E.R2.fmap(r => Dist(r)) ->E.R2.fmap(r => Dist(r))
@ -154,6 +168,8 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
->E.R2.fmap(r => Dist(r)) ->E.R2.fmap(r => Dist(r))
->OutputLocal.fromResult ->OutputLocal.fromResult
} }
response
}
switch functionCallInfo { switch functionCallInfo {
| FromDist(subFnName, dist) => fromDistFn(subFnName, dist) | FromDist(subFnName, dist) => fromDistFn(subFnName, dist)
@ -201,6 +217,7 @@ module Constructors = {
let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR
let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR let pdf = (~env, dist, f) => C.pdf(dist, f)->run(~env)->toFloatR
let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR let normalize = (~env, dist) => C.normalize(dist)->run(~env)->toDistR
let isNormalized = (~env, dist) => C.isNormalized(dist)->run(~env)->toBoolR
let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR
let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR
let truncate = (~env, dist, leftCutoff, rightCutoff) => let truncate = (~env, dist, leftCutoff, rightCutoff) =>

View File

@ -11,6 +11,7 @@ type outputType =
| Dist(genericDist) | Dist(genericDist)
| Float(float) | Float(float)
| String(string) | String(string)
| Bool(bool)
| GenDistError(error) | GenDistError(error)
@genType @genType
@ -34,6 +35,8 @@ module Output: {
let toFloatR: t => result<float, error> let toFloatR: t => result<float, error>
let toString: t => option<string> let toString: t => option<string>
let toStringR: t => result<string, error> let toStringR: t => result<string, error>
let toBool: t => option<bool>
let toBoolR: t => result<bool, error>
let toError: t => option<error> let toError: t => option<error>
let fmap: (~env: env, t, GenericDist_Types.Operation.singleParamaterFunction) => t let fmap: (~env: env, t, GenericDist_Types.Operation.singleParamaterFunction) => t
} }
@ -52,6 +55,8 @@ module Constructors: {
@genType @genType
let normalize: (~env: env, genericDist) => result<genericDist, error> let normalize: (~env: env, genericDist) => result<genericDist, error>
@genType @genType
let isNormalized: (~env: env, genericDist) => result<bool, error>
@genType
let toPointSet: (~env: env, genericDist) => result<genericDist, error> let toPointSet: (~env: env, genericDist) => result<genericDist, error>
@genType @genType
let toSampleSet: (~env: env, genericDist, int) => result<genericDist, error> let toSampleSet: (~env: env, genericDist, int) => result<genericDist, error>

View File

@ -32,6 +32,15 @@ let normalize = (t: t): t =>
| SampleSet(_) => t | SampleSet(_) => t
} }
let integralEndY = (t: t): float =>
switch t {
| PointSet(r) => PointSetDist.T.integralEndY(r)
| Symbolic(_) => 1.0
| SampleSet(_) => 1.0
}
let isNormalized = (t: t): bool => Js.Math.abs_float(integralEndY(t) -. 1.0) < 1e-7
let toFloatOperation = ( let toFloatOperation = (
t, t,
~toPointSetFn: toPointSetFn, ~toPointSetFn: toPointSetFn,

View File

@ -15,6 +15,8 @@ let toString: t => string
let normalize: t => t let normalize: t => t
let isNormalized: t => bool
let toFloatOperation: ( let toFloatOperation: (
t, t,
~toPointSetFn: toPointSetFn, ~toPointSetFn: toPointSetFn,

View File

@ -71,11 +71,14 @@ module Operation = {
| ToString | ToString
| ToSparkline(int) | ToSparkline(int)
type toBool = IsNormalized
type fromDist = type fromDist =
| ToFloat(toFloat) | ToFloat(toFloat)
| ToDist(toDist) | ToDist(toDist)
| ToDistCombination(direction, arithmeticOperation, [#Dist(genericDist) | #Float(float)]) | ToDistCombination(direction, arithmeticOperation, [#Dist(genericDist) | #Float(float)])
| ToString(toString) | ToString(toString)
| ToBool(toBool)
type singleParamaterFunction = type singleParamaterFunction =
| FromDist(fromDist) | FromDist(fromDist)
@ -101,6 +104,7 @@ module Operation = {
| ToDist(Inspect) => `inspect` | ToDist(Inspect) => `inspect`
| ToString(ToString) => `toString` | ToString(ToString) => `toString`
| ToString(ToSparkline(n)) => `toSparkline(${E.I.toString(n)})` | ToString(ToSparkline(n)) => `toSparkline(${E.I.toString(n)})`
| ToBool(IsNormalized) => `isNormalized`
| ToDistCombination(Algebraic, _, _) => `algebraic` | ToDistCombination(Algebraic, _, _) => `algebraic`
| ToDistCombination(Pointwise, _, _) => `pointwise` | ToDistCombination(Pointwise, _, _) => `pointwise`
} }
@ -131,6 +135,7 @@ module Constructors = {
let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist) let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist)
let pdf = (dist, x): t => FromDist(ToFloat(#Pdf(x)), dist) let pdf = (dist, x): t => FromDist(ToFloat(#Pdf(x)), dist)
let normalize = (dist): t => FromDist(ToDist(Normalize), dist) let normalize = (dist): t => FromDist(ToDist(Normalize), dist)
let isNormalized = (dist): t => FromDist(ToBool(IsNormalized), dist)
let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist) let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist)
let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist) let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist)
let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist) let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist)

View File

@ -47,6 +47,7 @@ module Dist = (T: dist) => {
let truncate = T.truncate let truncate = T.truncate
let mean = T.mean let mean = T.mean
let variance = T.variance let variance = T.variance
let integralEndY = T.integralEndY
let updateIntegralCache = T.updateIntegralCache let updateIntegralCache = T.updateIntegralCache

View File

@ -1,9 +1,11 @@
module ExpressionValue = ReducerInterface_ExpressionValue module ExpressionValue = ReducerInterface_ExpressionValue
type expressionValue = ReducerInterface_ExpressionValue.expressionValue type expressionValue = ReducerInterface_ExpressionValue.expressionValue
let defaultSampleCount = 10000
let runGenericOperation = DistributionOperation.run( let runGenericOperation = DistributionOperation.run(
~env={ ~env={
sampleCount: 1000, sampleCount: defaultSampleCount,
xyPointLength: 1000, xyPointLength: 1000,
}, },
) )
@ -52,6 +54,13 @@ module Helpers = {
FromDist(GenericDist_Types.Operation.ToString(fnCall), dist)->runGenericOperation->Some FromDist(GenericDist_Types.Operation.ToString(fnCall), dist)->runGenericOperation->Some
} }
let toBoolFn = (
fnCall: GenericDist_Types.Operation.toBool,
dist: GenericDist_Types.genericDist,
) => {
FromDist(GenericDist_Types.Operation.ToBool(fnCall), dist)->runGenericOperation->Some
}
let toDistFn = (fnCall: GenericDist_Types.Operation.toDist, dist) => { let toDistFn = (fnCall: GenericDist_Types.Operation.toDist, dist) => {
FromDist(GenericDist_Types.Operation.ToDist(fnCall), dist)->runGenericOperation->Some FromDist(GenericDist_Types.Operation.ToDist(fnCall), dist)->runGenericOperation->Some
} }
@ -193,12 +202,16 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
// https://mathjs.org/docs/reference/functions/exp.html // https://mathjs.org/docs/reference/functions/exp.html
Helpers.twoDiststoDistFn(Algebraic, "pow", GenericDist.fromFloat(Math.e), a)->Some Helpers.twoDiststoDistFn(Algebraic, "pow", GenericDist.fromFloat(Math.e), a)->Some
| ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist) | ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist)
| ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist)
| ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist) | ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist)
| ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist) | ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist)
| ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist) | ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist)
| ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist) | ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist)
| ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) => | ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) =>
Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist) Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist)
| ("toSampleSet", [EvDistribution(dist)]) =>
Helpers.toDistFn(ToSampleSet(defaultSampleCount), dist)
| ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist)
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) => | ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) =>
Helpers.toDistFn(Truncate(Some(float), None), dist) Helpers.toDistFn(Truncate(Some(float), None), dist)
| ("truncateRight", [EvDistribution(dist), EvNumber(float)]) => | ("truncateRight", [EvDistribution(dist), EvNumber(float)]) =>
@ -244,6 +257,7 @@ let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
| Dist(d) => Ok(ReducerInterface_ExpressionValue.EvDistribution(d)) | Dist(d) => Ok(ReducerInterface_ExpressionValue.EvDistribution(d))
| Float(d) => Ok(EvNumber(d)) | Float(d) => Ok(EvNumber(d))
| String(d) => Ok(EvString(d)) | String(d) => Ok(EvString(d))
| Bool(d) => Ok(EvBool(d))
| GenDistError(NotYetImplemented) => Error(RETodo("Function not yet implemented")) | GenDistError(NotYetImplemented) => Error(RETodo("Function not yet implemented"))
| GenDistError(Unreachable) => Error(RETodo("Unreachable")) | GenDistError(Unreachable) => Error(RETodo("Unreachable"))
| GenDistError(DistributionVerticalShiftIsInvalid) => | GenDistError(DistributionVerticalShiftIsInvalid) =>