
SymPy 拉普拉斯变换从“暴力积分”到规则表驱动引擎的设计与实现解析【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy本文以 SymPy 官方设计文档《Laplace Transform: Design Decisions and Implementation Details》laplace.md为主体结合 sympy/integrals/laplace.py 源码完整梳理 SymPy 拉普拉斯变换与逆拉普拉斯变换的规则表驱动实现包括算法的调用层级、规则表的构造方式、正/逆变换各自的规则执行顺序以及调试机制与微分方程求解配套工具。读完本篇你可以理解laplace_transform/inverse_laplace_transform背后的设计决策、看懂SYMPY_DEBUG调试输出的每一行含义并知道哪些环节适合扩展规则、哪些是已知的算法局限。1. 设计动机为什么放弃“直接积分”SymPy 早期的做法是所有积分变换一律通过计算积分来完成。作者指出这与教学实践相悖讲授拉普拉斯变换时老师要求学生永远不要靠积分而是查表、用已知规则。作者认为 SymPy 在大多数问题上“比查表的人类更弱、更慢”是令人遗憾的因此从 2021 年开始几乎完全重写了拉普拉斯变换优先使用规则只在规则全部失败时才回退到积分。到 2026 年初实际使用中积分几乎不再被触发即便被触发也往往给不出解。这种实现的优势是速度与能力作者称“massively faster”劣势同样明确每条规则都可能引入自己的 bug实现与作者基于多年电气工程拉普拉斯变换教学/使用经验形成的一种特定规则应用策略深度绑定。作者同时说明他希望能有类似的傅里叶变换实现但自己经验不足不敢动手因此本文的另一个目的是展示这些设计决策供 SymPy 其他“可用规则表改进算法”的模块参考。2. 数学背景定义、收敛域与线性原理2.1 正变换与逆变换的定义拉普拉斯变换把时域函数 $f(t)$ 变到复频域 $F(s)$$$F(s) \int_{0^{-}}^\infty f(t), e^{-st}, dt$$其中 $s$ 为复变量。下限 $0^{-}$ 表示“从零的下方无限接近零”若 $f(t)$ 含狄拉克 $\delta(t)$整个 $\delta(t)$ 都要参与计算。这一点在源码中对应 laplace_transform 的 docstring 说明当前只在 $f(t)$ 含DiracDelta时按下式处理——$$F(s) \lim_{\tau\to 0^{-}} \int_{\tau}^\infty e^{-st} f(t), dt$$逆变换用 Fourier–Mellin 积分$$f(t) \frac{1}{2\pi i} \lim_{\omega\to\infty} \int_{\sigma - i \omega}^{\sigma i \omega} e^{st} F(s), ds$$$\sigma$、$\omega$ 均为实变量。对 $\sigma$ 总存在使积分收敛的条件且通常很难算出——这正是业界自拉普拉斯变换诞生起就收集“已知变换对与规则”表的原因。最完整的表之一由 Bateman 于 1954 年整理出版。注意 Bateman 的表不含狄拉克 $\delta(t)$ 相关规则这部分见其他教材与通用资料。一个容易忽略的数学事实用 Fourier–Mellin 积分算出的 $f(t)$ 必须满足 $t0$ 时为 0。SymPy 通过在结果中返回Heaviside(t)因子来体现这一点文档强调这是数学上正确的做法其他计算机代数系统不做这一点。2.2 线性原理算法拆分的数学依据作为积分变换是线性的若 $f(t)\leftrightarrow F(s)$、$g(t)\leftrightarrow G(s)$则对任意 $a,b$ 有 $af(t)bg(t)\leftrightarrow aF(s)bG(s)$。因此任何可拆成求和的函数都可以逐项变换——这就是文档中“linearity principle”也是_laplace_transform第一步先按Add拆分表达式的依据。3. 对象、函数与代码结构laplace.py 引入两个可构造“未求值变换”的对象LaplaceTransform与InverseLaplaceTransform调用对象的.doit()即可求值 from sympy import LaplaceTransform, sin, symbols t symbols(t, realTrue) s symbols(s) LaplaceTransform(sin(t), t, s) LaplaceTransform(sin(t), t, s) LaplaceTransform(sin(t), t, s).doit() 1/(s**2 1)若目的是直接计算应使用前端函数laplace_transform与inverse_laplace_transform from sympy import laplace_transform, sin, symbols t symbols(t, realTrue) s symbols(s) laplace_transform(sin(t), t, s) (1/(s**2 1), 0, True)返回三元组变换结果、收敛平面半平面 $\operatorname{Re}(s) a$ 中的 $a$、附加条件。文档特别指出一个有意识的设计决策前端函数带nocondsTrue时只返回1/(s**21)而.doit(nocondsFalse)返回完整三元组(1/(s**21), 0, True)。之所以让所有内部函数一律返回条件、只在最外层按noconds裁剪是因为“写一堆永远返回条件的函数”远比把noconds一路透传进递归更容易维护、也没有额外计算开销。逆拉普拉斯变换默认不输出条件noconds默认为True。真正的计算工作由_laplace_transformlaplace.py#L1201与_inverse_laplace_transformlaplace.py#L2164完成两类入口殊途同归。3.1 调试包装器观察算法在做什么所有关键函数都套了DEBUG_WRAPlaplace.py#L49-L76。全局变量_LT_levellaplace.py#L46记录递归层数输出用缩进体现嵌套深度进入积分函数时会临时关闭调试以避免integrate内部刷屏。开启方式import sympy sympy.SYMPY_DEBUG True以laplace_transform(5*sin(t), t, s)为例调试输出如下摘自原文档[LT doit] (5*sin(t), t, s) ------------------------------------------------------------------------------ -LT- _laplace_transform(5*sin(t), t, s) -LT- _laplace_apply_simple_rules(sin(t), t, s) -LT- _laplace_build_rules is building rules -LT- _laplace_deep_collect(sin(_t), _t) -LT- _laplace_deep_collect(_t, _t) -LT- --- _t -LT- --- sin(_t) -LT- --- (1/(s**2 1), 0, True) -LT- --- (5/(s**2 1), 0, True) ------------------------------------------------------------------------------ (5/(s**2 1), 0, True)从外向内读_laplace_transform收到(5*sin(t), t, s)先提出系数把sin(t)交给_laplace_apply_simple_rules后者先经_laplace_build_rules建规则表再用_laplace_deep_collect归一化sin(_t)最终命中规则得到(1/(s**2 1), 0, True)乘回系数得(5/(s**2 1), 0, True)。作者强烈建议读者亲自开调试跑几个例子来读懂后文。4. 正变换算法_laplace_transform全流程4.1 入口层矩阵支持与条件裁剪前端laplace_transformlaplace.py#L1324对矩阵逐元素做变换并收集所有条件docstring 中标记了legacy_matrix的弃用迁移路径对非矩阵输入则交给LaplaceTransform对象执行.doit(nocondsFalse, simplify_simplify)最后按自身的noconds参数决定返回仅变换结果还是含条件的完整结果。对象LaplaceTransform.doit()laplace.py#L1292只向_laplace_transform传函数、两个变量和一个simplify键自己依据noconds决定返回形态。4.2 核心调度拆分求和、剥离 Heaviside、按序试规则_laplace_transform的完整流程laplace.py#L1201-L1265按Add拆项把a*f b*g拆成独立项分别变换含SingularityFunction的项先rewrite(Heaviside)Piecewise项不含DiracDelta(t)经_piecewise_to_heaviside重写为 Heaviside 形式剥离Heaviside(t)对不含DiracDelta的项直接把Heaviside(t)替换为 1因为积分域 $t\ge 0$ 上它恒为 1按固定顺序尝试_laplace_apply_simple_rules查表规则_laplace_apply_prog_rules算法性规则_laplace_expand展开再递归若表达式含未定义函数f(t)跳过积分直接返回LaplaceTransform对象_laplace_transform_integration积分回退汇总结果取各项之和收敛平面取所有项的Max条件取And。源码用海象运算符实现“任一成功即返回”的短路逻辑laplace.py#L1237-L1243if ( (r : _laplace_apply_simple_rules(ft, t_, s_)) is not None or (r : _laplace_apply_prog_rules(ft, t_, s_)) is not None or (r : _laplace_expand(ft, t_, s_)) is not None): pass elif ...所有规则函数要么返回结果、要么返回None任何一个成功则r保存结果否则落入elif分支。算法天然递归——多个被调函数内部会再次调用laplace_transform通常带simplifyFalse因为化简统一放在递归顶部做。文档明确指出防死循环只靠设计没有任何递归深度检查。文档还坦陈一个已知局限Bateman 表中存在极少数 $f(t)g(t)$ 可变换而 $f(t)$、$g(t)$ 各自不可变换的情形只有求和积分收敛。先拆求和的策略使这类情形难以处理据作者所知它们在实际中不相关若将来必须覆盖需要在拆分求和之前额外插入一个函数。4.3 简单规则.match()查表 规则五元组_laplace_apply_simple_rules依赖_laplace_build_ruleslaplace.py#L316构造规则表。该函数带cacheit缓存整个会话只构建一次。每条规则是一个五元组(时域匹配模式, 频域替换表达式, 规则适用条件, 收敛平面, 匹配前预处理函数)原文档给出的一条规则示例对应 laplace.py#L352编号 4.4.1 引自 Bateman 表(Heaviside(a*t-b), exp(-s*b/a)/s, And(a 0, b 0), S.Zero, dco), # 4.4.1它尝试把输入匹配到Heaviside(a*t-b)命中则返回exp(-s*b/a)/s仅当And(a 0, b 0)成立才生效收敛平面返回S.Zero。匹配前先执行dco即_laplace_deep_collect的简写见 laplace.py#L340遍历输入表达式、收集 $t$ 的系数把表达式整理成可被模式匹配的形式。_laplace_deep_collectlaplace.py#L299的作用是把类似f(w*t-1*t-c)的形式归一为f((w-1)*t-c)使其能匹配f(a*tb)。文档的例子 from sympy import Heaviside, laplace_transform, symbols s symbols(s) t symbols(t, realTrue) a, b symbols(a, b, positiveTrue) laplace_transform(Heaviside(a*(t - b)), t, s) (exp(-b*s)/s, 0, True)调试输出节选自原文档[LT doit] (Heaviside(a*(-b t)), t, s) ------------------------------------------------------------------------------ -LT- _laplace_transform(Heaviside(a*(-b t)), t, s) -LT- _laplace_apply_simple_rules(Heaviside(a*(-b t)), t, s) -LT- _laplace_build_rules is building rules -LT- _laplace_deep_collect(Heaviside(a*(_t - b)), _t) -LT- _laplace_deep_collect(a*(_t - b), _t) -LT- --- _t*a - a*b ... -LT- --- Heaviside(_t*a - a*b) -LT- --- (exp(-b*s)/s, 0, True) -LT- --- (exp(-b*s)/s, 0, True) ------------------------------------------------------------------------------关键在最后规则无法匹配原始形态Heaviside(a*(-b t))而能匹配归一化后的Heaviside(_t*a - a*b)——这正是dco预处理函数的价值。从源码看当前规则表laplace.py#L343-L531覆盖常数/幂函数/DiracDelta/Heaviside、指数与高斯型、对数、三角/双曲函数及其乘积、erf、Bessel 函数besselj/besseli/bessely/besselk等数十条规则注释标明 Bateman 表编号如# 4.5.1、# 4.7.80。表中还有相当数量的规则被注释掉并附有 TODO 说明例如含sqrt(a*t)的规则在as_base_exp改动后失效文档明确建议扩展规则表是新贡献者友好的切入点。规则表的实现覆盖情况可在 SymPy 开发文档仓库中查询原文档给出的外部链接此处不再复述。4.4 算法性规则_laplace_apply_prog_rules的固定顺序对无法用简单模式匹配解决的输入按以下固定顺序尝试laplace.py#L1003 汇总调用函数作用_laplace_rule_heaviside处理时移Heaviside()乘积正时移应用时移规则负时移直接移除还能处理Heaviside(a-t)形式的矩形窗窗口开/关以及未知函数f(t)的时移乘积_laplace_rule_delta利用狄拉克分布的掩蔽性质处理DiracDelta因子例如DiracDelta(t-a)*f(t) → f(a)*exp(-a*s)见 laplace.py#L623-L664含对多项式自变量多根情况的处理_laplace_rule_timescale处理时间缩放f(a*t)a0且a!1时转为LaplaceTransform(f(t)/a, t, s/a)_laplace_rule_exp移除指数因子exp(a*t)表达为频域平移s-a并相应修正收敛平面laplace.py#L599-L619_laplace_rule_trig最复杂的规则laplace.py#L861先把三角函数转成指数和分别变换再把来自sin/cosh的共轭复极对、来自sinh/cosh的对称实极对在 $s$ 域合并回“好看”的实系数表达式内部经_laplace_trig_split→_laplace_trig_expsum→_laplace_trig_ltex三步含_ccpole/_rspole/_quadpole等极对合并助手_laplace_rule_diff把 $t$ 域的导数替换为结果中的 $s$ 因子_laplace_rule_sdiff把 $t$ 域的t因子替换为 $s$ 域的导数频域微分性质文档强调上面许多函数会递归调用_laplace_transform且显式传simplifyFalse因为它们知道化简会在递归顶部统一执行。4.5 进一步展开_laplace_expand以上规则全部失败后_laplace_expandlaplace.py#L974按此顺序尝试expand(f, deepFalse)expand_mul(f)expand(f)expand(expand_trig(f))只要任一结果变为Add和就递归调用_laplace_transform此外若expand(f)改变了输入这本身也是一种防无限递归的设计决策也递归调用。4.6 积分回退_laplace_transform_integration最后手段是integrate(f*exp(-s*t), (t, S.Zero, S.Infinity))。这段代码的主体是重写integrate返回的条件——文档指出这段逻辑早于 2021 年重写、与integrate的具体实现耦合紧密维护时要注意。4.7 长调试示例一次典型的规则接力原文档用cos(a*t)*sinh(b*t)*sinh(c*t)展示算法的递归深度输出较长这里保留关键帧完整输出见 laplace.md from sympy import cos, laplace_transform, sinh, symbols import sympy sympy.SYMPY_DEBUG True s symbols(s) t symbols(t, realTrue) a, b, c symbols(a, b, c, realTrue) laplace_transform(cos(a*t)*sinh(b*t)*sinh(c*t), t, s) ((-s**3/2 s*(-a**2/2 (-b c)**2/2))/(a**4 2*a**2*(-b c)**2 s**4 s**2*(2*a**2 - 2*(-b c)**2) (-b c)**4) (s**3/2 s*(a**2/2 - (-b - c)**2/2))/(a**4 2*a**2*(-b - c)**2 s**4 s**2*(2*a**2 - 2*(-b - c)**2) (-b - c)**4), Max(Abs(b - c), Abs(b c)), True)调试输出摘录-LT- _laplace_transform(cos(a*t)*sinh(b*t)*sinh(c*t), t, s) -LT- _laplace_apply_simple_rules(cos(a*t)*sinh(b*t)*sinh(c*t), t, s) ... -LT- --- None -LT- _laplace_apply_prog_rules(cos(a*t)*sinh(b*t)*sinh(c*t), t, s) -LT- _laplace_rule_heaviside(...) --- None -LT- _laplace_rule_delta(...) --- None -LT- _laplace_rule_timescale(...) --- None -LT- _laplace_rule_exp(...) --- None -LT- _laplace_rule_trig(cos(a*t)*sinh(b*t)*sinh(c*t), t, s) -LT- _laplace_trig_split(...) -LT- --- (cos(_t*a)*sinh(_t*b)*sinh(_t*c), 1) -LT- _laplace_trig_expsum(cos(_t*a)*sinh(_t*b)*sinh(_t*c), _t) -LT- _laplace_deep_collect(-exp(_t*I*a _t*b - _t*c)/8, _t) # 三角→指数和后的 8 项 ... -LT- --- ([{k: -1/8, a: I*a b - c, re: b - c, im: a}, ..., {k: 1/8, a: -I*a - b - c, re: -b - c, im: -a}], []) -LT- _laplace_trig_ltex([...8 项极点...], _t, s) -LT- --- ((-s**3/2 ...)/(...) (s**3/2 ...)/(...), Max(Abs(b - c), Abs(b c))) -LT- --- ((-s**3/2 ...), Max(Abs(b - c), Abs(b c)), True) -LT- --- (最终结果, Max(Abs(b - c), Abs(b c)), True)流程清晰可见简单规则整体返回None五条算法性规则中前四条逐一返回None_laplace_rule_trig接管——先_laplace_trig_split分离_laplace_trig_expsum把乘积展开为 8 项k*exp(a*t)的指数和每项带re/im分量_laplace_trig_ltex对极点配对合并出实系数有理式与收敛平面Max(Abs(b-c), Abs(bc))。5. 逆变换算法规则分成两批是关键设计5.1 入口层前端inverse_laplace_transformlaplace.py#L2291同样支持矩阵逐元素处理非矩阵输入交给InverseLaplaceTransform对象执行.doit(nocondsFalse, simplify_simplify)按noconds裁剪返回。对象的doit()则向_inverse_laplace_transform传递函数、两个变量、收敛平面以及simplify、dorational两个键。InverseLaplaceTransform额外维护fundamental_plane属性laplace.py#L2239-L2244当构造时planeNone时内部用一个哨兵 Dummy 占位。5.2 核心调度_inverse_laplace_transform执行顺序laplace.py#L2164-L2217按Add拆项含一个技巧对含exp的项做subs(s,-s).together().subs(s,-s)把时移表达式规整为“分子上负指数”的形式便于后续时移规则匹配若是s的有理函数且dorationalTrue尝试_inverse_laplace_rational尝试规则表_inverse_laplace_apply_simple_rules尝试第一批算法性规则_inverse_laplace_early_prog_rules尝试_inverse_laplace_expand尝试第二批算法性规则_inverse_laplace_apply_prog_rules若含未定义函数返回InverseLaplaceTransform对象跳过积分最后尝试_inverse_laplace_transform_integration。任一成功即返回结果否则返回未求值的InverseLaplaceTransform对象。文档把“为什么把算法性规则拆成展开前/展开后两批”列为逆变换最重要的设计决策目标是让算法对可能输入的覆盖尽可能好。5.3 有理函数捷径_inverse_laplace_rational该函数laplace.py#L2106对s的二阶及以下有理函数直接套用全部已知的零阶/一阶/二阶公式apart部分分式后按分母阶数分支常数项→DiracDelta阶分布一次分母→exp(-a t)二次分母→判别后生成exp(-a t)(cos/sin)或cosh/sinh组合。若阶数高于二它递归调用_inverse_laplace_transform并强制dorationalFalse防止无限递归——源码中 laplace.py#L2151-L2154 正是这一防递归点。5.4 简单规则与两批算法性规则_inverse_laplace_apply_simple_ruleslaplace.py#L1604结构同正向的简单规则但规则少得多且有一条规则是硬编码的1的逆拉普拉斯变换是DiracDelta(t)laplace.py#L1608-L1610。其余规则来自_inverse_laplace_build_rules同样带缓存包括a/s、b*(sa)**(-c)、1/(s**2a**2)**2、1/(s**b)、1/(s*(sa)**b)等注意表中相邻规则的顺序有讲究文档与代码注释都说明a0的特例单独成规则。第一批_inverse_laplace_early_prog_ruleslaplace.py#L2050——适合在展开之前工作_inverse_laplace_laplace若输入是未求值的LaplaceTransform(f(t), t, s)直接返回f(t)*Heaviside(t)laplace.py#L2034-L2046_inverse_laplace_irrational算法化实现 $s^{-1/2}(s^{1/2}a)$ 这类无理分式实现方式类似_inverse_laplace_rational。展开_inverse_laplace_expandlaplace.py#L2078首先检查输入是否已经是Add是则返回None——这是防无限递归的必要设计。随后按expand(fn, deepFalse)→expand_mul(fn)→expand(fn)→ 有理函数则fn.apart(s).doit()的顺序尝试任一产生Add就递归。第二批_inverse_laplace_apply_prog_ruleslaplace.py#L2063——在展开无法继续时效果最好_inverse_laplace_time_shift找因子exp(a*s)替换为结果的时移t-a_inverse_laplace_freq_shift找频移s-a替换为因子exp(-a*t)_inverse_laplace_time_diff找因子s**n对结果应用 $n$ 阶导数_inverse_laplace_diff对s的 $n$ 阶导数替换为因子t**n_inverse_laplace_irrational再试一次。文档解释这是刻意的设计无理分式的输入形态多变无法预测何时需要展开所以必须试两遍。5.5 积分回退与调试示例全部失败后进入_inverse_laplace_transform_integrationlaplace.py#L1470。原文档给出的调试示例 from sympy import inverse_laplace_transform, sqrt, symbols s symbols(s) t symbols(t, realTrue) a, b symbols(a, b, positiveTrue) inverse_laplace_transform((a - b)*sqrt(s)/(sqrt(s) sqrt(a))/(s - b), s, t) (sqrt(a)*sqrt(b)*exp(b*t)*erfc(sqrt(b)*sqrt(t)) a*exp(a*t)*erfc(sqrt(a)*sqrt(t)) - b*exp(b*t))*Heaviside(t)[ILT doit] (sqrt(s)*(a - b)/((sqrt(a) sqrt(s))*(-b s)), s, t) ------------------------------------------------------------------------------ -LT- _inverse_laplace_transform(sqrt(s)*(a - b)/((sqrt(a) sqrt(s))*(-b s)), s, t, None) -LT- _inverse_laplace_apply_simple_rules(...) --- None -LT- _inverse_laplace_early_prog_rules(...) -LT- _inverse_laplace_laplace(...) --- None -LT- _inverse_laplace_irrational(...) -LT- rule 5.3.6 -LT- --- ((sqrt(a)*sqrt(b)*exp(b*t)*erfc(sqrt(b)*sqrt(t)) a*exp(a*t)*erfc(sqrt(a)*sqrt(t)) - b*exp(b*t))*Heaviside(t)/(a - b), True) -LT- --- ... -LT- --- (sqrt(a)*sqrt(b)*exp(b*t)*erfc(sqrt(b)*sqrt(t)) a*exp(a*t)*erfc(sqrt(a)*sqrt(t)) - b*exp(b*t))*Heaviside(t) ------------------------------------------------------------------------------输出显示_inverse_laplace_irrational命中规则 5.3.6Bateman 编号后在_inverse_laplace_expand之前就把问题解决了——两批规则的设计使展开机会被保留但简单路径优先。6. 其他实现细节原文档“Further details”一节列出无特定顺序均可以在源码中对应调试包装器DEBUG_WRAP(func)通过全局变量_LT_level跟踪递归层级laplace.py#L46-L83。ODE/PDE 配套工具laplace_correspondencelaplace.py#L1095把结果中未求值的LaplaceTransform(y(t), t, s)按字典{y: Y}替换为Y(s)InverseLaplaceTransform反向替换回y(t)laplace_initial_condslaplace.py#L1155接受{y: [y(0), y(0), y(0), ...]}形式的初始条件列表并逐阶替换。二者与laplace_transform/inverse_laplace_transform配合可代数化求解 ODE/PDE完整工作流见指南 solve-de-laplace.md——例如 ODE $y(t)9y(t)0$ 在初值 $y(0)y_0, y(0)v_0$ 下得到 $\theta(t)(\frac{v_0}{3}\sin 3t y_0\cos 3t)$结果天然带Heaviside(t)因子表示解在 $t0$ 时为 0若已知解对 $t0$ 也成立可手工subs(Heaviside(t), 1)。_as_integral()方法LaplaceTransformlaplace.py#L1289-L1290与InverseLaplaceTransformlaplace.py#L2250-L2255都提供_as_integral()返回本文开头给出的两个未求值积分公式本身。实验性_fast_inverse_laplacelaplace.py#L2352尝试用RootSum根和求解有理函数逆变换对Add/Mul/Pow/RootSum递归处理目前能力有限不接入主算法。7. 使用要点与适用边界小结结合文档与源码实际使用时的要点返回值形态laplace_transform(f, t, s)默认返回(F, a, cond)nocondsTrue只返回F。inverse_laplace_transform通过plane参数可显式给出收敛平面传None时由对象内部哨兵占位fundamental_plane属性会还原为None。Heaviside 因子是特性而非瑕疵逆变换结果含Heaviside(t)是数学正确性的体现文档还提示inverse_laplace_transform会无条件假设t为实与t的 SymPy 假设无关。simplify的位置内部递归一律simplifyFalse只在最顶层按doit(simplify...)做整体化简这是全局性的设计决策。防递归全靠构造算法没有深度检查防死循环依赖dorationalFalse回退、_inverse_laplace_expand拒绝Add输入、expand是否改变输入等结构性约束改动规则时需保留这些不变量。已知缺口Bateman 表中“和可变换而单项不可变换”的情形目前不覆盖规则表里被注释掉的条目如部分含sqrt(a*t)的规则是明确的扩展入口。测试基准位于 test_laplace.py公共 API 的导出可见 sympy/integrals/init.py。本文所有算法顺序、函数职责与代码引用均取自 laplace.md 设计文档及 sympy/integrals/laplace.py 当前实现若仓库后续重写相关模块请以实际源码为准。【免费下载链接】sympyA computer algebra system written in pure Python项目地址: https://gitcode.com/GitHub_Trending/sy/sympy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考