如何 return 为 sympy 中缺失的单项式归零
How to return zero for a missing monomial in sympy
我想 return 为缺少的单项式归零,但在 sympy 的文档中找不到任何指针。我的意图是从多个表达式构建一个稀疏数组。是否有捷径可寻?
MWE:
import sympy
x, y, z = sympy.symbols('x, y, z')
func_1 = 3 + x + 5 * y + 2 * z
func_2 = 1 + x + 2 * y
expr_2 = [func_1, func_2]
func_vars = [x, y, z]
eqs = sympy.parallel_poly_from_expr(expr_2, func_vars)
[[eqn.coeff_monomial(m) for m in eqn.monoms()][:-1] for eqn in eqs[0]]
# >>> [[1, 5, 2], [1, 2]]
# expected [[1,5,2],[1,2,0]]
根据 smichr 的建议使用带非线性变量的 indexedbase 更新了 MWE:
def get_coeffs(coeff_dict, func_vars):
c = coeff_dict
for i in list(c.keys()):
b, _ = i.as_base_exp()
if b == i:
continue
if b in c:
raise ValueError('multiple generators with %s' % b)
if any(k.has(b) for k in c):
raise ValueError('cross terms detected with %s' % b)
c[b] = c[i]
return [coeff_dict[val] for val in func_vars]
x = sympy.IndexedBase('x')
func_1 = 3 + x[0]**2 + 5 * x[1] + 2 * x[2]
func_2 = 1 + x[0] + 2 * x[1]
expr_2 = [func_1, func_2]
func_vars = [x[0], x[1], x[2]]
([get_coeffs(i.as_coefficients_dict(), func_vars) for i in expr_2])
# I get [[1, 5, 2], [1, 2, 0]]
如果它只是一个普通的列表,你可以post-处理它。要在右侧用 0
填充二维列表 x
,您可以这样做:
width = max(map(len, x))
for row in x:
row.extend([0] * (width - len(row)))
基本上,您可以通过找到所有行的最大宽度来获得整个内容的宽度。然后,对于每一行,您只需在其后插入多少 0
即可使其达到正确的宽度。
如果您使用的是线性方程,那么 linear_eq_to_matrix
可以处理原始(非多边形)表达式,为您提供系数矩阵:
>>> linear_eq_to_matrix([i.as_expr() for i in eqs[0]],[x,y,z])
(Matrix([
[1, 5, 2],
[1, 2, 0]]), Matrix([
[-3],
[-1]]))
as_coefficients_dict
方法可能是更好的选择。如果您拥有某个变量的幂,则可以修改生成的字典以存储具有相同系数的幂的底数。
>>> x=IndexedBase('x')
>>> eq=3 + x[0]**2 + 5 * x[1] + 2 * x[2]
>>> eq.as_coefficients_dict()
defaultdict(<class 'int'>, {1: 3, x[0]**2: 1, x[2]: 2, x[1]: 5})
>>> c=_
>>> for i in list(c.keys()):
... c[i.as_base_exp()[0]] = c[i] # set values bases of powers
...
>>> [_[x[i]] for i in range(4)] # default dict will supply 0
[1, 5, 2, 0]
我想 return 为缺少的单项式归零,但在 sympy 的文档中找不到任何指针。我的意图是从多个表达式构建一个稀疏数组。是否有捷径可寻? MWE:
import sympy
x, y, z = sympy.symbols('x, y, z')
func_1 = 3 + x + 5 * y + 2 * z
func_2 = 1 + x + 2 * y
expr_2 = [func_1, func_2]
func_vars = [x, y, z]
eqs = sympy.parallel_poly_from_expr(expr_2, func_vars)
[[eqn.coeff_monomial(m) for m in eqn.monoms()][:-1] for eqn in eqs[0]]
# >>> [[1, 5, 2], [1, 2]]
# expected [[1,5,2],[1,2,0]]
根据 smichr 的建议使用带非线性变量的 indexedbase 更新了 MWE:
def get_coeffs(coeff_dict, func_vars):
c = coeff_dict
for i in list(c.keys()):
b, _ = i.as_base_exp()
if b == i:
continue
if b in c:
raise ValueError('multiple generators with %s' % b)
if any(k.has(b) for k in c):
raise ValueError('cross terms detected with %s' % b)
c[b] = c[i]
return [coeff_dict[val] for val in func_vars]
x = sympy.IndexedBase('x')
func_1 = 3 + x[0]**2 + 5 * x[1] + 2 * x[2]
func_2 = 1 + x[0] + 2 * x[1]
expr_2 = [func_1, func_2]
func_vars = [x[0], x[1], x[2]]
([get_coeffs(i.as_coefficients_dict(), func_vars) for i in expr_2])
# I get [[1, 5, 2], [1, 2, 0]]
如果它只是一个普通的列表,你可以post-处理它。要在右侧用 0
填充二维列表 x
,您可以这样做:
width = max(map(len, x))
for row in x:
row.extend([0] * (width - len(row)))
基本上,您可以通过找到所有行的最大宽度来获得整个内容的宽度。然后,对于每一行,您只需在其后插入多少 0
即可使其达到正确的宽度。
如果您使用的是线性方程,那么 linear_eq_to_matrix
可以处理原始(非多边形)表达式,为您提供系数矩阵:
>>> linear_eq_to_matrix([i.as_expr() for i in eqs[0]],[x,y,z])
(Matrix([
[1, 5, 2],
[1, 2, 0]]), Matrix([
[-3],
[-1]]))
as_coefficients_dict
方法可能是更好的选择。如果您拥有某个变量的幂,则可以修改生成的字典以存储具有相同系数的幂的底数。
>>> x=IndexedBase('x')
>>> eq=3 + x[0]**2 + 5 * x[1] + 2 * x[2]
>>> eq.as_coefficients_dict()
defaultdict(<class 'int'>, {1: 3, x[0]**2: 1, x[2]: 2, x[1]: 5})
>>> c=_
>>> for i in list(c.keys()):
... c[i.as_base_exp()[0]] = c[i] # set values bases of powers
...
>>> [_[x[i]] for i in range(4)] # default dict will supply 0
[1, 5, 2, 0]