You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

欠定方程组求解:Sympy报错问题及随机近似解需求

欠定方程组近似求解方案

针对变量数远多于约束方程的情况,核心思路是固定大部分自由变量为接近0的小正数,将问题转化为2方程2变量的定解问题,再用数值方法求解,具体步骤和代码如下:

核心思路

由于系统欠定,我们可以选择保留2个变量作为待求解变量,将其余所有自由变量设为接近0的随机小正数(满足正数约束),这样原方程组就简化为定解系统,可通过数值求解器得到可行解。

具体实现步骤

1. 生成自由变量的小正数初始值

为满足变量为正数的约束,给自由变量生成1e-7~1e-6量级的随机正数,既接近0,又避免后续计算中出现分母为0的问题。

2. 代入自由变量,简化方程组

将自由变量的取值代入原方程,得到仅含2个待求解变量的新方程组,整理为残差等于0的形式(即目标值 - 表达式 = 0)。

3. 用数值求解器求解定解方程组

使用scipy.optimize.root代替sympy的nsolve,它更适合处理纯数值的非线性方程组,且对初始值的兼容性更好。

代码示例

import sympy as sp
import numpy as np
from scipy.optimize import root

# ---------------------- 替换为你的实际参数 ----------------------
# 定义常量(c0、c20为负数,其余非负)
c0 = -2
c1 = 5
c2 = 1
c3 = 2
c4 = 3  # x2的系数
c5 = 1  # x3的系数
# ... 补充其余常量

c20 = -1
c21 = 4
c22 = 1
c23 = 2  # x2的系数
c24 = 0.5  # x3的系数
# ... 补充其余c2x常量

# 定义目标值(即eq1、eq2的左边值)
target_eq1 = 1.2
target_eq2 = 0.6

# 定义变量:x0到x10共11个变量(可根据实际数量调整)
x = sp.symbols('x0:11', positive=True)
x0, x1 = x[0], x[1]
free_vars = x[2:]  # 自由变量x2~x10
# -------------------------------------------------------------

# 生成自由变量的小正数随机值
free_vals = np.random.uniform(1e-7, 1e-6, size=len(free_vars))
subs_dict = {var: val for var, val in zip(free_vars, free_vals)}

# 定义符号形式的残差方程(整理为目标值 - 表达式 = 0)
# 构建eq1的分母:c2*x0 + c3*x1 + 其他自由变量项
denominator_eq1 = c2*x0 + c3*x1 + sum([c4*x[2], c5*x[3]])  # 补充其余自由变量的系数项
residual_eq1 = target_eq1 - (c0 + c1 / denominator_eq1)

# 构建eq2的分母:c21*x0 + c22*x1 + 其他自由变量项
denominator_eq2 = c21*x0 + c22*x1 + sum([c23*x[2], c24*x[3]])  # 补充其余自由变量的系数项
residual_eq2 = target_eq2 - (c20 + c21*x0 / denominator_eq2)

# 将符号方程转为数值函数
residual_func1 = sp.lambdify((x0, x1), residual_eq1.subs(subs_dict), 'numpy')
residual_func2 = sp.lambdify((x0, x1), residual_eq2.subs(subs_dict), 'numpy')

# 组合为scipy所需的向量残差函数
def residual(vars):
    x0_val, x1_val = vars
    return [
        residual_func1(x0_val, x1_val),
        residual_func2(x0_val, x1_val)
    ]

# 设置x0、x1的初始猜测值(正数即可)
initial_guess = [1.0, 1.0]
# 调用求解器,使用LM方法适合非线性方程组
result = root(residual, initial_guess, method='lm')

# 输出结果
if result.success:
    x0_sol, x1_sol = result.x
    if x0_sol > 1e-8 and x1_sol > 1e-8:  # 确保解为正数
        full_sol = subs_dict.copy()
        full_sol[x0] = x0_sol
        full_sol[x1] = x1_sol
        print("可行解:")
        for var in sorted(full_sol.keys(), key=lambda v: str(v)):
            print(f"{var}: {full_sol[var]:.8f}")
    else:
        print("求解得到非正解,尝试调整初始值或自由变量取值")
else:
    print(f"求解失败:{result.message},可重新生成自由变量值或调整初始猜测")

注意事项

  • 若求解失败,可尝试:
    • 重新生成自由变量的随机值(调整uniform的范围)
    • 修改x0、x1的初始猜测值(比如设为0.5或2.0)
    • 检查常量和方程形式是否正确,确保分母不会出现0
  • 所有变量的正数约束通过初始值设置和结果校验保证,避免出现非正解

内容的提问来源于stack exchange,提问作者user23234204

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 11:12:08