如何用Python暴力法求解给定二元函数的全局最大值与最小值?
没问题!scipy.optimize.brute完全能搞定这个二元函数的全局最值求解,核心就是把你的函数适配成它需要的输入格式就行,我给你一步步拆解实现:
用Scipy Brute求解二元函数全局最值
1. 先导入需要的库
import numpy as np from scipy.optimize import brute, fmin
2. 定义目标函数
brute要求函数接受一个一维数组作为输入,数组里的元素对应各个变量(这里就是x和y)。你可以直接按这个格式定义函数:
def f(params): x, y = params # 把你的原函数表达式搬过来就行 r1 = np.sqrt((x - 8)**2 + y**2) term1 = np.sin(r1) / r1 r2 = np.sqrt((x + 8)**2 + y**2) term2 = 0.8 * np.sin(r2) / r2 return term1 + term2
如果你想保留原来f(x,y)的写法,也可以用lambda快速包装一下:
def f(x, y): r1 = np.sqrt((x - 8)**2 + y**2) term1 = np.sin(r1) / r1 r2 = np.sqrt((x + 8)**2 + y**2) term2 = 0.8 * np.sin(r2) / r2 return term1 + term2 # 转成brute需要的单参数函数 f_for_brute = lambda params: f(params[0], params[1])
3. 运行暴力搜索找最值
找全局最小值
ranges参数用来指定每个变量的搜索区间,这里x和y都是[-20,20];Ns是每个维度的采样点数,对应你原来的linspace(-20,20,1000),所以设成1000就行:
# 定义搜索范围:x∈[-20,20],y∈[-20,20] search_ranges = ((-20, 20), (-20, 20)) # 运行brute,full_output=True会返回更多细节 min_result = brute(f, ranges=search_ranges, Ns=1000, full_output=True) min_point, min_value, _, _ = min_result print(f"全局最小值点:x={min_point[0]:.4f}, y={min_point[1]:.4f}") print(f"全局最小值:{min_value:.4f}")
找全局最大值
brute默认是找最小值,要找最大值的话,只需要对原函数取反,搜索这个反函数的最小值,对应的就是原函数的最大值:
# 定义取反后的函数 def f_neg(params): return -f(params) max_result = brute(f_neg, ranges=search_ranges, Ns=1000, full_output=True) max_point, max_neg_value, _, _ = max_result max_value = -max_neg_value print(f"\n全局最大值点:x={max_point[0]:.4f}, y={max_point[1]:.4f}") print(f"全局最大值:{max_value:.4f}")
4. 可选:用fmin细化结果
Brute是网格采样,精度取决于采样密度。如果需要更精准的极值点,可以用fmin在Brute找到的结果附近做局部优化:
# 细化最小值点 refined_min_point = fmin(f, min_point, disp=False) refined_min_val = f(refined_min_point) # 细化最大值点 refined_max_point = fmin(f_neg, max_point, disp=False) refined_max_val = f(refined_max_point) print(f"\n细化后全局最小值点:x={refined_min_point[0]:.6f}, y={refined_min_point[1]:.6f}") print(f"细化后全局最小值:{refined_min_val:.6f}") print(f"细化后全局最大值点:x={refined_max_point[0]:.6f}, y={refined_max_point[1]:.6f}") print(f"细化后全局最大值:{refined_max_val:.6f}")
小提示
- 你的函数是两个
sinc类函数(sin(r)/r)的组合,极值点大概在x=±8、y=0附近,Brute的1000点采样完全能覆盖到这些区域。 Ns越大,网格越密,结果越准,但计算时间也会变长,1000x1000的网格大概是100万次函数调用,在普通电脑上几秒就能跑完。
内容的提问来源于stack exchange,提问作者trala
相关产品推荐
相关产品推荐

