如何指定SymPy中的已知变量?求解线性方程组获空解求助
问题描述
我正尝试使用SymPy求解一个包含32个未知变量、4个已知变量(e, j, o, t)和34个方程的大型方程组,目标是得到仅依赖已知变量的u, v, w, y, z, c_c的表达式,但不知道如何告知SymPye, j, o, t是已知变量。运行代码后输出空列表[],代码如下:
import sympy as sp a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = sp.symbols( 'a b c d e f g h i j k l m n o p q r s t u v w x y z') a_a, b_b, c_c, e_e, t_t, f_f, m_m, p_p, s_s, o_o = sp.symbols( 'a_a b_b c_c e_e t_t f_f m_m p_p s_s o_o') eq1 = sp.Eq(a+b+c+d, e) eq2 = sp.Eq(f+g+h+i, j) eq3 = sp.Eq(k+l+m+n, o) eq4 = sp.Eq(p+q+r+s, t) eq5 = sp.Eq(a+f+k+p, 1) eq6 = sp.Eq(b+g+l+q, 1) eq7 = sp.Eq(c+h+m+r, 1) eq8 = sp.Eq(d+i+n+s, 1) eq9 = sp.Eq(1/m_m, a) eq10 = sp.Eq(x/m_m, f) eq11 = sp.Eq(a_a/m_m, k) eq12 = sp.Eq(e_e/m_m, p) eq13 = sp.Eq(u/p_p, b) eq14 = sp.Eq(1/p_p, g) eq15 = sp.Eq(b_b/p_p, l) eq16 = sp.Eq(t_t/p_p, q) eq17 = sp.Eq(v/s_s, l) eq18 = sp.Eq(y/s_s, h) eq19 = sp.Eq(1/s_s, m) eq20 = sp.Eq(f_f/s_s, r) eq21 = sp.Eq(w/o_o, d) eq22 = sp.Eq(z/o_o, i) eq23 = sp.Eq(c_c/o_o, n) eq24 = sp.Eq(1/o_o, s) eq25 = sp.Eq(x, 1/u) eq26 = sp.Eq(a_a, 1/v) eq27 = sp.Eq(e_e, 1/w) eq28 = sp.Eq(b_b, 1/y) eq29 = sp.Eq(t_t, 1/z) eq30 = sp.Eq(f_f, 1/c_c) eq31 = sp.Eq(1+x+a_a+e_e, m_m) eq32 = sp.Eq(u+1+b_b+t_t, p_p) eq33 = sp.Eq(v+y+1+f_f, s_s) eq34 = sp.Eq(w+z+c_c+1, o_o) solution = sp.solve((eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12, eq13, eq14, eq15, eq16, eq17, eq18, eq19, eq20, eq21, eq22, eq23, eq24, eq25, eq26, eq27, eq28, eq29, eq30, eq31, eq32, eq33, eq34 ), u, v, w, y, z, c_c) print(solution)
解决方案
1. 明确已知变量的处理方式
SymPy的solve函数不需要专门标记已知变量,只需明确指定要解出的未知变量列表,其余未被指定的符号会自动被当作已知常量处理。
2. 分步简化方程组
原方程组嵌套了大量代换关系,直接一次性求解会增加SymPy的推导难度,建议先将中间变量用目标变量代换,再代入核心方程求解:
修改后的代码示例:
import sympy as sp # 定义所有符号 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = sp.symbols( 'a b c d e f g h i j k l m n o p q r s t u v w x y z') a_a, b_b, c_c, e_e, t_t, f_f, m_m, p_p, s_s, o_o = sp.symbols( 'a_a b_b c_c e_e t_t f_f m_m p_p s_s o_o') # 先处理代换关系,将中间变量用目标变量表示 subs_map = { x: 1/u, a_a: 1/v, e_e: 1/w, b_b: 1/y, t_t: 1/z, f_f: 1/c_c, m_m: 1 + x + a_a + e_e, p_p: u + 1 + b_b + t_t, s_s: v + y + 1 + f_f, o_o: w + z + c_c + 1, a: 1/m_m, f: x/m_m, k: a_a/m_m, p: e_e/m_m, b: u/p_p, g: 1/p_p, l: b_b/p_p, q: t_t/p_p, h: y/s_s, m: 1/s_s, r: f_f/s_s, d: w/o_o, i: z/o_o, n: c_c/o_o, s: 1/o_o } # 补充l的约束:原eq15和eq17都定义了l,需将其加入方程组 eq_l_constraint = sp.Eq(b_b/p_p, v/s_s).subs(subs_map) # 将代换代入核心方程(eq1到eq8) core_eqs = [ sp.Eq(a+b+c+d, e).subs(subs_map), sp.Eq(f+g+h+i, j).subs(subs_map), sp.Eq(k+l+m+n, o).subs(subs_map), sp.Eq(p+q+r+s, t).subs(subs_map), sp.Eq(a+f+k+p, 1).subs(subs_map), sp.Eq(b+g+l+q, 1).subs(subs_map), sp.Eq(c+h+m+r, 1).subs(subs_map), sp.Eq(d+i+n+s, 1).subs(subs_map), eq_l_constraint ] # 求解目标变量,e,j,o,t自动作为已知量 solution = sp.solve(core_eqs, (u, v, w, y, z, c_c), dict=True) # 输出结果 for idx, sol in enumerate(solution): print(f"解 {idx+1}:") print(f"u = {sp.simplify(sol[u])}") print(f"v = {sp.simplify(sol[v])}") print(f"w = {sp.simplify(sol[w])}") print(f"y = {sp.simplify(sol[y])}") print(f"z = {sp.simplify(sol[z])}") print(f"c_c = {sp.simplify(sol[c_c])}") print("---")
3. 关键注意事项
- 原方程组中
eq15和eq17都定义了变量l,这两个表达式必须等价,否则方程组无解,需将其作为约束方程加入求解列表。 - 分步代换能降低计算复杂度,避免SymPy因处理超大型方程组出现推导停滞或返回空解的情况。
- 调用
solve时,传入目标变量元组(u, v, w, y, z, c_c),SymPy会自动将e,j,o,t等未指定符号视为已知常量。
内容的提问来源于stack exchange,提问作者ndndinger
相关产品推荐
相关产品推荐

