如何在脚本中计算单峰函数f(x)取最大值时对应的x值
单峰函数峰值点求解方案
已知约束条件
- 目标函数
f(x)为单峰函数:x增大时函数值先递增,到峰值后持续递减 - x取值为正数,峰值高概率落在
0 < x < 100000区间内 - 从x=1开始计算,若
f(1)为负数直接终止计算 - 函数包含随机入参,输出不完全仅由x决定
适配方案
你已经在用的倍增法确定峰值区间的逻辑非常合理,后续可以搭配单峰函数最优的三分收敛法完成求解,整体逻辑如下:
- 沿用你现有的倍增逻辑:从x=1开始每次乘2,直到后一个点的函数值小于前一个点,就能确定峰值落在
[前前一个点, 当前点]的区间内 - 对锁定的区间用三分法迭代收缩:每次把区间均分为三段,比较两个三等分点的函数值,直接排除1/3的无效区间,迭代20~30次就能达到极高的精度
- 全程记录所有采样点的最大值,避免函数随机波动导致丢失最优解
完整实现代码
function findPeakX(myFunction, maxIter = 30, precision = 1e-6) { // 校验x=1的终止条件 const firstY = myFunction(1, Math.random()); if (firstY < 0) return null; // 第一步:倍增法锁定峰值区间 let left = 1, right = 2; let yLeft = firstY, yRight = myFunction(right, Math.random()); // 上限设置为20万,覆盖高概率区间 while (yRight > yLeft && right < 200000) { left = right; yLeft = yRight; right *= 2; yRight = myFunction(right, Math.random()); } let low = left / 2, high = right; // 第二步:三分法收敛求最优解 let maxY = -Infinity, bestX = 0; for (let i = 0; i < maxIter; i++) { if (high - low < precision) break; // 取两个三等分点 const m1 = low + (high - low) / 3; const m2 = high - (high - low) / 3; const y1 = myFunction(m1, Math.random()); const y2 = myFunction(m2, Math.random()); // 记录过程最大值 if (y1 > maxY) { maxY = y1; bestX = m1; } if (y2 > maxY) { maxY = y2; bestX = m2; } // 收缩无效区间 y1 < y2 ? low = m1 : high = m2; } // 最后校验区间中点 const midX = (low + high) / 2; const midY = myFunction(midX, Math.random()); if (midY > maxY) bestX = midX; return bestX; } // 调用示例 const bestX = findPeakX(myFunction); if (bestX) { console.log(`Got best x: ${bestX}`); }
方案优势
- 兼容你已有的初始搜索逻辑,改动成本极低
- 收敛速度快,30次迭代就能达到小数点后6位的精度,远低于常规迭代上限
- 全程记录最优值,适配函数带随机噪声的场景,不会因为单次随机波动丢失最优解
- 自动覆盖0~10万的高概率区间,不会漏过峰值点
内容的提问来源于stack exchange,提问作者flo
相关产品推荐
相关产品推荐

