Added normal from90PercentCI for distributions that are at 0 or below

This commit is contained in:
Ozzie Gooen 2020-04-30 11:18:33 +01:00
parent 77c9ce09be
commit 5129ff20d5
2 changed files with 68 additions and 43 deletions

View File

@ -111,12 +111,12 @@ module MathAdtToDistDst = {
let to_: array(arg) => result(SymbolicDist.bigDist, string) = let to_: array(arg) => result(SymbolicDist.bigDist, string) =
fun fun
| [|Value(low), Value(high)|] when low <= 0.0 && low < high=> {
Ok(`Simple(SymbolicDist.Normal.from90PercentCI(low, high)));
}
| [|Value(low), Value(high)|] when low < high => { | [|Value(low), Value(high)|] when low < high => {
Ok(`Simple(SymbolicDist.Lognormal.from90PercentCI(low, high))); Ok(`Simple(SymbolicDist.Lognormal.from90PercentCI(low, high)));
} }
| [|Value(low), _|] when low <= 0.0 => {
Error("Low value cannot be less than 0.");
}
| [|Value(_), Value(_)|] => | [|Value(_), Value(_)|] =>
Error("Low value must be less than high value.") Error("Low value must be less than high value.")
| _ => Error("Wrong number of variables in lognormal distribution"); | _ => Error("Wrong number of variables in lognormal distribution");

View File

@ -31,7 +31,10 @@ type triangular = {
high: float, high: float,
}; };
type continuousShape = {pdf: DistTypes.continuousShape, cdf: DistTypes.continuousShape} type continuousShape = {
pdf: DistTypes.continuousShape,
cdf: DistTypes.continuousShape,
};
type contType = [ | `Continuous | `Discrete]; type contType = [ | `Continuous | `Discrete];
@ -53,12 +56,14 @@ type bigDist = [ | `Simple(dist) | `PointwiseCombination(pointwiseAdd)];
module ContinuousShape = { module ContinuousShape = {
type t = continuousShape; type t = continuousShape;
let make = (pdf, cdf):t => ({pdf, cdf}); let make = (pdf, cdf): t => {pdf, cdf};
let pdf = (x, t: t) => Distributions.Continuous.T.xToY(x,t.pdf).continuous let pdf = (x, t: t) =>
let inv = (p, t: t) => Distributions.Continuous.T.xToY(p,t.pdf).continuous Distributions.Continuous.T.xToY(x, t.pdf).continuous;
let inv = (p, t: t) =>
Distributions.Continuous.T.xToY(p, t.pdf).continuous;
// TODO: Fix the sampling, to have it work correctly. // TODO: Fix the sampling, to have it work correctly.
let sample = (t:t) => 3.0; let sample = (t: t) => 3.0;
let toString = (t) => {j|CustomContinuousShape|j}; let toString = t => {j|CustomContinuousShape|j};
let contType: contType = `Continuous; let contType: contType = `Continuous;
}; };
@ -92,6 +97,12 @@ module Triangular = {
module Normal = { module Normal = {
type t = normal; type t = normal;
let pdf = (x, t: t) => Jstat.normal##pdf(x, t.mean, t.stdev); let pdf = (x, t: t) => Jstat.normal##pdf(x, t.mean, t.stdev);
let from90PercentCI = (low, high) => {
let mean = E.A.Floats.mean([|low, high|]);
let stdev = (high -. low) /. 1.645;
`Normal({mean, stdev});
};
let inv = (p, t: t) => Jstat.normal##inv(p, t.mean, t.stdev); let inv = (p, t: t) => Jstat.normal##inv(p, t.mean, t.stdev);
let sample = (t: t) => Jstat.normal##sample(t.mean, t.stdev); let sample = (t: t) => Jstat.normal##sample(t.mean, t.stdev);
let toString = ({mean, stdev}: t) => {j|Normal($mean,$stdev)|j}; let toString = ({mean, stdev}: t) => {j|Normal($mean,$stdev)|j};
@ -167,10 +178,10 @@ module GenericSimple = {
| `Uniform(n) => Uniform.pdf(x, n) | `Uniform(n) => Uniform.pdf(x, n)
| `Beta(n) => Beta.pdf(x, n) | `Beta(n) => Beta.pdf(x, n)
| `Float(n) => Float.pdf(x, n) | `Float(n) => Float.pdf(x, n)
| `ContinuousShape(n) => ContinuousShape.pdf(x,n) | `ContinuousShape(n) => ContinuousShape.pdf(x, n)
}; };
let contType = (dist:dist):contType => let contType = (dist: dist): contType =>
switch (dist) { switch (dist) {
| `Normal(_) => Normal.contType | `Normal(_) => Normal.contType
| `Triangular(_) => Triangular.contType | `Triangular(_) => Triangular.contType
@ -193,7 +204,7 @@ module GenericSimple = {
| `Uniform(n) => Uniform.inv(x, n) | `Uniform(n) => Uniform.inv(x, n)
| `Beta(n) => Beta.inv(x, n) | `Beta(n) => Beta.inv(x, n)
| `Float(n) => Float.inv(x, n) | `Float(n) => Float.inv(x, n)
| `ContinuousShape(n) => ContinuousShape.inv(x,n) | `ContinuousShape(n) => ContinuousShape.inv(x, n)
}; };
let sample: dist => float = let sample: dist => float =
@ -206,7 +217,7 @@ module GenericSimple = {
| `Uniform(n) => Uniform.sample(n) | `Uniform(n) => Uniform.sample(n)
| `Beta(n) => Beta.sample(n) | `Beta(n) => Beta.sample(n)
| `Float(n) => Float.sample(n) | `Float(n) => Float.sample(n)
| `ContinuousShape(n) => ContinuousShape.sample(n) | `ContinuousShape(n) => ContinuousShape.sample(n);
let toString: dist => string = let toString: dist => string =
fun fun
@ -218,7 +229,7 @@ module GenericSimple = {
| `Uniform(n) => Uniform.toString(n) | `Uniform(n) => Uniform.toString(n)
| `Beta(n) => Beta.toString(n) | `Beta(n) => Beta.toString(n)
| `Float(n) => Float.toString(n) | `Float(n) => Float.toString(n)
| `ContinuousShape(n) => ContinuousShape.toString(n) | `ContinuousShape(n) => ContinuousShape.toString(n);
let min: dist => float = let min: dist => float =
fun fun
@ -229,7 +240,7 @@ module GenericSimple = {
| `Lognormal(n) => Lognormal.inv(minCdfValue, n) | `Lognormal(n) => Lognormal.inv(minCdfValue, n)
| `Uniform({low}) => low | `Uniform({low}) => low
| `Beta(n) => Beta.inv(minCdfValue, n) | `Beta(n) => Beta.inv(minCdfValue, n)
| `ContinuousShape(n) => ContinuousShape.inv(minCdfValue,n) | `ContinuousShape(n) => ContinuousShape.inv(minCdfValue, n)
| `Float(n) => n; | `Float(n) => n;
let max: dist => float = let max: dist => float =
@ -240,7 +251,7 @@ module GenericSimple = {
| `Normal(n) => Normal.inv(maxCdfValue, n) | `Normal(n) => Normal.inv(maxCdfValue, n)
| `Lognormal(n) => Lognormal.inv(maxCdfValue, n) | `Lognormal(n) => Lognormal.inv(maxCdfValue, n)
| `Beta(n) => Beta.inv(maxCdfValue, n) | `Beta(n) => Beta.inv(maxCdfValue, n)
| `ContinuousShape(n) => ContinuousShape.inv(maxCdfValue,n) | `ContinuousShape(n) => ContinuousShape.inv(maxCdfValue, n)
| `Uniform({high}) => high | `Uniform({high}) => high
| `Float(n) => n; | `Float(n) => n;
@ -257,16 +268,15 @@ module GenericSimple = {
let toShape = let toShape =
(~xSelection: [ | `Linear | `ByWeight]=`Linear, dist: dist, sampleCount) (~xSelection: [ | `Linear | `ByWeight]=`Linear, dist: dist, sampleCount)
: DistTypes.shape => { : DistTypes.shape => {
switch(dist){ switch (dist) {
| `ContinuousShape(n) => n.pdf |> Distributions.Continuous.T.toShape | `ContinuousShape(n) => n.pdf |> Distributions.Continuous.T.toShape
| dist => { | dist =>
let xs = interpolateXs(~xSelection, dist, sampleCount); let xs = interpolateXs(~xSelection, dist, sampleCount);
let ys = xs |> E.A.fmap(r => pdf(r, dist)); let ys = xs |> E.A.fmap(r => pdf(r, dist));
XYShape.T.fromArrays(xs, ys) XYShape.T.fromArrays(xs, ys)
|> Distributions.Continuous.make(`Linear, _) |> Distributions.Continuous.make(`Linear, _)
|> Distributions.Continuous.T.toShape; |> Distributions.Continuous.T.toShape;
} };
}
}; };
}; };
@ -289,17 +299,26 @@ module PointwiseAddDistributionsWeighted = {
let max = (dists: t) => let max = (dists: t) =>
dists |> E.A.fmap(d => d |> fst |> GenericSimple.max) |> E.A.max; dists |> E.A.fmap(d => d |> fst |> GenericSimple.max) |> E.A.max;
let discreteShape = (dists:t, sampleCount: int) => { let discreteShape = (dists: t, sampleCount: int) => {
let discrete = dists |> E.A.fmap((((r,e)) => r |> fun let discrete =
| `Float(r) => Some((r,e)) dists
| _ => None |> E.A.fmap(((r, e)) =>
)) |> E.A.O.concatSomes r
|> E.A.fmap(((x, y)):DistTypes.xyShape => ({xs: [|x|], ys: [|y|]})) |> (
|> Distributions.Discrete.reduce((+.)) fun
discrete | `Float(r) => Some((r, e))
} | _ => None
)
)
|> E.A.O.concatSomes
|> E.A.fmap(((x, y)) =>
({xs: [|x|], ys: [|y|]}: DistTypes.xyShape)
)
|> Distributions.Discrete.reduce((+.));
discrete;
};
let continuousShape = (dists:t, sampleCount: int) => { let continuousShape = (dists: t, sampleCount: int) => {
let xs = let xs =
dists dists
|> E.A.fmap(r => |> E.A.fmap(r =>
@ -314,16 +333,22 @@ module PointwiseAddDistributionsWeighted = {
|> E.A.concatMany; |> E.A.concatMany;
xs |> Array.fast_sort(compare); xs |> Array.fast_sort(compare);
let ys = xs |> E.A.fmap(pdf(_, dists)); let ys = xs |> E.A.fmap(pdf(_, dists));
XYShape.T.fromArrays(xs, ys) XYShape.T.fromArrays(xs, ys) |> Distributions.Continuous.make(`Linear, _);
|> Distributions.Continuous.make(`Linear, _) };
}
let toShape = (dists: t, sampleCount: int) => { let toShape = (dists: t, sampleCount: int) => {
let normalized = normalizeWeights(dists); let normalized = normalizeWeights(dists);
let continuous = normalized |> E.A.filter(((r,_)) => GenericSimple.contType(r) == `Continuous) |> continuousShape(_, sampleCount); let continuous =
let discrete = normalized |> E.A.filter(((r,_)) => GenericSimple.contType(r) == `Discrete) |> discreteShape(_, sampleCount); normalized
let shape = MixedShapeBuilder.buildSimple(~continuous=Some(continuous), ~discrete); |> E.A.filter(((r, _)) => GenericSimple.contType(r) == `Continuous)
shape |> E.O.toExt("") |> continuousShape(_, sampleCount);
let discrete =
normalized
|> E.A.filter(((r, _)) => GenericSimple.contType(r) == `Discrete)
|> discreteShape(_, sampleCount);
let shape =
MixedShapeBuilder.buildSimple(~continuous=Some(continuous), ~discrete);
shape |> E.O.toExt("");
}; };
let toString = (dists: t) => { let toString = (dists: t) => {