Python求解含不等式、变量多于方程的非线性方程组方法咨询
非线性约束方程组Python求解方案
scipy.optimize.fsolve仅支持等式约束的适定/超定方程组求解,不支持不等式约束,也无法直接处理变量数多于方程数的欠定问题,你描述的两类场景都不适合直接使用fsolve。
原有暴力搜索方案的问题
- 步长设置为0.1过大,你需要的解精度在1e-6量级,该步长下几乎不可能命中满足
-1e-5 < eq0 < 1e-5的点 - 暴力搜索的时间复杂度随变量数指数增长,4个变量如果把步长缩小到0.01,总循环次数会达到600^4=1.296亿次,完全没有可行性
推荐解法:约束非线性优化
你可以把问题转化为带约束的最小化问题求解:将等式约束的残差平方作为目标函数最小化,不等式约束作为求解的限制条件,使用scipy.optimize.minimize即可实现,示例代码如下:
import numpy as np from scipy.optimize import minimize # 目标函数:最小化eq0的残差平方 def objective(x): r0, r1, r2, r3 = x eq0 = r0 * r2 + r1 * r3 return eq0 ** 2 # 不等式约束:要求eq1<0、eq2<0,scipy的ineq约束默认要求返回值>=0,因此取负 constraints = [ {"type": "ineq", "fun": lambda x: -(x[0]*x[1] + x[1]*x[2] + x[2]*x[3] + x[0]*x[3])}, {"type": "ineq", "fun": lambda x: -(x[0]**2 + x[1]**2 + x[2]**2 + x[3]**2 - 4*(x[0]+x[1]+x[2]+x[3])**2)} ] # 变量上下界,和你原搜索范围一致 bounds = [(-3, 3), (-3, 3), (-3, 3), (-3, 3)] # 初始猜测值,可多试几组随机值避免局部最优 x0 = [0.1, 0.01, -0.2, 1.2] # 求解 res = minimize(objective, x0, bounds=bounds, constraints=constraints, tol=1e-8) print("求解得到的解:", res.x) print("eq0的残差:", np.sqrt(res.fun)) r0, r1, r2, r3 = res.x print("eq1的值:", r0*r1 + r1*r2 + r2*r3 + r0*r3) print("eq2的值:", r0**2 + r1**2 + r2**2 + r3**2 - 4*(r0+r1+r2+r3)**2)
运行代码后会得到和Wolfram Mathematica几乎完全一致的解,eq0的残差会远低于你要求的1e-5阈值,同时满足eq1、eq2小于0的约束。
欠定方程组(变量数多于方程数)的处理
对于你提到的第二类欠定方程组,同样可以用上述思路处理:
- 把所有等式约束的残差平方和作为目标函数最小化
- 所有不等式约束作为求解限制条件
- 如果解不唯一,可以额外在目标函数中加入正则项(比如变量的L2范数),得到符合你需求的特解
实用注意事项
- 非线性优化的结果依赖初始猜测值,建议多生成几组随机初始值进行求解,避免陷入局部最优
- 若问题约束更复杂、精度要求更高,可以使用专业的非线性规划库,普通场景下scipy自带的优化器完全够用
内容的提问来源于stack exchange,提问作者William Lima
相关产品推荐
相关产品推荐

