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

SymPy求解复杂表达式耗时过长,寻求优化方案

SymPy符号求解性能优化问题

我正在用SymPy对下方方程做符号求解,已经在solve函数里设置了simplify=False和rational=False,这对eq7的求解帮助很大,但对eq14完全没用,求解耗时极久。同款代码在Matlab里只需要几秒就能完成,该怎么优化?

from sympy import symbols, Eq, solve, Function

def dynamic_solver():
    # Define symbolic variables
    C_steps, O, Kc, Ko, kc, ko, S, Q, CB6F, RUB, kq, Kp1, Kp2, Kd, Kf, Ku, nl, nc, JP700_j, JP700_c, a2, a1, Abs, phi2P_a, phi2p_a, phi2u_a, q2_a, JP680_j, Vc_j, An_j, Ag_j, An_c, Ag_c, E, gtc, gm, Ca, Vc_c, Rd = symbols(
        'C_steps O Kc Ko kc ko S Q CB6F RUB kq Kp1 Kp2 Kd Kf Ku nl nc JP700_j JP700_c a2 a1 Abs phi2P_a phi2p_a phi2u_a q2_a JP680_j Vc_j An_j Ag_j An_c Ag_c E gtc gm Ca Vc_c Rd'
    )
    
    # Calculate S and gammas
    S = (kc / Kc) * (Ko / ko)
    gammas = O / (2 * S)
    
    # Define equations
    eq1 = JP700_j - (Q * CB6F * kq) / (Q + (CB6F * kq) / ((Abs - a2) * (Kp1 / (Kp1 + Kd + Kf))))    
    eq2 = eq1.subs(JP700_j, JP680_j * (1 - (nl / nc) + (3 + 7 * gammas / C_steps) / ((4 + 8 * gammas / C_steps) * nc)))    
    eq3 = eq2.subs(JP680_j, Vc_j * (4 * (1 + 2 * gammas / C_steps)))    
    eq4 = eq3.subs(Vc_j, Ag_j / (1 - gammas / C_steps))    
    eq5 = eq4.subs(Ag_j, An_j + Rd)    
    eq6 = eq5.subs(An_j, -(C_steps * E * gm + Ca * E * gm + 2 * C_steps * gm * gtc - 2 * Ca * gm * gtc) / (E + 2 * gm + 2 * gtc))    
    eq7 = solve(eq6, a2, dict=True,simplify=False,rational=False)
    
    # Pass out the first root
    eqA = Function('eqA')(Abs, C_steps, CB6F, Ca, E, Kc, Kd, Kf, Ko, Kp1, O, Q, Rd, gm, gtc, kc, ko, kq, nc, nl)
    eqA = eq7[0][a2]
    
    # Define equations for the second case
    eq8 = JP700_j - Q * a2 * phi2P_a * (1 - (nl / nc) + (3 + 7 * gammas / C_steps) / ((4 + 8 * gammas / C_steps) * nc))
    eq9 = eq8.subs(JP700_j, Q * CB6F * kq / (Q + CB6F * kq / ((Abs - a2) * (Kp1 / (Kp1 + Kd + Kf)))))
    eq10 = eq9.subs(phi2P_a, phi2p_a / (1 - phi2u_a))
    eq11 = eq10.subs(phi2p_a, (q2_a) * Kp2 / (Kp2 + Kd + Kf + Ku))
    eq12 = eq11.subs(phi2u_a, (q2_a) * Ku / (Kp2 + Kd + Kf + Ku) + (1 - q2_a) * Ku / (Kd + Kf + Ku))
    eq13 = eq12.subs(q2_a, 1 - (Q / (Q + CB6F * kq / ((Abs - a2) * (Kp1 / (Kp1 + Kd + Kf))))))
    eq14 = solve(eq13, a2, dict=True,simplify=False,rational=False)
    
    # Pass out the second root
    eqB = Function('eqB')(Abs, C_steps, CB6F, Kc, Kd, Kf, Ko, Kp1, Kp2, Ku, O, Q, kc, ko, kq, nc, nl)
    eqB = eq14[1][a2]
    
    return eqA, eqB

# Call the dynamic_solver function to obtain the equations eqA and eqB
eqA, eqB = dynamic_solver()

优化建议

  • 清理无关变量:代码中RUB、JP700_c、a1、An_c、Ag_c、Vc_c这些变量完全没参与eq13的推导,删除它们可以直接减少SymPy的计算负载。
  • 复用重复子表达式:多次出现的Q + CB6F * kq / ((Abs - a2) * (Kp1 / (Kp1 + Kd + Kf)))可以定义为临时符号,比如:
    temp_term = Q + CB6F * kq / ((Abs - a2) * (Kp1 / (Kp1 + Kd + Kf)))
    
    后续所有用到该表达式的地方直接替换为temp_term,避免重复构建复杂表达式。
  • 分步化简中间式:在每一步subs后对表达式做轻量化简(比如eq9 = eq9.simplify()),避免最终的eq13成为极度臃肿的分式结构,降低求解器的处理难度。
  • 转化为多项式求解:对eq13先通分去掉分母,将其转化为多项式方程后再求解。可以用eq13_poly = eq13.as_poly(a2),再对多项式调用solve,多项式求解通常比分式方程更高效。
  • 切换求解器:尝试用solveset替代solve,或者指定求解器的方法,比如对于有理方程,启用rational=True(根据方程实际情况调整),部分场景下专用求解逻辑会比通用求解器更快。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 10:55:56