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

牛顿法未返回定义域内全部收敛根的问题排查与优化咨询

牛顿法未返回定义域内全部收敛根的问题排查与优化咨询

嘿,我来帮你捋捋这个问题——你的代码逻辑其实犯了几个关键错误,导致你没法拿到所有收敛的根,甚至会出现奇怪的结果,咱们一步步拆解:

首先,你的批量初始点处理逻辑完全错了

你现在的代码把所有初始点当成一个整体来迭代,还要求所有点同时收敛才返回结果,这完全不符合牛顿法对批量初始点的处理方式啊!

举个例子:你在(-2,2)里取的初始点,有的会收敛到0,有的会收敛到π(属于牛顿法的吸引域问题),但你的代码会检查np.all(adz < TOL)——也就是所有点的误差都要小于阈值才返回。这显然不可能,因为收敛到0和π的点进度不一样,所以代码会一直迭代到最大次数,要么返回False,要么因为某些点迭代过度,反而跑到更远的根(比如±3π)去了。

而且你把所有点放在同一个数组里统一更新,这相当于把不同收敛路径的点强行混在一起处理,完全违背了每个初始点独立迭代的原则。

其次,代码里还有几个细节问题

  • 收敛判断逻辑错误:应该逐个点判断是否收敛,标记已收敛的点停止迭代,而不是要求所有点同时达标。
  • 未处理迭代中的导数为0情况:你只在最开始筛选了导数不为0的点,但迭代过程中某个点可能走到导数为0的位置,直接会导致除以0的报错。
  • 没有根去重机制:不同初始点会收敛到同一个根,你需要对结果去重才能得到唯一的根列表。

改进后的代码示例

我给你改了一个适合批量初始点的版本,每个点独立跟踪收敛状态,最后返回所有去重后的收敛根:

import numpy as np

def newton_batch(z0, f, fp, MAX_IT):
    TOL = 1e-10
    z = np.copy(z0)
    # 标记哪些点还在迭代中
    active = np.ones(z.shape, dtype=bool)
    roots = []
    
    for i in range(MAX_IT):
        # 只处理还没收敛的点
        z_active = z[active]
        if len(z_active) == 0:
            break  # 所有点都收敛了,提前退出
        
        # 过滤掉导数接近0的点(避免除以0)
        fp_active = fp(z_active)
        valid = np.abs(fp_active) > 1e-12  # 用小阈值代替严格等于0
        z_valid = z_active[valid]
        fp_valid = fp_active[valid]
        
        # 计算牛顿更新量
        dz = f(z_valid) / fp_valid
        z_valid -= dz
        
        # 更新原数组里的有效点
        z[active][valid] = z_valid
        
        # 检查哪些点已经收敛
        converged = np.abs(dz) < TOL
        # 收集新收敛的根
        new_roots = z_valid[converged]
        roots.extend(new_roots)
        
        # 更新活跃标记:收敛的点不再参与后续迭代
        active[active] &= ~np.concatenate([converged, np.ones(len(z_active) - len(z_valid), dtype=bool)])
    
    # 对根去重(考虑浮点误差,保留8位小数后去重)
    if roots:
        roots = np.array(roots)
        unique_roots = np.unique(np.round(roots, decimals=8))
        return unique_roots
    else:
        return np.array([])

关于牛顿法本身的限制(你提到的多项式问题)

即使代码改对了,也要明白:牛顿法不是万能的,它有吸引域的限制。每个根都有自己的吸引域,只有初始点落在某个根的吸引域内,才会收敛到那个根。比如多项式的牛顿分形,吸引域是分形结构,有些区域的初始点可能会发散到无穷,或者在几个根之间震荡。

如果想要覆盖所有根,可以结合其他方法:比如先用二分法(针对实根)或者其他全局寻根方法找到根的大致位置,再用牛顿法细化;或者用足够密集的初始点覆盖定义域,确保每个根的吸引域都被命中。

备注:内容来源于stack exchange,提问作者fractal_girl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 13:28:12