Merge pull request #198 from QURIresearch/generic-sparklines
Implement generic sparklines with tests
This commit is contained in:
commit
d699c32072
|
@ -6,9 +6,19 @@ let env: DistributionOperation.env = {
|
||||||
xyPointLength: 100,
|
xyPointLength: 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
normalDist5,
|
||||||
|
normalDist10,
|
||||||
|
normalDist20,
|
||||||
|
normalDist,
|
||||||
|
uniformDist,
|
||||||
|
betaDist,
|
||||||
|
lognormalDist,
|
||||||
|
cauchyDist,
|
||||||
|
triangularDist,
|
||||||
|
exponentialDist,
|
||||||
|
} = module(GenericDist_Fixtures)
|
||||||
let mkNormal = (mean, stdev) => GenericDist_Types.Symbolic(#Normal({mean: mean, stdev: stdev}))
|
let mkNormal = (mean, stdev) => GenericDist_Types.Symbolic(#Normal({mean: mean, stdev: stdev}))
|
||||||
let normalDist5: GenericDist_Types.genericDist = mkNormal(5.0, 2.0)
|
|
||||||
let uniformDist: GenericDist_Types.genericDist = Symbolic(#Uniform({low: 9.0, high: 10.0}))
|
|
||||||
|
|
||||||
let {toFloat, toDist, toString, toError} = module(DistributionOperation.Output)
|
let {toFloat, toDist, toString, toError} = module(DistributionOperation.Output)
|
||||||
let {run} = module(DistributionOperation)
|
let {run} = module(DistributionOperation)
|
||||||
|
@ -19,6 +29,57 @@ let toExt: option<'a> => 'a = E.O.toExt(
|
||||||
"Should be impossible to reach (This error is in test file)",
|
"Should be impossible to reach (This error is in test file)",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
describe("sparkline", () => {
|
||||||
|
let runTest = (
|
||||||
|
name: string,
|
||||||
|
dist: GenericDist_Types.genericDist,
|
||||||
|
expected: DistributionOperation.outputType,
|
||||||
|
) => {
|
||||||
|
test(name, () => {
|
||||||
|
let result = DistributionOperation.run(~env, FromDist(ToString(ToSparkline(20)), dist))
|
||||||
|
expect(result)->toEqual(expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
"normal",
|
||||||
|
normalDist,
|
||||||
|
String(`▁▁▁▁▁▂▄▆▇██▇▆▄▂▁▁▁▁▁`),
|
||||||
|
)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
"uniform",
|
||||||
|
uniformDist,
|
||||||
|
String(`████████████████████`),
|
||||||
|
)
|
||||||
|
|
||||||
|
runTest("beta", betaDist, String(`▁▄▇████▇▆▅▄▃▃▂▁▁▁▁▁▁`))
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
"lognormal",
|
||||||
|
lognormalDist,
|
||||||
|
String(`▁█▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁`),
|
||||||
|
)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
"cauchy",
|
||||||
|
cauchyDist,
|
||||||
|
String(`▁▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁`),
|
||||||
|
)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
"triangular",
|
||||||
|
triangularDist,
|
||||||
|
String(`▁▁▂▃▄▅▆▇████▇▆▅▄▃▂▁▁`),
|
||||||
|
)
|
||||||
|
|
||||||
|
runTest(
|
||||||
|
"exponential",
|
||||||
|
exponentialDist,
|
||||||
|
String(`█▅▄▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁`),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
describe("toPointSet", () => {
|
describe("toPointSet", () => {
|
||||||
test("on symbolic normal distribution", () => {
|
test("on symbolic normal distribution", () => {
|
||||||
let result =
|
let result =
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
let normalDist5: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 5.0, stdev: 2.0}))
|
||||||
|
let normalDist10: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 10.0, stdev: 2.0}))
|
||||||
|
let normalDist20: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 20.0, stdev: 2.0}))
|
||||||
|
let normalDist: GenericDist_Types.genericDist = normalDist5
|
||||||
|
|
||||||
|
let betaDist: GenericDist_Types.genericDist = Symbolic(#Beta({alpha: 2.0, beta: 5.0}))
|
||||||
|
let lognormalDist: GenericDist_Types.genericDist = Symbolic(#Lognormal({mu: 0.0, sigma: 1.0}))
|
||||||
|
let cauchyDist: GenericDist_Types.genericDist = Symbolic(#Cauchy({local: 1.0, scale: 1.0}))
|
||||||
|
let triangularDist: GenericDist_Types.genericDist = Symbolic(#Triangular({low: 1.0, medium: 2.0, high: 3.0}))
|
||||||
|
let exponentialDist: GenericDist_Types.genericDist = Symbolic(#Exponential({rate: 2.0}))
|
||||||
|
let uniformDist: GenericDist_Types.genericDist = Symbolic(#Uniform({low: 9.0, high: 10.0}))
|
|
@ -134,21 +134,21 @@ describe("Normal distribution with sparklines", () => {
|
||||||
|
|
||||||
let normalDistAtMean5: SymbolicDistTypes.normal = {mean: 5.0, stdev: 2.0}
|
let normalDistAtMean5: SymbolicDistTypes.normal = {mean: 5.0, stdev: 2.0}
|
||||||
let normalDistAtMean10: SymbolicDistTypes.normal = {mean: 10.0, stdev: 2.0}
|
let normalDistAtMean10: SymbolicDistTypes.normal = {mean: 10.0, stdev: 2.0}
|
||||||
let range20Float = E.A.rangeFloat(0, 20) // [0.0,1.0,2.0,3.0,4.0,...19.0,]
|
let range20Float = E.A.Floats.range(0.0, 20.0, 20) // [0.0,1.0,2.0,3.0,4.0,...19.0,]
|
||||||
|
|
||||||
test("mean=5 pdf", () => {
|
test("mean=5 pdf", () => {
|
||||||
let pdfNormalDistAtMean5 = x => SymbolicDist.Normal.pdf(x, normalDistAtMean5)
|
let pdfNormalDistAtMean5 = x => SymbolicDist.Normal.pdf(x, normalDistAtMean5)
|
||||||
let sparklineMean5 = fnImage(pdfNormalDistAtMean5, range20Float)
|
let sparklineMean5 = fnImage(pdfNormalDistAtMean5, range20Float)
|
||||||
Sparklines.create(sparklineMean5, ())
|
Sparklines.create(sparklineMean5, ())
|
||||||
-> expect
|
-> expect
|
||||||
-> toEqual(`▁▂▃▅███▅▃▂▁▁▁▁▁▁▁▁▁▁▁`)
|
-> toEqual(`▁▂▃▆██▇▅▂▁▁▁▁▁▁▁▁▁▁▁`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("parameter-wise addition of two normal distributions", () => {
|
test("parameter-wise addition of two normal distributions", () => {
|
||||||
let sparklineMean15 = normalDistAtMean5 -> parameterWiseAdditionPdf(normalDistAtMean10) -> fnImage(range20Float)
|
let sparklineMean15 = normalDistAtMean5 -> parameterWiseAdditionPdf(normalDistAtMean10) -> fnImage(range20Float)
|
||||||
Sparklines.create(sparklineMean15, ())
|
Sparklines.create(sparklineMean15, ())
|
||||||
-> expect
|
-> expect
|
||||||
-> toEqual(`▁▁▁▁▁▁▁▁▁▁▂▃▅▇███▇▅▃▂`)
|
-> toEqual(`▁▁▁▁▁▁▁▁▁▂▃▄▆███▇▅▄▂`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("mean=10 cdf", () => {
|
test("mean=10 cdf", () => {
|
||||||
|
@ -156,6 +156,6 @@ describe("Normal distribution with sparklines", () => {
|
||||||
let sparklineMean10 = fnImage(cdfNormalDistAtMean10, range20Float)
|
let sparklineMean10 = fnImage(cdfNormalDistAtMean10, range20Float)
|
||||||
Sparklines.create(sparklineMean10, ())
|
Sparklines.create(sparklineMean10, ())
|
||||||
-> expect
|
-> expect
|
||||||
-> toEqual(`▁▁▁▁▁▁▁▁▂▃▅▆▇████████`)
|
-> toEqual(`▁▁▁▁▁▁▁▁▂▄▅▇████████`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,6 +9,3 @@ let expectParseToBe = (expr: string, answer: string) =>
|
||||||
|
|
||||||
let expectEvalToBe = (expr: string, answer: string) =>
|
let expectEvalToBe = (expr: string, answer: string) =>
|
||||||
Reducer.eval(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
Reducer.eval(expr)->ExpressionValue.toStringResult->expect->toBe(answer)
|
||||||
|
|
||||||
// Current configuration does not ignore this file so we have to have a test
|
|
||||||
test("test helpers", () => expect(1)->toBe(1))
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ describe("eval on distribution functions", () => {
|
||||||
testEval("mean(normal(5,2))", "Ok(5)")
|
testEval("mean(normal(5,2))", "Ok(5)")
|
||||||
testEval("mean(lognormal(1,2))", "Ok(20.085536923187668)")
|
testEval("mean(lognormal(1,2))", "Ok(20.085536923187668)")
|
||||||
})
|
})
|
||||||
|
describe("toString", () => {
|
||||||
|
testEval("toString(normal(5,2))", "Ok('Normal(5,2)')")
|
||||||
|
})
|
||||||
describe("normalize", () => {
|
describe("normalize", () => {
|
||||||
testEval("normalize(normal(5,2))", "Ok(Normal(5,2))")
|
testEval("normalize(normal(5,2))", "Ok(Normal(5,2))")
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
preset: 'ts-jest',
|
preset: "ts-jest",
|
||||||
testEnvironment: 'node',
|
testEnvironment: "node",
|
||||||
setupFilesAfterEnv: [
|
setupFilesAfterEnv: [
|
||||||
"<rootdir>/../../node_modules/bisect_ppx/src/runtime/js/jest.bs.js"
|
"<rootdir>/../../node_modules/bisect_ppx/src/runtime/js/jest.bs.js",
|
||||||
],
|
],
|
||||||
testPathIgnorePatterns: [
|
testPathIgnorePatterns: [
|
||||||
"__tests__/TestHelpers.bs.js"
|
".*Fixtures.bs.js",
|
||||||
|
"/node_modules/",
|
||||||
|
".*Helpers.bs.js",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -113,7 +113,11 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
|
||||||
GenericDist.toFloatOperation(dist, ~toPointSetFn, ~distToFloatOperation)
|
GenericDist.toFloatOperation(dist, ~toPointSetFn, ~distToFloatOperation)
|
||||||
->E.R2.fmap(r => Float(r))
|
->E.R2.fmap(r => Float(r))
|
||||||
->OutputLocal.fromResult
|
->OutputLocal.fromResult
|
||||||
| ToString => dist->GenericDist.toString->String
|
| ToString(ToString) => dist->GenericDist.toString->String
|
||||||
|
| ToString(ToSparkline(buckets)) =>
|
||||||
|
GenericDist.toSparkline(dist, ~sampleCount, ~buckets, ())
|
||||||
|
->E.R2.fmap(r => String(r))
|
||||||
|
->OutputLocal.fromResult
|
||||||
| ToDist(Inspect) => {
|
| ToDist(Inspect) => {
|
||||||
Js.log2("Console log requested: ", dist)
|
Js.log2("Console log requested: ", dist)
|
||||||
Dist(dist)
|
Dist(dist)
|
||||||
|
@ -127,7 +131,7 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
|
||||||
dist->GenericDist.sampleN(n)->E.R2.fmap(r => Dist(SampleSet(r)))->OutputLocal.fromResult
|
dist->GenericDist.sampleN(n)->E.R2.fmap(r => Dist(SampleSet(r)))->OutputLocal.fromResult
|
||||||
| ToDist(ToPointSet) =>
|
| ToDist(ToPointSet) =>
|
||||||
dist
|
dist
|
||||||
->GenericDist.toPointSet(~xyPointLength, ~sampleCount)
|
->GenericDist.toPointSet(~xyPointLength, ~sampleCount, ())
|
||||||
->E.R2.fmap(r => Dist(PointSet(r)))
|
->E.R2.fmap(r => Dist(PointSet(r)))
|
||||||
->OutputLocal.fromResult
|
->OutputLocal.fromResult
|
||||||
| ToDistCombination(Algebraic, _, #Float(_)) => GenDistError(NotYetImplemented)
|
| ToDistCombination(Algebraic, _, #Float(_)) => GenDistError(NotYetImplemented)
|
||||||
|
|
|
@ -49,13 +49,19 @@ let toFloatOperation = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Todo: If it's a pointSet, but the xyPointLenght is different from what it has, it should change.
|
//Todo: If it's a pointSet, but the xyPointLength is different from what it has, it should change.
|
||||||
// This is tricky because the case of discrete distributions.
|
// This is tricky because the case of discrete distributions.
|
||||||
// Also, change the outputXYPoints/pointSetDistLength details
|
// Also, change the outputXYPoints/pointSetDistLength details
|
||||||
let toPointSet = (~xyPointLength, ~sampleCount, t): result<PointSetTypes.pointSetDist, error> => {
|
let toPointSet = (
|
||||||
|
t,
|
||||||
|
~xyPointLength,
|
||||||
|
~sampleCount,
|
||||||
|
~xSelection: GenericDist_Types.Operation.pointsetXSelection=#ByWeight,
|
||||||
|
unit,
|
||||||
|
): result<PointSetTypes.pointSetDist, error> => {
|
||||||
switch (t: t) {
|
switch (t: t) {
|
||||||
| PointSet(pointSet) => Ok(pointSet)
|
| PointSet(pointSet) => Ok(pointSet)
|
||||||
| Symbolic(r) => Ok(SymbolicDist.T.toPointSetDist(xyPointLength, r))
|
| Symbolic(r) => Ok(SymbolicDist.T.toPointSetDist(~xSelection, xyPointLength, r))
|
||||||
| SampleSet(r) => {
|
| SampleSet(r) => {
|
||||||
let response = SampleSet.toPointSetDist(
|
let response = SampleSet.toPointSetDist(
|
||||||
~samples=r,
|
~samples=r,
|
||||||
|
@ -75,6 +81,11 @@ let toPointSet = (~xyPointLength, ~sampleCount, t): result<PointSetTypes.pointSe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let toSparkline = (t: t, ~sampleCount: int, ~buckets: int=20, unit): result<string, error> =>
|
||||||
|
t
|
||||||
|
->toPointSet(~xSelection=#Linear, ~xyPointLength=buckets, ~sampleCount, ())
|
||||||
|
->E.R.bind(r => r->PointSetDist.toSparkline->E.R2.errMap(r => Error(GenericDist_Types.Other(r))))
|
||||||
|
|
||||||
module Truncate = {
|
module Truncate = {
|
||||||
let trySymbolicSimplification = (leftCutoff, rightCutoff, t: t): option<t> =>
|
let trySymbolicSimplification = (leftCutoff, rightCutoff, t: t): option<t> =>
|
||||||
switch (leftCutoff, rightCutoff, t) {
|
switch (leftCutoff, rightCutoff, t) {
|
||||||
|
|
|
@ -20,17 +20,20 @@ let toFloatOperation: (
|
||||||
) => result<float, error>
|
) => result<float, error>
|
||||||
|
|
||||||
let toPointSet: (
|
let toPointSet: (
|
||||||
|
t,
|
||||||
~xyPointLength: int,
|
~xyPointLength: int,
|
||||||
~sampleCount: int,
|
~sampleCount: int,
|
||||||
t,
|
~xSelection: GenericDist_Types.Operation.pointsetXSelection=?,
|
||||||
|
unit,
|
||||||
) => result<PointSetTypes.pointSetDist, error>
|
) => result<PointSetTypes.pointSetDist, error>
|
||||||
|
let toSparkline: (t, ~sampleCount: int, ~buckets: int=?, unit) => result<string, error>
|
||||||
|
|
||||||
let truncate: (
|
let truncate: (
|
||||||
t,
|
t,
|
||||||
~toPointSetFn: toPointSetFn,
|
~toPointSetFn: toPointSetFn,
|
||||||
~leftCutoff: option<float>=?,
|
~leftCutoff: option<float>=?,
|
||||||
~rightCutoff: option<float>=?,
|
~rightCutoff: option<float>=?,
|
||||||
unit
|
unit,
|
||||||
) => result<t, error>
|
) => result<t, error>
|
||||||
|
|
||||||
let algebraicCombination: (
|
let algebraicCombination: (
|
||||||
|
|
|
@ -41,6 +41,8 @@ module Operation = {
|
||||||
| #Sample
|
| #Sample
|
||||||
]
|
]
|
||||||
|
|
||||||
|
type pointsetXSelection = [#Linear | #ByWeight]
|
||||||
|
|
||||||
type toDist =
|
type toDist =
|
||||||
| Normalize
|
| Normalize
|
||||||
| ToPointSet
|
| ToPointSet
|
||||||
|
@ -50,11 +52,15 @@ module Operation = {
|
||||||
|
|
||||||
type toFloatArray = Sample(int)
|
type toFloatArray = Sample(int)
|
||||||
|
|
||||||
|
type toString =
|
||||||
|
| ToString
|
||||||
|
| ToSparkline(int)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
type singleParamaterFunction =
|
type singleParamaterFunction =
|
||||||
| FromDist(fromDist)
|
| FromDist(fromDist)
|
||||||
|
@ -77,7 +83,8 @@ module Operation = {
|
||||||
| ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})`
|
| ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})`
|
||||||
| ToDist(Truncate(_, _)) => `truncate`
|
| ToDist(Truncate(_, _)) => `truncate`
|
||||||
| ToDist(Inspect) => `inspect`
|
| ToDist(Inspect) => `inspect`
|
||||||
| ToString => `toString`
|
| ToString(ToString) => `toString`
|
||||||
|
| ToString(ToSparkline(n)) => `toSparkline(${E.I.toString(n)})`
|
||||||
| ToDistCombination(Algebraic, _, _) => `algebraic`
|
| ToDistCombination(Algebraic, _, _) => `algebraic`
|
||||||
| ToDistCombination(Pointwise, _, _) => `pointwise`
|
| ToDistCombination(Pointwise, _, _) => `pointwise`
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,6 @@ let isFloat = (t: t) =>
|
||||||
let sampleNRendered = (n, dist) => {
|
let sampleNRendered = (n, dist) => {
|
||||||
let integralCache = T.Integral.get(dist)
|
let integralCache = T.Integral.get(dist)
|
||||||
let distWithUpdatedIntegralCache = T.updateIntegralCache(Some(integralCache), dist)
|
let distWithUpdatedIntegralCache = T.updateIntegralCache(Some(integralCache), dist)
|
||||||
|
|
||||||
doN(n, () => sample(distWithUpdatedIntegralCache))
|
doN(n, () => sample(distWithUpdatedIntegralCache))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,3 +202,8 @@ let operate = (distToFloatOp: Operation.distToFloatOperation, s): float =>
|
||||||
| #Sample => sample(s)
|
| #Sample => sample(s)
|
||||||
| #Mean => T.mean(s)
|
| #Mean => T.mean(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let toSparkline = (t: t) =>
|
||||||
|
T.toContinuous(t)
|
||||||
|
->E.O2.toResult("toContinous Error: Could not convert into continuous distribution")
|
||||||
|
->E.R2.fmap(r => Continuous.getShape(r).ys->Sparklines.create())
|
|
@ -346,11 +346,11 @@ module T = {
|
||||||
| _ => #NoSolution
|
| _ => #NoSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
let toPointSetDist = (sampleCount, d: symbolicDist): PointSetTypes.pointSetDist =>
|
let toPointSetDist = (~xSelection=#ByWeight, sampleCount, d: symbolicDist): PointSetTypes.pointSetDist =>
|
||||||
switch d {
|
switch d {
|
||||||
| #Float(v) => Discrete(Discrete.make(~integralSumCache=Some(1.0), {xs: [v], ys: [1.0]}))
|
| #Float(v) => Discrete(Discrete.make(~integralSumCache=Some(1.0), {xs: [v], ys: [1.0]}))
|
||||||
| _ =>
|
| _ =>
|
||||||
let xs = interpolateXs(~xSelection=#ByWeight, d, sampleCount)
|
let xs = interpolateXs(~xSelection, d, sampleCount)
|
||||||
let ys = xs |> E.A.fmap(x => pdf(x, d))
|
let ys = xs |> E.A.fmap(x => pdf(x, d))
|
||||||
Continuous(Continuous.make(~integralSumCache=Some(1.0), {xs: xs, ys: ys}))
|
Continuous(Continuous.make(~integralSumCache=Some(1.0), {xs: xs, ys: ys}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,13 @@ module Helpers = {
|
||||||
FromDist(GenericDist_Types.Operation.ToFloat(fnCall), dist)->runGenericOperation->Some
|
FromDist(GenericDist_Types.Operation.ToFloat(fnCall), dist)->runGenericOperation->Some
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let toStringFn = (
|
||||||
|
fnCall: GenericDist_Types.Operation.toString,
|
||||||
|
dist: GenericDist_Types.genericDist,
|
||||||
|
) => {
|
||||||
|
FromDist(GenericDist_Types.Operation.ToString(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
|
||||||
}
|
}
|
||||||
|
@ -119,6 +126,9 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
|
||||||
->SymbolicConstructors.symbolicResultToOutput
|
->SymbolicConstructors.symbolicResultToOutput
|
||||||
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist)
|
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist)
|
||||||
| ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist)
|
| ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist)
|
||||||
|
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist)
|
||||||
|
| ("toSparkline", [EvDistribution(dist)]) => Helpers.toStringFn(ToSparkline(20), dist)
|
||||||
|
| ("toSparkline", [EvDistribution(dist), EvNumber(n)]) => Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist)
|
||||||
| ("exp", [EvDistribution(a)]) =>
|
| ("exp", [EvDistribution(a)]) =>
|
||||||
// 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
|
||||||
|
|
|
@ -101,6 +101,7 @@ module O2 = {
|
||||||
let default = (a, b) => O.default(b, a)
|
let default = (a, b) => O.default(b, a)
|
||||||
let toExn = (a, b) => O.toExn(b, a)
|
let toExn = (a, b) => O.toExn(b, a)
|
||||||
let fmap = (a, b) => O.fmap(b, a)
|
let fmap = (a, b) => O.fmap(b, a)
|
||||||
|
let toResult = (a, b) => O.toResult(b, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
|
@ -178,6 +179,13 @@ module R = {
|
||||||
|
|
||||||
module R2 = {
|
module R2 = {
|
||||||
let fmap = (a,b) => R.fmap(b,a)
|
let fmap = (a,b) => R.fmap(b,a)
|
||||||
|
let bind = (a, b) => R.bind(b, a)
|
||||||
|
|
||||||
|
//Converts result type to change error type only
|
||||||
|
let errMap = (a, map) => switch(a){
|
||||||
|
| Ok(r) => Ok(r)
|
||||||
|
| Error(e) => map(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let safe_fn_of_string = (fn, s: string): option<'a> =>
|
let safe_fn_of_string = (fn, s: string): option<'a> =>
|
||||||
|
@ -289,8 +297,7 @@ module A = {
|
||||||
))
|
))
|
||||||
|> Rationale.Result.return
|
|> Rationale.Result.return
|
||||||
}
|
}
|
||||||
let rangeFloat = (~step=1, start, stop) =>
|
|
||||||
Belt.Array.rangeBy(start, stop, ~step) |> fmap(Belt.Int.toFloat)
|
|
||||||
|
|
||||||
// This zips while taking the longest elements of each array.
|
// This zips while taking the longest elements of each array.
|
||||||
let zipMaxLength = (array1, array2) => {
|
let zipMaxLength = (array1, array2) => {
|
||||||
|
@ -442,6 +449,12 @@ module A = {
|
||||||
let mean = a => sum(a) /. (Array.length(a) |> float_of_int)
|
let mean = a => sum(a) /. (Array.length(a) |> float_of_int)
|
||||||
let random = Js.Math.random_int
|
let random = Js.Math.random_int
|
||||||
|
|
||||||
|
// Gives an array with all the differences between values
|
||||||
|
// diff([1,5,3,7]) = [4,-2,4]
|
||||||
|
let diff = (arr: array<float>): array<float> =>
|
||||||
|
Belt.Array.zipBy(arr, Belt.Array.sliceToEnd(arr, 1), (left, right) => right -. left)
|
||||||
|
|
||||||
|
|
||||||
exception RangeError(string)
|
exception RangeError(string)
|
||||||
let range = (min: float, max: float, n: int): array<float> =>
|
let range = (min: float, max: float, n: int): array<float> =>
|
||||||
switch n {
|
switch n {
|
||||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -8434,13 +8434,6 @@ extglob@^2.0.4:
|
||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
fast-check@^2.17.0:
|
|
||||||
version "2.24.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.24.0.tgz#39f85586862108a4de6394c5196ebcf8b76b6c8b"
|
|
||||||
integrity sha512-iNXbN90lbabaCUfnW5jyXYPwMJLFYl09eJDkXA9ZoidFlBK63gNRvcKxv+8D1OJ1kIYjwBef4bO/K3qesUeWLQ==
|
|
||||||
dependencies:
|
|
||||||
pure-rand "^5.0.1"
|
|
||||||
|
|
||||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3, fast-deep-equal@~3.1.3:
|
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3, fast-deep-equal@~3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
||||||
|
@ -13573,11 +13566,6 @@ pure-color@^1.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e"
|
||||||
integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=
|
integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=
|
||||||
|
|
||||||
pure-rand@^5.0.1:
|
|
||||||
version "5.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-5.0.1.tgz#97a287b4b4960b2a3448c0932bf28f2405cac51d"
|
|
||||||
integrity sha512-ksWccjmXOHU2gJBnH0cK1lSYdvSZ0zLoCMSz/nTGh6hDvCSgcRxDyIcOBD6KNxFz3xhMPm/T267Tbe2JRymKEQ==
|
|
||||||
|
|
||||||
q@^1.1.2:
|
q@^1.1.2:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||||
|
@ -14766,13 +14754,6 @@ requires-port@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
rescript-fast-check@^1.1.1:
|
|
||||||
version "1.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/rescript-fast-check/-/rescript-fast-check-1.1.1.tgz#ef153cb01254b2f01a738faf85b73327d423d5e1"
|
|
||||||
integrity sha512-wxeW0TsL/prkRvEYGbhEiLaLKmYJaECyDcKEWh65hDqP2i76lARzVW3QmYujSYK4OnjAC70dln3X6UC/2m2Huw==
|
|
||||||
dependencies:
|
|
||||||
fast-check "^2.17.0"
|
|
||||||
|
|
||||||
rescript@^9.1.4:
|
rescript@^9.1.4:
|
||||||
version "9.1.4"
|
version "9.1.4"
|
||||||
resolved "https://registry.npmjs.org/rescript/-/rescript-9.1.4.tgz"
|
resolved "https://registry.npmjs.org/rescript/-/rescript-9.1.4.tgz"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user