Merge pull request #529 from quantified-uncertainty/samplesMap
SamplesMap() and toInternalSampleArray() functions
This commit is contained in:
		
						commit
						2b48e2bb53
					
				|  | @ -17,6 +17,10 @@ describe("builtin", () => { | |||
|   testEval("1-1", "Ok(0)") | ||||
|   testEval("2>1", "Ok(true)") | ||||
|   testEval("concat('a','b')", "Ok('ab')") | ||||
|   testEval( | ||||
|     "addOne(t)=t+1; toInternalSampleArray(mapSamples(fromSamples([1,2,3,4,5,6]), addOne))", | ||||
|     "Ok([2,3,4,5,6,7])", | ||||
|   ) | ||||
| }) | ||||
| 
 | ||||
| describe("builtin exception", () => { | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ module Error = { | |||
|     | LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}` | ||||
|     | SampleSetError(TooFewSamples) => "Too Few Samples" | ||||
|     | SampleSetError(NonNumericInput(err)) => `Found a non-number in input: ${err}` | ||||
|     | SampleSetError(OperationError(err)) => Operation.Error.toString(err) | ||||
|     | OperationError(err) => Operation.Error.toString(err) | ||||
|     | PointSetConversionError(err) => SampleSetDist.pointsetConversionErrorToString(err) | ||||
|     | SparklineError(err) => PointSetTypes.sparklineErrorToString(err) | ||||
|  |  | |||
|  | @ -1,12 +1,14 @@ | |||
| @genType | ||||
| module Error = { | ||||
|   @genType | ||||
|   type sampleSetError = TooFewSamples | NonNumericInput(string) | ||||
|   type sampleSetError = | ||||
|     TooFewSamples | NonNumericInput(string) | OperationError(Operation.operationError) | ||||
| 
 | ||||
|   let sampleSetErrorToString = (err: sampleSetError): string => | ||||
|     switch err { | ||||
|     | TooFewSamples => "Too few samples when constructing sample set" | ||||
|     | NonNumericInput(err) => `Found a non-number in input: ${err}` | ||||
|     | OperationError(err) => Operation.Error.toString(err) | ||||
|     } | ||||
| 
 | ||||
|   @genType | ||||
|  | @ -16,6 +18,8 @@ module Error = { | |||
|     switch err { | ||||
|     | TooFewSamplesForConversionToPointSet => "Too Few Samples to convert to point set" | ||||
|     } | ||||
| 
 | ||||
|   let fromOperationError = e => OperationError(e) | ||||
| } | ||||
| 
 | ||||
| include Error | ||||
|  | @ -83,6 +87,14 @@ let sampleN = (t: t, n) => { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| let samplesMap = (~fn: float => result<float, Operation.Error.t>, t: t): result< | ||||
|   t, | ||||
|   sampleSetError, | ||||
| > => { | ||||
|   let samples = T.get(t)->E.A2.fmap(fn) | ||||
|   E.A.R.firstErrorOrOpen(samples)->E.R2.errMap(Error.fromOperationError) |> E.R2.bind(make) | ||||
| } | ||||
| 
 | ||||
| //TODO: Figure out what to do if distributions are different lengths. ``zip`` is kind of inelegant for this. | ||||
| let map2 = (~fn: (float, float) => result<float, Operation.Error.t>, ~t1: t, ~t2: t): result< | ||||
|   t, | ||||
|  | @ -96,7 +108,7 @@ let map2 = (~fn: (float, float) => result<float, Operation.Error.t>, ~t1: t, ~t2 | |||
|   // I could prove this to the type system (say, creating a {first: float, second: float, ..., fifth: float, rest: array<float>} | ||||
|   // But doing so would take too much time, so I'll leave it as an assertion | ||||
|   E.A.R.firstErrorOrOpen(samples)->E.R2.fmap(x => | ||||
|     E.R.toExn("Input of samples should be larger than 5", make(x)) | ||||
|     E.R.toExnFnString(Error.sampleSetErrorToString, make(x)) | ||||
|   ) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -99,6 +99,18 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce | |||
|     rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->EvArray) | ||||
|   } | ||||
| 
 | ||||
|   let doMapSampleSetDist = (sampleSetDist: SampleSetDist.t, aLambdaValue) => { | ||||
|     let fn = r => | ||||
|       switch Lambda.doLambdaCall(aLambdaValue, list{EvNumber(r)}, environment, reducer) { | ||||
|       | Ok(EvNumber(f)) => Ok(f) | ||||
|       | _ => Error(Operation.SampleMapNeedsNtoNFunction) | ||||
|       } | ||||
|     switch SampleSetDist.samplesMap(~fn, sampleSetDist) { | ||||
|     | Ok(r) => Ok(EvDistribution(SampleSet(r))) | ||||
|     | Error(r) => Error(REDistributionError(SampleSetError(r))) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   let doReduceArray = (aValueArray, initialValue, aLambdaValue) => { | ||||
|     aValueArray->Belt.Array.reduce(Ok(initialValue), (rAcc, elem) => | ||||
|       rAcc->Result.flatMap(acc => | ||||
|  | @ -128,6 +140,8 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce | |||
|   | ("keep", [EvArray(aValueArray), EvLambda(aLambdaValue)]) => | ||||
|     doKeepArray(aValueArray, aLambdaValue) | ||||
|   | ("map", [EvArray(aValueArray), EvLambda(aLambdaValue)]) => doMapArray(aValueArray, aLambdaValue) | ||||
|   | ("mapSamples", [EvDistribution(SampleSet(dist)), EvLambda(aLambdaValue)]) => | ||||
|     doMapSampleSetDist(dist, aLambdaValue) | ||||
|   | ("reduce", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) => | ||||
|     doReduceArray(aValueArray, initialValue, aLambdaValue) | ||||
|   | ("reduceReverse", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) => | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ type errorValue = | |||
|   | REArrayIndexNotFound(string, int) | ||||
|   | REAssignmentExpected | ||||
|   | REDistributionError(DistributionTypes.error) | ||||
|   | REOperationError(Operation.operationError) | ||||
|   | REExpressionExpected | ||||
|   | REFunctionExpected(string) | ||||
|   | REJavaScriptExn(option<string>, option<string>) // Javascript Exception | ||||
|  | @ -29,6 +30,7 @@ let errorToString = err => | |||
|   | REExpressionExpected => "Expression expected" | ||||
|   | REFunctionExpected(msg) => `Function expected: ${msg}` | ||||
|   | REDistributionError(err) => `Distribution Math Error: ${DistributionTypes.Error.toString(err)}` | ||||
|   | REOperationError(err) => `Math Error: ${Operation.Error.toString(err)}` | ||||
|   | REJavaScriptExn(omsg, oname) => { | ||||
|       let answer = "JS Exception:" | ||||
|       let answer = switch oname { | ||||
|  |  | |||
|  | @ -306,6 +306,8 @@ let dispatchToGenericOutput = ( | |||
|     Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env) | ||||
|   | ("toSampleSet", [EvDistribution(dist)]) => | ||||
|     Helpers.toDistFn(ToSampleSet(env.sampleCount), dist, ~env) | ||||
|   | ("toInternalSampleArray", [EvDistribution(SampleSet(dist))]) => | ||||
|     Some(FloatArray(SampleSetDist.T.get(dist))) | ||||
|   | ("fromSamples", [EvArray(inputArray)]) => { | ||||
|       let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x) | ||||
|       let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors) | ||||
|  |  | |||
|  | @ -235,13 +235,16 @@ module R = { | |||
|     | Ok(a) => f(a) | ||||
|     | Error(err) => Error(err) | ||||
|     } | ||||
| 
 | ||||
|   let toExn = (msg: string, x: result<'a, 'b>): 'a => | ||||
|     switch x { | ||||
|     | Ok(r) => r | ||||
|     | Error(_) => raise(Assertion(msg)) | ||||
|     } | ||||
| 
 | ||||
|   let toExnFnString = (errorToStringFn, o) => | ||||
|     switch o { | ||||
|     | Ok(r) => r | ||||
|     | Error(r) => raise(Assertion(errorToStringFn(r))) | ||||
|     } | ||||
|   let default = (default, res: Belt.Result.t<'a, 'b>) => | ||||
|     switch res { | ||||
|     | Ok(r) => r | ||||
|  |  | |||
|  | @ -55,6 +55,7 @@ type operationError = | |||
|   | ComplexNumberError | ||||
|   | InfinityError | ||||
|   | NegativeInfinityError | ||||
|   | SampleMapNeedsNtoNFunction | ||||
|   | PdfInvalidError | ||||
|   | NotYetImplemented // should be removed when `klDivergence` for mixed and discrete is implemented. | ||||
| 
 | ||||
|  | @ -69,6 +70,7 @@ module Error = { | |||
|     | ComplexNumberError => "Operation returned complex result" | ||||
|     | InfinityError => "Operation returned positive infinity" | ||||
|     | NegativeInfinityError => "Operation returned negative infinity" | ||||
|     | SampleMapNeedsNtoNFunction => "SampleMap needs a function that converts a number to a number" | ||||
|     | PdfInvalidError => "This Pdf is invalid" | ||||
|     | NotYetImplemented => "This pathway is not yet implemented" | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user