cleanup: More Dangers cleanup

and formatting
This commit is contained in:
NunoSempere 2022-09-06 14:24:44 +02:00
parent ae71bb8ec5
commit 60e42cf1e8
2 changed files with 442 additions and 408 deletions

View File

@ -12,7 +12,7 @@ module Wrappers = {
let evRecord = r => ReducerInterface_InternalExpressionValue.IEvRecord(r)
let evString = r => ReducerInterface_InternalExpressionValue.IEvString(r)
let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution
let evArrayOfEvNumber = xs => xs ->Belt.Array.map(evNumber) -> evArray
let evArrayOfEvNumber = xs => xs->Belt.Array.map(evNumber)->evArray
}
let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleError)

View File

@ -233,17 +233,12 @@ module Integration = {
}
}
module Internals = {
// Diminishing returns
// Helpers
module DiminishingReturns = {
module Helpers = {
type diminishingReturnsAccumulatorInner = {
optimalAllocations: array<float>,
currentMarginalReturns: result<array<float>, string>,
}
// Cannot be be done by Js.Math.max_int or maxMany_int
// because that function returns the value of the element
// not of the index.
let findBiggestElementIndex = xs =>
E.A.reducei(xs, 0, (acc, newElement, index) => {
switch newElement > xs[acc] {
@ -253,7 +248,19 @@ module Internals = {
})
type diminishingReturnsAccumulator = result<diminishingReturnsAccumulatorInner, string>
//TODO: This is so complicated, it probably should be its own file. It might also make sense to have it work in Rescript directly, taking in a function rather than a reducer; then something else can wrap that function in the reducer/lambdas/environment.
let diminishingMarginalReturnsForManyFunctions = (
/*
The key idea for this function is that
1. we keep track of past spending and current marginal returns for each function
2. we look an additional increment in funds
3. we assign it to the function with the best marginal returns
4. we update the spending, and we compute the new returns for that function, with more spending
- But we only compute the new marginal returns for the function we end up assigning the spending to.
5. We continue doing this until all the funding is exhausted
This is currently being done with a reducer, that keeps track of:
- Value of marginal spending for each function
- How much has been assigned to each function.
*/
let optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions = (
lambdas,
funds,
approximateIncrement,
@ -263,7 +270,7 @@ module Internals = {
/*
Two possible algorithms (n=funds/increment, m=num lambdas)
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. Fun is, it doesn'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) => {
// Defined here so that it has access to environment, reducer
@ -278,9 +285,12 @@ module Internals = {
| Ok(IEvNumber(x)) => Ok(x)
| Error(_) =>
Error(
"Error 1 in Danger.diminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead",
"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",
)
| _ => Error("Error 2 in Danger.diminishingMarginalReturnsForManyFunctions")
}
}
@ -307,10 +317,14 @@ module Internals = {
| Ok(oldMarginalReturns) => {
let indexOfBiggestDMR = findBiggestElementIndex(oldMarginalReturns)
let newOptimalAllocations = Belt.Array.copy(accInner.optimalAllocations)
let newOptimalAllocationsi = newOptimalAllocations[indexOfBiggestDMR] +. newIncrement
let newOptimalAllocationsi =
newOptimalAllocations[indexOfBiggestDMR] +. newIncrement
newOptimalAllocations[indexOfBiggestDMR] = newOptimalAllocationsi
let lambdai = lambdas[indexOfBiggestDMR]
let newMarginalResultsLambdai = applyFunctionAtPoint(lambdai, newOptimalAllocationsi)
let newMarginalResultsLambdai = applyFunctionAtPoint(
lambdai,
newOptimalAllocationsi,
)
let newCurrentMarginalReturns = switch newMarginalResultsLambdai {
| Ok(value) => {
let result = Belt.Array.copy(oldMarginalReturns)
@ -335,7 +349,8 @@ module Internals = {
})
let optimalAllocationResult = switch optimalAllocationEndAccumulator {
| Ok(inner) => Ok(FunctionRegistry_Helpers.Wrappers.evArrayOfEvNumber(inner.optimalAllocations))
| Ok(inner) =>
Ok(FunctionRegistry_Helpers.Wrappers.evArrayOfEvNumber(inner.optimalAllocations))
| Error(b) => Error(b)
}
@ -344,38 +359,19 @@ module Internals = {
// result
// ^ helper with the same type as what the result should be. Useful for debugging.
}
}
let library = [
// Combinatorics
Combinatorics.Lib.laplace,
Combinatorics.Lib.factorial,
Combinatorics.Lib.choose,
Combinatorics.Lib.binomial,
// Integration
Integration.Lib.integrateFunctionBetweenWithNumIntegrationPoints,
// ^ Integral in terms of function, min, max, epsilon (distance between points)
// Execution time will be less predictable, because it
// will depend on min, max and epsilon together,
// as well and the complexity of the function
Integration.Lib.integrateFunctionBetweenWithEpsilon,
// ^ Integral in terms of function, min, max, num points
// Note that execution time will be more predictable, because it
// will only depend on num points and the complexity of the function
// Diminishing marginal return functions
// There are functions diminishingMarginalReturnsForFunctions2 through diminishingMarginalReturnsForFunctions7
// Because of this bug: <https://github.com/quantified-uncertainty/squiggle/issues/1090>
// As soon as that is fixed, I will simplify this monstrosity.
Function.make(
~name="diminishingMarginalReturnsForFunctions2",
}
module Lib = {
let optimalAllocationGivenDiminishingMarginalReturnsFunctions2 = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions2",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[`Danger.diminishingMarginalReturnsForFunctions2({|x| 20-x}, {|y| 10}, 100, 0.01)`],
~examples=[
`Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions2({|x| 20-x}, {|y| 10}, 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForFunctions2",
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions2",
~inputs=[FRTypeLambda, FRTypeLambda, FRTypeNumber, FRTypeNumber],
~run=(inputs, _, env, reducer) =>
switch inputs {
@ -385,31 +381,32 @@ let library = [
IEvNumber(funds),
IEvNumber(approximateIncrement),
] =>
Internals.diminishingMarginalReturnsForManyFunctions(
Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
[lambda1, lambda2],
funds,
approximateIncrement,
env,
reducer,
)
| _ => Error("Error in Danger.diminishingMarginalReturnsForFunctions2")
| _ =>
Error("Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions2")
},
(),
),
],
(),
),
Function.make(
~name="diminishingMarginalReturnsForFunctions3",
)
let optimalAllocationGivenDiminishingMarginalReturnsFunctions3 = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions3",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[
`Danger.diminishingMarginalReturnsForFunctions3({|x| x+1}, {|y| 10}, {|z| 20-2*z}, 100, 0.01)`,
`Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions3({|x| x+1}, {|y| 10}, {|z| 20-2*z}, 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForFunctions3",
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions3",
~inputs=[FRTypeLambda, FRTypeLambda, FRTypeLambda, FRTypeNumber, FRTypeNumber],
~run=(inputs, _, env, reducer) =>
switch inputs {
@ -420,31 +417,32 @@ let library = [
IEvNumber(funds),
IEvNumber(approximateIncrement),
] =>
Internals.diminishingMarginalReturnsForManyFunctions(
Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
[lambda1, lambda2, lambda3],
funds,
approximateIncrement,
env,
reducer,
)
| _ => Error("Error in Danger.diminishingMarginalReturnsForFunctions3")
| _ =>
Error("Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions3")
},
(),
),
],
(),
),
Function.make(
~name="diminishingMarginalReturnsForFunctions4",
)
let optimalAllocationGivenDiminishingMarginalReturnsFunctions4 = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions4",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[
`Danger.diminishingMarginalReturnsForFunctions4({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, 100, 0.01)`,
`Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions4({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForFunctions4",
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions4",
~inputs=[
FRTypeLambda,
FRTypeLambda,
@ -463,31 +461,32 @@ let library = [
IEvNumber(funds),
IEvNumber(approximateIncrement),
] =>
Internals.diminishingMarginalReturnsForManyFunctions(
Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
[lambda1, lambda2, lambda3, lambda4],
funds,
approximateIncrement,
env,
reducer,
)
| _ => Error("Error in Danger.diminishingMarginalReturnsForFunctions4")
| _ =>
Error("Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions4")
},
(),
),
],
(),
),
Function.make(
~name="diminishingMarginalReturnsForFunctions5",
)
let optimalAllocationGivenDiminishingMarginalReturnsFunctions5 = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions5",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[
`Danger.diminishingMarginalReturnsForFunctions5({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, {|b| 17-b}, 100, 0.01)`,
`Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions5({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, {|b| 17-b}, 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForFunctions5",
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions5",
~inputs=[
FRTypeLambda,
FRTypeLambda,
@ -508,31 +507,32 @@ let library = [
IEvNumber(funds),
IEvNumber(approximateIncrement),
] =>
Internals.diminishingMarginalReturnsForManyFunctions(
Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
[lambda1, lambda2, lambda3, lambda4, lambda5],
funds,
approximateIncrement,
env,
reducer,
)
| _ => Error("Error in Danger.diminishingMarginalReturnsForFunctions5")
| _ =>
Error("Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions5")
},
(),
),
],
(),
),
Function.make(
~name="diminishingMarginalReturnsForFunctions6",
)
let optimalAllocationGivenDiminishingMarginalReturnsFunctions6 = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions6",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[
`Danger.diminishingMarginalReturnsForFunctions6({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, {|b| 17-b}, {|c| 19-c}, 100, 0.01)`,
`Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions6({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, {|b| 17-b}, {|c| 19-c}, 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForFunctions6",
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions6",
~inputs=[
FRTypeLambda,
FRTypeLambda,
@ -555,31 +555,32 @@ let library = [
IEvNumber(funds),
IEvNumber(approximateIncrement),
] =>
Internals.diminishingMarginalReturnsForManyFunctions(
Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
[lambda1, lambda2, lambda3, lambda4, lambda5, lambda6],
funds,
approximateIncrement,
env,
reducer,
)
| _ => Error("Error in Danger.diminishingMarginalReturnsForFunctions6")
| _ =>
Error("Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions6")
},
(),
),
],
(),
),
Function.make(
~name="diminishingMarginalReturnsForFunctions7",
)
let optimalAllocationGivenDiminishingMarginalReturnsFunctions7 = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions7",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[
`Danger.diminishingMarginalReturnsForFunctions7({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, {|b| 17-b}, {|c| 19-c}, {|d| 20-d/2}, 100, 0.01)`,
`Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions7({|x| x+1}, {|y| 10}, {|z| 20-2*z}, {|a| 15-a}, {|b| 17-b}, {|c| 19-c}, {|d| 20-d/2}, 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForFunctions7",
~name="optimalAllocationGivenDiminishingMarginalReturnsFunctions7",
~inputs=[
FRTypeLambda,
FRTypeLambda,
@ -604,33 +605,35 @@ let library = [
IEvNumber(funds),
IEvNumber(approximateIncrement),
] =>
Internals.diminishingMarginalReturnsForManyFunctions(
Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
[lambda1, lambda2, lambda3, lambda4, lambda5, lambda6, lambda7],
funds,
approximateIncrement,
env,
reducer,
)
| _ => Error("Error in Danger.diminishingMarginalReturnsForFunctions4")
| _ =>
Error("Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsFunctions7")
},
(),
),
],
(),
),
)
// The following will compile, but not work, because of this bug: <https://github.com/quantified-uncertainty/squiggle/issues/558> Instead, I am creating different functions for different numbers of inputs above.
/*
Function.make(
~name="diminishingMarginalReturnsForManyFunctions",
@dead
let optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions = Function.make(
~name="optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions",
~nameSpace,
~output=EvtArray,
~requiresNamespace=false,
~examples=[
`Danger.diminishingMarginalReturnsForManyFunctions([{|x| x+1}, {|y| 10}], 100, 0.01)`,
`Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions([{|x| x+1}, {|y| 10}], 100, 0.01)`,
],
~definitions=[
FnDefinition.make(
~name="diminishingMarginalReturnsForManyFunctions",
~name="optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions",
~inputs=[FRTypeArray(FRTypeLambda), FRTypeNumber, FRTypeNumber],
~run=(inputs, _, environment, reducer) =>
switch inputs {
@ -640,14 +643,14 @@ let library = [
| ReducerInterface_InternalExpressionValue.IEvLambda(lambda) => Ok(lambda)
| _ =>
Error(
"Error in Danger.diminishingMarginalReturnsForManyFunctions. A member of the array wasn't a function",
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. A member of the array wasn't a function",
)
}
}, innerlambdas)
let wrappedLambdas = E.A.R.firstErrorOrOpen(individuallyWrappedLambdas)
let result = switch wrappedLambdas {
| Ok(lambdas) => {
let result = Internals.diminishingMarginalReturnsForManyFunctions(
let result = Helpers.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions(
lambdas,
funds,
approximateIncrement,
@ -658,7 +661,7 @@ let library = [
}
| Error(b) => Error(b)
}
result //Error("wtf man")
result
}
| _ => Error("Error in Danger.diminishingMarginalReturnsForTwoFunctions")
},
@ -666,6 +669,37 @@ let library = [
),
],
(),
),
*/
)
}
}
let library = [
// Combinatorics
Combinatorics.Lib.laplace,
Combinatorics.Lib.factorial,
Combinatorics.Lib.choose,
Combinatorics.Lib.binomial,
// Integration
Integration.Lib.integrateFunctionBetweenWithNumIntegrationPoints,
// ^ Integral in terms of function, min, max, epsilon (distance between points)
// Execution time will be less predictable, because it
// will depend on min, max and epsilon together,
// as well and the complexity of the function
Integration.Lib.integrateFunctionBetweenWithEpsilon,
// ^ Integral in terms of function, min, max, num points
// Note that execution time will be more predictable, because it
// will only depend on num points and the complexity of the function
// Diminishing marginal return functions
// There are functions optimalAllocationGivenDiminishingMarginalReturnsFunctions2 through optimalAllocationGivenDiminishingMarginalReturnsFunctions7
// because of this bug: <https://github.com/quantified-uncertainty/squiggle/issues/1090>
// As soon as that is fixed, I will delete this bag of functions
// and uncomment the function below
DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsFunctions2,
DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsFunctions3,
DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsFunctions4,
DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsFunctions5,
DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsFunctions6,
DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsFunctions7,
// DiminishingReturns.Lib.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions
]