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函数确保所有项为多项式,但报错仍未解决。
错误分析与修复方案
核心错误点
- 类型判断无效:
isinstance(ltg, poly)中,poly是Sympy的多项式构造函数而非类类型,正确类应为Poly;且LT()返回的是多项式首项(Term类型),并非Poly对象,该判断逻辑完全错误。 - 混淆LT与LM用法:
LT()返回带系数的首项,LM()返回首项的单项式(不含系数),多项式约简需基于单项式的整除性判断,而非带系数的首项。 - 除法操作类型不匹配:对首项直接使用
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
相关产品推荐
相关产品推荐

