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

Sympy实现Gröbner基Buchberger算法报错:'int'无'is_commutative'属性

问题

在Python中使用Sympy库实现Buchberger算法计算Gröbner基时,持续遇到报错:

'Results check error: During the evaluation of 'groebner_basis' the next error occured: 'int' object has no attribute 'is_commutative'

无法定位错误位置,实现代码如下:

from sympy import symbols, div, LT, poly, lcm

def S_polynomial(f1, f2, mo):
    lcm_lt = lcm(f1.LM(order=mo), f2.LM(order=mo))
    term1 = lcm_lt // f1.LM(order=mo)
    term2 = lcm_lt // f2.LM(order=mo)
    # Ensure that term1 and term2 are symbolic expressions
    term1 = term1 * f1.as_expr()
    term2 = term2 * f2.as_expr()
    return poly(term1 - term2, *f1.gens)

def reduce_with_division(f, G, mo):
    while True:
        division_occurred = False
        for g in G:
            ltg = LT(g, order=mo)
            ltf = LT(f, order=mo)
            # Check if ltg is a Poly and divides ltf
            if isinstance(ltg, poly) and ltg.divides(ltf):
                quotient, _ = div(ltf, ltg)
                f = poly(f.as_expr() - quotient * g.as_expr(), *f.gens)
                division_occurred = True
                break
        if not division_occurred:
            return f

def groebner_basis(F, mo):
    G = [poly(f.as_expr(), *f.gens) for f in F]
    pairs = [(i, j) for i in range(len(G)) for j in range(i + 1, len(G))]
    
    while pairs:
        i, j = pairs.pop(0)
        sp = S_polynomial(G[i], G[j], mo)
        sp_reduced = reduce_with_division(sp, G, mo)
        
        if not sp_reduced.is_zero:
            for k in range(len(G)):
                pairs.append((k, len(G)))
            G.append(sp_reduced)

    return G

已尝试通过poly函数确保所有项为多项式,但报错仍未解决。

错误分析与修复方案

核心错误点

  1. 类型判断无效:isinstance(ltg, poly)中,poly是Sympy的多项式构造函数而非类类型,正确类应为Poly;且LT()返回的是多项式首项(Term类型),并非Poly对象,该判断逻辑完全错误。
  2. 混淆LT与LM用法:LT()返回带系数的首项,LM()返回首项的单项式(不含系数),多项式约简需基于单项式的整除性判断,而非带系数的首项。
  3. 除法操作类型不匹配:对首项直接使用div()函数会导致整数与符号表达式的类型冲突,应通过单项式除法计算商后再应用到整个多项式。

修复后的完整代码

from sympy import symbols, Poly, lcm, LT

def S_polynomial(f1, f2, monomial_order):
    # 获取首项单项式(不含系数)
    lm1 = f1.LM(order=monomial_order)
    lm2 = f2.LM(order=monomial_order)
    # 计算首项单项式的最小公倍数
    lcm_lm = lcm(lm1, lm2)
    # 构造S多项式的两项
    term1 = (lcm_lm / lm1) * f1
    term2 = (lcm_lm / lm2) * f2
    # 返回Poly类型的S多项式
    return term1 - term2

def reduce_with_division(f, G, monomial_order):
    while True:
        division_occurred = False
        for g in G:
            if g.is_zero:
                continue
            # 获取f和g的首项单项式
            f_lm = f.LM(order=monomial_order)
            g_lm = g.LM(order=monomial_order)
            # 检查g的首项单项式是否整除f的首项单项式
            if g_lm.divides(f_lm):
                # 计算商的首项(系数+单项式)
                f_lt = LT(f, order=monomial_order)
                g_lt = LT(g, order=monomial_order)
                quotient = f_lt / g_lt
                # 执行约简操作
                f = f - quotient * g
                division_occurred = True
                break
        if not division_occurred:
            return f

def groebner_basis(F, monomial_order):
    # 将输入转换为Poly对象
    G = [Poly(f) if not isinstance(f, Poly) else f for f in F]
    # 初始化所有待处理的多项式对
    pairs = [(i, j) for i in range(len(G)) for j in range(i + 1, len(G))]
    
    while pairs:
        i, j = pairs.pop(0)
        f1, f2 = G[i], G[j]
        # 计算S多项式
        sp = S_polynomial(f1, f2, monomial_order)
        # 约简S多项式
        sp_reduced = reduce_with_division(sp, G, monomial_order)
        
        if not sp_reduced.is_zero:
            # 添加新的多项式对(新多项式与现有所有多项式的组合)
            new_idx = len(G)
            pairs.extend([(k, new_idx) for k in range(new_idx)])
            G.append(sp_reduced)

    return G

关键修复说明

  • 统一使用Poly类处理所有多项式,避免类型转换混乱;
  • 明确区分LT()(带系数首项)和LM()(首项单项式)的用法,基于LM()判断整除性;
  • 直接对Poly对象进行算术运算,无需反复转换为表达式再转回多项式,减少类型错误;
  • 移除无效类型判断,改用divides()方法检查单项式整除性;
  • 优化多项式对添加逻辑,使用extend()简化代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:17:49