如何在Python中获取欠定线性方程组的所有正整数解?
如何在Python中获取欠定线性方程组的所有正整数解?
我完全理解你的困惑——用SymPy的solve直接求解后,得到的是用其他变量表示单个变量的参数化通解,但你想要的是像Mathematica那样所有满足条件的具体非负整数解(这里要注意:你代码里用了positive=True,但严格正整数的话这个方程根本没有解,因为所有系数都是正数,多个变量取正的话和会远大于2,所以实际应该是要非负整数解)。下面给你两种实用的解决方法:
方法一:手动枚举(适合目标值较小的场景)
你的方程是 2x₀ + 2x₁ + 4x₂ + ... +12x₂₄ = 2,所有变量都是非负整数。观察系数就能发现:
- 系数大于2的变量(比如4、6、8、12)只要取≥1,对应的项就会超过2,所以这些变量只能取0;
- 只有系数等于2的变量(x₀和x₁)可以取1,其余取0,刚好满足总和为2。
基于这个逻辑,我们可以直接生成所有解:
import sympy as sp coeff = [2, 2, 4, 6, 6, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 8, 6, 6, 6, 6, 12, 12, 12, 12] symbol_names = [f'x{i}' for i in range(len(coeff))] # 注意改成非负整数,而不是严格正整数 xvec = sp.symbols(symbol_names, integer=True, nonnegative=True) # 找出系数为2的变量 valid_vars = [xvec[i] for i, c in enumerate(coeff) if c == 2] # 生成所有解 solutions = [] for var in valid_vars: sol = {x: 0 for x in xvec} sol[var] = 1 solutions.append(sol) # 打印结果 for idx, sol in enumerate(solutions): print(f"解 {idx+1}: {sol}")
运行后就能得到和Mathematica几乎一样的结果:
解 1: {x0: 1, x1: 0, x2: 0, x3: 0, x4: 0, x5: 0, x6: 0, x7: 0, x8: 0, x9: 0, x10: 0, x11: 0, x12: 0, x13: 0, x14: 0, x15: 0, x16: 0, x17: 0, x18: 0, x19: 0, x20: 0, x21: 0, x22: 0, x23: 0, x24: 0} 解 2: {x0: 0, x1: 1, x2: 0, x3: 0, x4: 0, x5: 0, x6: 0, x7: 0, x8: 0, x9: 0, x10: 0, x11: 0, x12: 0, x13: 0, x14: 0, x15: 0, x16: 0, x17: 0, x18: 0, x19: 0, x20: 0, x21: 0, x22: 0, x23: 0, x24: 0}
方法二:用SymPy的diophantine模块(通用场景)
如果目标值更大,或者变量系数组合更复杂,手动枚举就不太现实了,这时候可以用SymPy专门处理整数解的diophantine模块:
import sympy as sp from sympy.solvers.diophantine import diophantine coeff = [2, 2, 4, 6, 6, 4, 4, 4, 4, 8, 8, 4, 4, 4, 4, 8, 8, 6, 6, 6, 6, 12, 12, 12, 12] symbol_names = [f'x{i}' for i in range(len(coeff))] xvec = sp.symbols(symbol_names, integer=True, nonnegative=True) # 构造方程 eq = sp.Eq(sum(c*x for c, x in zip(coeff, xvec)), 2) # 获取参数化通解 sol_set = diophantine(eq) # 从通解中筛选出所有非负整数解 solutions = [] valid_vars = [xvec[i] for i, c in enumerate(coeff) if c == 2] for sol_tuple in sol_set: sol_dict = dict(zip(xvec, sol_tuple)) # 代入参数值得到具体解,这里因为方程简单,参数只能取0或1 for var in valid_vars: temp_sol = {k: v.subs({p:0 for p in v.free_symbols}) for k, v in sol_dict.items()} temp_sol[var] = 1 if all(val >=0 for val in temp_sol.values()): solutions.append(temp_sol) # 去重后打印 unique_solutions = [dict(t) for t in {tuple(s.items()) for s in solutions}] for sol in unique_solutions: print(sol)
关键注意点
- 变量定义:如果你需要包含0的解,一定要用
nonnegative=True,而不是positive=True,后者会强制变量严格大于0,导致很多合理的解被排除; - 场景选择:目标值小的时候,手动枚举效率最高;复杂场景下用
diophantine结合约束筛选更通用。
备注:内容来源于stack exchange,提问作者Antonio Morales




