是否存在从表达式中提取子表达式的算法?

Does an algorithm for extracting sub expressions from an expression exist?

假设我的表达式是:

v = ((((x * 3) * y) * 5) * z) + 5

而且我想通过将子表达式移动到不同的变量中来尽可能减少 v 中的操作量,但保持 y 必须只出现在 v 中,如:

a = x * 3
b = 5 * z
v = ((a * y) * b) + 5

有算法可以实现吗?

如果程序仅限于带有加、减、次的直线程序,那么您可以将 v 的值确定为 y 中的多项式,并使用 Horner 方法对其进行计算。

这里有一些粗略的 Python 作为说明。

import operator


class Formula:
    def __init__(self, s=0):
        self.s = str(s)

    def __repr__(self):
        return "Formula({!r})".format(self.s)

    def __str__(self):
        return self.s

    def __add__(self, other):
        if isinstance(other, int):
            other = Formula(str(other))
        if not isinstance(other, Formula):
            return NotImplemented
        if other.s == "0":
            return self
        return Formula("({}) + ({})".format(self, other))

    def __radd__(self, other):
        return self + other

    def __mul__(self, other):
        if isinstance(other, int):
            other = Formula(str(other))
        if not isinstance(other, Formula):
            return NotImplemented
        if other.s == "0":
            return 0
        if other.s == "1":
            return self
        return Formula("({}) * ({})".format(self, other))

    def __rmul__(self, other):
        return self * other


class Polynomial:
    def __init__(self, *coefs):
        self.coefs = coefs

    def print_program(self):
        v = 0
        for i, coef in enumerate(reversed(self.coefs)):
            c = Formula("c{}".format(i))
            print("{} = {}".format(c, coef))
            v *= Formula("y")
            v += c
        print("v = {}".format(v))

    def __add__(self, other):
        if isinstance(other, int):
            other = Formula(other)
        if isinstance(other, Formula):
            other = Polynomial(other)
        if not isinstance(other, Polynomial):
            return NotImplemented
        coefs = list(map(operator.add, self.coefs, other.coefs))
        if len(self.coefs) > len(other.coefs):
            coefs.extend(self.coefs[len(other.coefs) :])
        if len(other.coefs) > len(self.coefs):
            coefs.extend(other.coefs[len(self.coefs) :])
        return Polynomial(*coefs)

    def __radd__(self, other):
        return self + other

    def __mul__(self, other):
        if isinstance(other, int):
            other = Formula(other)
        if isinstance(other, Formula):
            other = Polynomial(other)
        if not isinstance(other, Polynomial):
            return NotImplemented
        coefs = [0] * (len(self.coefs) + len(other.coefs) - 1)
        for i, ci in enumerate(self.coefs):
            for j, cj in enumerate(other.coefs):
                coefs[i + j] += ci * cj
        return Polynomial(*coefs)

    def __rmul__(self, other):
        return self * other


x = Formula("x")
y = Polynomial(0, 1)
z = Formula("z")

v = ((((x * 3) * y) * 5) * z) + 5
v.print_program()

输出为

c0 = (((x) * (3)) * (5)) * (z)
c1 = 5
v = ((c0) * (y)) + (c1)