I have a function f(x). I want to calculate x where f(x) = max. How can I do that in a script?
Given: x is a positive number, f(x) can be positive or negative. I want to start with x = 1. If f(1) is already negative I'm not interested anymore. With increasing x, also f(x) returns increasing values, until a peak is reached, and then f(x) decreases. x at the peak is what I am interested in.
EDIT: Ok what I tried so far:
I tried starting with x = 1, then x *=2. If f(x) is smaller then the last result, I set back x to x/4.
Example: f(16) = 9, f(32) = 11, f(64) = 10. The peak can be between x=16 and x=64. So my new starting point is f(16). From there on, I want to continue in a similar way, but I cant find an algorithm.
Here is what I got so far:
let x = 1
let lasty = 0
let holder = 1
while (iteration < 20) {
let y = myFunction(x)
if(y < lasty ) {
x = x / 4
holder = 1
}
x = holder * 2
holder = 1
lasty = y
}
EDIT2: My improved version which works quite good but for sure not perfect:
let x = 1
let lasty = 0
let iteration = 0
let previousX = 1
let lastX = 1
let step = 2
let maxY = -Infinity
let bestX = 0
let randomInput = Math.random
while (iteration < 20) {
let y = myFunction(x, randomInput) //added randomInput to show the function does not rely on x alone
if (y < 0 && iteration == 1) break
if(y > maxY) {
maxY = y
bestX = x
}
if (y < lasty) {
x = previousX
step *= 0.8
lasty = 0
} else {
previousX = lastX
lastX = x
x = x * step
lasty = y
}
}
if(bestX > 0) {
console.log(`Got best x: ${bestX}`)
}
EDIT3: Added random additional parameter to emphasise the needed approach
EDIT4: I should also mention that the probability of f(x) = max is the highest when 0 < x < 100000
CodePudding user response:
Assuming you want to maximise y, You can just store the x and y values where xy is highest:
let highestX = 1; // this is just the corresponding x value for the highest y
let highestY = -Infinity;
let x = 1
let lasty = 0
let holder = 1
while (iteration < 20) {
let y = myFunction(x);
// code for storing the highest y and corresponding x
if (y > highestY) {
highestY = y;
highestX = x;
}
if(y < lasty ) {
x = x / 4
holder = 1
}
x = holder * 2
holder = 1
lasty = y
}
console.log('f(x) is maximised when x =', highestX);
CodePudding user response:
It could be solved using recursive function calls.
// array of arguments
const args = [...Array(16).keys()];
// sample function
const sampleFunc = (x) => Math.sin(x);
// recursive function
function getElementWithFuncMaximum(arr, func, index = 0, currValue = 0) {
const currFuncValue = func(arr[index]);
return currFuncValue >= currValue
? getElementWithFuncMaximum(arr, func, index 1, currFuncValue)
: arr[index - 1];
}
console.log(getElementWithFuncMaximum(args, sampleFunc));