tweak: Add error checking to dmr calculation

This commit is contained in:
NunoSempere 2022-09-06 14:49:14 +02:00
parent 60e42cf1e8
commit fc2d647b62

View File

@ -272,92 +272,114 @@ module DiminishingReturns = {
1. O(n): Iterate through value on next n dollars. At each step, only compute the new marginal return of the function which is spent 1. O(n): Iterate through value on next n dollars. At each step, only compute the new marginal return of the function which is spent
2. O(n*m): Iterate through all possible spending combinations. The advantage of this option is that it wouldn't assume that the returns of marginal spending are diminishing. 2. O(n*m): Iterate through all possible spending combinations. The advantage of this option is that it wouldn't assume that the returns of marginal spending are diminishing.
*/ */
let applyFunctionAtPoint = (lambda, point: float) => { switch (
// Defined here so that it has access to environment, reducer E.A.length(lambdas) > 1,
let pointAsInternalExpression = FunctionRegistry_Helpers.Wrappers.evNumber(point) funds > 0.0,
let resultAsInternalExpression = Reducer_Expression_Lambda.doLambdaCall( approximateIncrement > 0.0,
lambda, funds > approximateIncrement,
list{pointAsInternalExpression}, ) {
environment, | (false, _, _, _) =>
reducer, Error(
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, number of functions should be greater than 1.",
) )
switch resultAsInternalExpression { | (_, false, _, _) =>
| Ok(IEvNumber(x)) => Ok(x) Error(
| Error(_) => "Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, funds should be greater than 0.",
Error( )
"Error 1 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead", | (_, _, false, _) =>
) Error(
| _ => "Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be greater than 0.",
Error( )
"Error 2 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions", | (_, _, _, false) =>
) Error(
} "Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be smaller than funds amount.",
} )
| (true, true, true, true) => {
let applyFunctionAtPoint = (lambda, point: float) => {
// Defined here so that it has access to environment, reducer
let pointAsInternalExpression = FunctionRegistry_Helpers.Wrappers.evNumber(point)
let resultAsInternalExpression = Reducer_Expression_Lambda.doLambdaCall(
lambda,
list{pointAsInternalExpression},
environment,
reducer,
)
switch resultAsInternalExpression {
| Ok(IEvNumber(x)) => Ok(x)
| Error(_) =>
Error(
"Error 1 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead",
)
| _ =>
Error(
"Error 2 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions",
)
}
}
let numDivisions = Js.Math.round(funds /. approximateIncrement) let numDivisions = Js.Math.round(funds /. approximateIncrement)
let increment = funds /. numDivisions let increment = funds /. numDivisions
let arrayOfIncrements = Belt.Array.make(Belt.Float.toInt(numDivisions), increment) let arrayOfIncrements = Belt.Array.make(Belt.Float.toInt(numDivisions), increment)
let initAccumulator: diminishingReturnsAccumulator = Ok({ let initAccumulator: diminishingReturnsAccumulator = Ok({
optimalAllocations: Belt.Array.make(E.A.length(lambdas), 0.0), optimalAllocations: Belt.Array.make(E.A.length(lambdas), 0.0),
currentMarginalReturns: E.A.fmap( currentMarginalReturns: E.A.fmap(
lambda => applyFunctionAtPoint(lambda, 0.0), lambda => applyFunctionAtPoint(lambda, 0.0),
lambdas, lambdas,
)->E.A.R.firstErrorOrOpen, )->E.A.R.firstErrorOrOpen,
}) })
let optimalAllocationEndAccumulator = E.A.reduce(arrayOfIncrements, initAccumulator, ( let optimalAllocationEndAccumulator = E.A.reduce(arrayOfIncrements, initAccumulator, (
acc, acc,
newIncrement, newIncrement,
) => { ) => {
switch acc { switch acc {
| Ok(accInner) => { | Ok(accInner) => {
let oldMarginalReturnsWrapped = accInner.currentMarginalReturns let oldMarginalReturnsWrapped = accInner.currentMarginalReturns
let newAccWrapped = switch oldMarginalReturnsWrapped { let newAccWrapped = switch oldMarginalReturnsWrapped {
| Ok(oldMarginalReturns) => { | Ok(oldMarginalReturns) => {
let indexOfBiggestDMR = findBiggestElementIndex(oldMarginalReturns) let indexOfBiggestDMR = findBiggestElementIndex(oldMarginalReturns)
let newOptimalAllocations = Belt.Array.copy(accInner.optimalAllocations) let newOptimalAllocations = Belt.Array.copy(accInner.optimalAllocations)
let newOptimalAllocationsi = let newOptimalAllocationsi =
newOptimalAllocations[indexOfBiggestDMR] +. newIncrement newOptimalAllocations[indexOfBiggestDMR] +. newIncrement
newOptimalAllocations[indexOfBiggestDMR] = newOptimalAllocationsi newOptimalAllocations[indexOfBiggestDMR] = newOptimalAllocationsi
let lambdai = lambdas[indexOfBiggestDMR] let lambdai = lambdas[indexOfBiggestDMR]
let newMarginalResultsLambdai = applyFunctionAtPoint( let newMarginalResultsLambdai = applyFunctionAtPoint(
lambdai, lambdai,
newOptimalAllocationsi, newOptimalAllocationsi,
) )
let newCurrentMarginalReturns = switch newMarginalResultsLambdai { let newCurrentMarginalReturns = switch newMarginalResultsLambdai {
| Ok(value) => { | Ok(value) => {
let result = Belt.Array.copy(oldMarginalReturns) let result = Belt.Array.copy(oldMarginalReturns)
result[indexOfBiggestDMR] = value result[indexOfBiggestDMR] = value
Ok(result) Ok(result)
}
| Error(b) => Error(b)
}
let newAcc: diminishingReturnsAccumulatorInner = {
optimalAllocations: newOptimalAllocations,
currentMarginalReturns: newCurrentMarginalReturns,
}
Ok(newAcc)
} }
| Error(b) => Error(b) | Error(b) => Error(b)
} }
newAccWrapped
let newAcc: diminishingReturnsAccumulatorInner = {
optimalAllocations: newOptimalAllocations,
currentMarginalReturns: newCurrentMarginalReturns,
}
Ok(newAcc)
} }
| Error(b) => Error(b) | Error(b) => Error(b)
} }
newAccWrapped })
let optimalAllocationResult = switch optimalAllocationEndAccumulator {
| Ok(inner) =>
Ok(FunctionRegistry_Helpers.Wrappers.evArrayOfEvNumber(inner.optimalAllocations))
| Error(b) => Error(b)
} }
| Error(b) => Error(b)
optimalAllocationResult
} }
})
let optimalAllocationResult = switch optimalAllocationEndAccumulator {
| Ok(inner) =>
Ok(FunctionRegistry_Helpers.Wrappers.evArrayOfEvNumber(inner.optimalAllocations))
| Error(b) => Error(b)
} }
optimalAllocationResult
// let result = [0.0, 0.0]->FunctionRegistry_Helpers.Wrappers.evArrayOfEvNumber->Ok
// result
// ^ helper with the same type as what the result should be. Useful for debugging.
} }
} }
module Lib = { module Lib = {