gpt4 book ai didi

python - 在 Sympy 中部分分解表达式

转载 作者:行者123 更新时间:2023-12-01 09:05:59 25 4
gpt4 key购买 nike

假设我有一个 First Form 形式的表达式。我知道我可以像这样简化表达式: Second Form 。但是,sympy.simplifysympy.factor 都返回原始表达式。

为了解决这个问题,我一直在低级别对表达式进行操作:

factor_map = defaultdict(set)
additive_terms = expr.as_coeff_add()[-1]
for term1, term2 in combinations(additive_terms, 2):
common_terms = (
set(term1.as_coeff_mul()[-1])
& set(term2.as_coeff_mul()[-1])
)
if common_terms:
common_factor = sympy.Mul(*common_terms)
factor_map[common_factor] |= {term1, term2}

factor_map 现在看起来像这样:

{
a: {a⋅x, -a⋅y},
b: {b⋅x, -b⋅y},
c: {-c⋅x, c⋅y},
x: {a⋅x, b⋅x, -c⋅x},
y: {-a⋅y, -b⋅y, c⋅y}
}

我按照术语所代表的操作数量对其进行排序:

factor_list = sorted(
factor_map.items(),
key = lambda i: (i[0].count_ops() + 1) * len(i[1])
)[::-1]

然后我只需重建表达式:

used = set()
new_expr = 0
for item in factor_list:
factor = item[0]
appearances = item[-1]
terms = 0
for instance in appearances:
if instance not in used:
terms += instance.as_coefficient(factor)
used.add(instance)
new_expr += factor * terms
for term in set(additive_terms) - used:
new_expr += term

这给出了new_expr = d + x*(a + b - c) + y*(-a - b + c)。不是很好,但更好。

我还可以通过将加法项的每个组合彼此相除,检查结果是否为数字,并使用该信息进一步将输出减少为 new_expr = d + (x - y) 来改进这一点*(a + b - c)

我还尝试将 sympy.factor 应用于加性项的每种可能的组合,但显然对于任何相当大的表达式来说,它都会很快爆炸。

<小时/>

编辑:这是一个在附加项集的所有分区上使用 sympy.factor 的实现(分区函数借用 this answer ):

def partition(collection):
if len(collection) == 1:
yield [ collection ]
return

first = collection[0]
for smaller in partition(collection[1:]):
# insert `first` in each of the subpartition's subsets
for n, subset in enumerate(smaller):
yield smaller[:n] + [[ first ] + subset] + smaller[n+1:]
# put `first` in its own subset
yield [ [ first ] ] + smaller


def partial_factor(expr):
args = list(expr.as_coeff_add()[-1])
# Groupings is just a cache to avoid duplicating factor operations
groupings = {}

unique = set()

for p in partition(args):
new_expr = 0
for group in p:
add_group = sympy.Add(*group)
new_expr += groupings.setdefault(add_group, sympy.factor(add_group))
unique.add(new_expr)
return sorted(unique, key=sympy.count_ops)[0]

对于像 a*x + b*y + c*z + d + e*x + f*y + h*z 这样的表达式,在我的计算机上运行需要 7.8 秒,而另一种方法需要 378 微秒并给出相同的结果。看来应该有一种方法比第一种方法更严格,而且不用花两万倍的时间来解决。

<小时/>

我觉得得到我想要的东西不应该那么难。有没有更简单的方法来做到这一点?

最佳答案

This similar question有一个涉及 collect()func 参数的答案。尽管您必须明确提及d,但它似乎也适用于这种特殊情况:

from sympy import *
a, b, c, d, x, y = symbols('a, b, c, d, x, y')
expr = a * x + b * x - c * x - a * y - b * y + c * y + d
collect(expr, d, func=factor)
=> d + (x - y)*(a + b - c)

这在这种特定情况下有所帮助,但是不存在更通用和自动的解决方案。

此外,除了现有的之外,我在任何地方都找不到此 func 参数的任何文档。

Github issue tracking this problem

关于python - 在 Sympy 中部分分解表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52046815/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com