Example #1
0
def test_issue_7840():
    # daveknippers' example
    C393 = sympify(  # noqa
        'Piecewise((C391 - 1.65, C390 < 0.5), (Piecewise((C391 - 1.65, \
        C391 > 2.35), (C392, True)), True))'
    )
    C391 = sympify(  # noqa
        'Piecewise((2.05*C390**(-1.03), C390 < 0.5), (2.5*C390**(-0.625), True))'
    )
    C393 = C393.subs('C391',C391)  # noqa
    # simple substitution
    sub = {}
    sub['C390'] = 0.703451854
    sub['C392'] = 1.01417794
    ss_answer = C393.subs(sub)
    # cse
    substitutions, new_eqn = cse(C393)
    for pair in substitutions:
        sub[pair[0].name] = pair[1].subs(sub)
    cse_answer = new_eqn[0].subs(sub)
    # both methods should be the same
    assert ss_answer == cse_answer

    # GitRay's example
    expr = sympify(
        "Piecewise((Symbol('ON'), Equality(Symbol('mode'), Symbol('ON'))), \
        (Piecewise((Piecewise((Symbol('OFF'), StrictLessThan(Symbol('x'), \
        Symbol('threshold'))), (Symbol('ON'), S.true)), Equality(Symbol('mode'), \
        Symbol('AUTO'))), (Symbol('OFF'), S.true)), S.true))"
    )
    substitutions, new_eqn = cse(expr)
    # this Piecewise should be exactly the same
    assert new_eqn[0] == expr
    # there should not be any replacements
    assert len(substitutions) < 1
Example #2
0
def test_issue_7840():
    # daveknippers' example
    C393 = sympify(  # noqa
        'Piecewise((C391 - 1.65, C390 < 0.5), (Piecewise((C391 - 1.65, \
        C391 > 2.35), (C392, True)), True))'
    )
    C391 = sympify(  # noqa
        'Piecewise((2.05*C390**(-1.03), C390 < 0.5), (2.5*C390**(-0.625), True))'
    )
    C393 = C393.subs('C391',C391)  # noqa
    # simple substitution
    sub = {}
    sub['C390'] = 0.703451854
    sub['C392'] = 1.01417794
    ss_answer = C393.subs(sub)
    # cse
    substitutions, new_eqn = cse(C393)
    for pair in substitutions:
        sub[pair[0].name] = pair[1].subs(sub)
    cse_answer = new_eqn[0].subs(sub)
    # both methods should be the same
    assert ss_answer == cse_answer

    # GitRay's example
    expr = sympify(
        "Piecewise((Symbol('ON'), Equality(Symbol('mode'), Symbol('ON'))), \
        (Piecewise((Piecewise((Symbol('OFF'), StrictLessThan(Symbol('x'), \
        Symbol('threshold'))), (Symbol('ON'), S.true)), Equality(Symbol('mode'), \
        Symbol('AUTO'))), (Symbol('OFF'), S.true)), S.true))"
    )
    substitutions, new_eqn = cse(expr)
    # this Piecewise should be exactly the same
    assert new_eqn[0] == expr
    # there should not be any replacements
    assert len(substitutions) < 1
Example #3
0
def test_cse_not_possible():
    # No substitution possible.
    e = Add(x, y)
    substs, reduced = cse([e])
    assert substs == []
    assert reduced == [x + y]
    # issue 6329
    eq = (meijerg((1, 2), (y, 4), (5,), [], x)
          + meijerg((1, 3), (y, 4), (5,), [], x))
    assert cse(eq) == ([], [eq])
Example #4
0
def test_cse_not_possible():
    # No substitution possible.
    e = Add(x, y)
    substs, reduced = cse([e])
    assert substs == []
    assert reduced == [x + y]
    # issue 6329
    eq = (meijerg((1, 2), (y, 4), (5,), [], x) +
          meijerg((1, 3), (y, 4), (5,), [], x))
    assert cse(eq) == ([], [eq])
Example #5
0
def test_recursive_matching():
    assert cse([x+y, 2+x+y, x+y+z, 3+x+y+z]) == \
        ([(x0, x + y), (x1, x0 + z)], [x0, x0 + 2, x1, x1 + 3])
    assert cse(reversed([x+y, 2+x+y, x+y+z, 3+x+y+z])) == \
        ([(x0, x + y), (x1, x0 + z)], [x1 + 3, x1, x0 + 2, x0])
    # sympy 1.0 gives ([(x0, x*y*z)], [5*x0, w*(x*y), 3*x0])
    assert cse([x*y*z*5, x*y*w, x*y*z*3]) == \
        ([(x0, x*y), (x1, x0*z)], [5*x1, w*x0, 3*x1])
    # sympy 1.0 gives ([(x4, x*y*z)], [5*x4, w*x3*x4, 3*x*x0*x1*x2*y])
    assert cse([x*y*z*5, x*y*z*w*x3, x*y*3*x0*x1*x2]) == \
        ([(x4, x*y), (x5, x4*z)], [5*x5, w*x3*x5, 3*x0*x1*x2*x4])
    assert cse([2*x*x, x*x*y, x*x*y*w, x*x*y*w*x0, x*x*y*w*x2]) == \
        ([(x1, x**2), (x3, x1*y), (x4, w*x3)], [2*x1, x3, x4, x0*x4, x2*x4])
Example #6
0
def test_recursive_matching():
    assert cse([x+y, 2+x+y, x+y+z, 3+x+y+z]) == \
        ([(x0, x + y), (x1, x0 + z)], [x0, x0 + 2, x1, x1 + 3])
    assert cse(reversed([x+y, 2+x+y, x+y+z, 3+x+y+z])) == \
        ([(x0, x + y), (x1, x0 + z)], [x1 + 3, x1, x0 + 2, x0])
    # sympy 1.0 gives ([(x0, x*y*z)], [5*x0, w*(x*y), 3*x0])
    assert cse([x*y*z*5, x*y*w, x*y*z*3]) == \
        ([(x0, x*y), (x1, x0*z)], [5*x1, w*x0, 3*x1])
    # sympy 1.0 gives ([(x4, x*y*z)], [5*x4, w*x3*x4, 3*x*x0*x1*x2*y])
    assert cse([x*y*z*5, x*y*z*w*x3, x*y*3*x0*x1*x2]) == \
        ([(x4, x*y), (x5, x4*z)], [5*x5, w*x3*x5, 3*x0*x1*x2*x4])
    assert cse([2*x*x, x*x*y, x*x*y*w, x*x*y*w*x0, x*x*y*w*x2]) == \
        ([(x1, x**2), (x3, x1*y), (x4, w*x3)], [2*x1, x3, x4, x0*x4, x2*x4])
Example #7
0
def test_dont_cse_subs():
    f = Function("f")
    g = Function("g")

    name_val, (expr,) = cse(f(x+y).diff(x) + g(x+y).diff(x))

    assert name_val == []
Example #8
0
def test_issue_4499():
    # previously, this gave 16 constants
    from sympy.abc import a, b
    from sympy import Tuple, S
    B = Function("B")  # noqa
    G = Function("G")  # noqa
    t = Tuple(*(
        a,
        a + S(1) / 2,
        2 * a,
        b,
        2 * a - b + 1,
        (sqrt(z) / 2)**(-2 * a + 1) * B(2 * a - b, sqrt(z)) *
        B(b - 1, sqrt(z)) * G(b) * G(2 * a - b + 1),  # noqa
        sqrt(z) * (sqrt(z) / 2)**(-2 * a + 1) * B(b, sqrt(z)) * B(
            2 * a - b,  # noqa
            sqrt(z)) * G(b) * G(2 * a - b + 1),
        sqrt(z) * (sqrt(z) / 2)**(-2 * a + 1) * B(b - 1, sqrt(z)) *
        B(2 * a - b + 1, sqrt(z)) * G(b) * G(2 * a - b + 1),
        (sqrt(z) / 2)**(-2 * a + 1) * B(b, sqrt(z)) * B(
            2 * a - b + 1,  # noqa
            sqrt(z)) * G(b) * G(2 * a - b + 1),
        1,
        0,
        S(1) / 2,
        z / 2,
        -b + 1,
        -2 * a + b,  # noqa
        -2 * a))  # noqa
    c = cse(t)
    assert len(c[0]) == 11
    def run_global_cse(self, extra_exprs=[]):
        import time
        start_time = time.time()

        logger.info("common subexpression elimination: start")

        assign_names = sorted(self.assignments)
        assign_exprs = [self.assignments[name] for name in assign_names]

        # Options here:
        # - checked_cse: if you mistrust the result of the cse.
        #   Uses maxima to verify.
        # - sym.cse: The sympy thing.
        # - sumpy.cse.cse: Based on sympy, designed to go faster.
        #from sumpy.symbolic import checked_cse

        from sumpy.cse import cse
        new_assignments, new_exprs = cse(assign_exprs + extra_exprs,
                                         symbols=self.symbol_generator)

        new_assign_exprs = new_exprs[:len(assign_exprs)]
        new_extra_exprs = new_exprs[len(assign_exprs):]

        for name, new_expr in zip(assign_names, new_assign_exprs):
            self.assignments[name] = new_expr

        for name, value in new_assignments:
            assert isinstance(name, sym.Symbol)
            self.add_assignment(name.name, value)

        logger.info(
            "common subexpression elimination: done after {dur:.2f} s".format(
                dur=time.time() - start_time))
        return new_extra_exprs
Example #10
0
def test_dont_cse_subs():
    f = Function("f")
    g = Function("g")

    name_val, (expr,) = cse(f(x+y).diff(x) + g(x+y).diff(x))

    assert name_val == []
Example #11
0
    def run_global_cse(self, extra_exprs=[]):
        import time
        start_time = time.time()

        logger.info("common subexpression elimination: start")

        assign_names = sorted(self.assignments)
        assign_exprs = [self.assignments[name] for name in assign_names]

        # Options here:
        # - checked_cse: if you mistrust the result of the cse.
        #   Uses maxima to verify.
        # - sym.cse: The sympy thing.
        # - sumpy.cse.cse: Based on sympy, designed to go faster.
        #from sumpy.symbolic import checked_cse

        from sumpy.cse import cse
        new_assignments, new_exprs = cse(assign_exprs + extra_exprs,
                symbols=self.symbol_generator)

        new_assign_exprs = new_exprs[:len(assign_exprs)]
        new_extra_exprs = new_exprs[len(assign_exprs):]

        for name, new_expr in zip(assign_names, new_assign_exprs):
            self.assignments[name] = new_expr

        for name, value in new_assignments:
            assert isinstance(name, sym.Symbol)
            self.add_assignment(name.name, value)

        logger.info("common subexpression elimination: done after {dur:.2f} s"
                    .format(dur=time.time() - start_time))
        return new_extra_exprs
Example #12
0
def test_issue_6169():
    from sympy import CRootOf
    r = CRootOf(x**6 - 4*x**5 - 2, 1)
    assert cse(r) == ([], [r])
    # and a check that the right thing is done with the new
    # mechanism
    assert sub_post(sub_pre((-x - y)*z - x - y)) == -z*(x + y) - x - y
Example #13
0
def test_Piecewise():  # noqa
    from sympy import Piecewise, Eq
    f = Piecewise((-z + x*y, Eq(y, 0)), (-z - x*y, True))
    ans = cse(f)
    actual_ans = ([(x0, -z), (x1, x*y)],
                  [Piecewise((x0+x1, Eq(y, 0)), (x0 - x1, True))])
    assert ans == actual_ans
Example #14
0
def test_Piecewise():  # noqa
    from sympy import Piecewise, Eq
    f = Piecewise((-z + x*y, Eq(y, 0)), (-z - x*y, True))
    ans = cse(f)
    actual_ans = ([(x0, -z), (x1, x*y)],
                  [Piecewise((x0+x1, Eq(y, 0)), (x0 - x1, True))])
    assert ans == actual_ans
Example #15
0
def test_issue_6169():
    from sympy import CRootOf
    r = CRootOf(x**6 - 4*x**5 - 2, 1)
    assert cse(r) == ([], [r])
    # and a check that the right thing is done with the new
    # mechanism
    assert sub_post(sub_pre((-x - y)*z - x - y)) == -z*(x + y) - x - y
Example #16
0
def test_subtraction_opt():
    # Make sure subtraction is optimized.
    e = (x - y)*(z - y) + exp((x - y)*(z - y))
    substs, reduced = cse(
        [e], optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)])
    assert substs == [(x0, (x - y)*(y - z))]
    assert reduced == [-x0 + exp(-x0)]
    e = -(x - y)*(z - y) + exp(-(x - y)*(z - y))
    substs, reduced = cse(
        [e], optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)])
    assert substs == [(x0, (x - y)*(y - z))]
    assert reduced == [x0 + exp(x0)]
    # issue 4077
    n = -1 + 1/x
    e = n/x/(-n)**2 - 1/n/x
    assert cse(e, optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)]) == \
        ([], [0])
Example #17
0
def test_subtraction_opt():
    # Make sure subtraction is optimized.
    e = (x - y)*(z - y) + exp((x - y)*(z - y))
    substs, reduced = cse(
        [e], optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)])
    assert substs == [(x0, (x - y)*(y - z))]
    assert reduced == [-x0 + exp(-x0)]
    e = -(x - y)*(z - y) + exp(-(x - y)*(z - y))
    substs, reduced = cse(
        [e], optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)])
    assert substs == [(x0, (x - y)*(y - z))]
    assert reduced == [x0 + exp(x0)]
    # issue 4077
    n = -1 + 1/x
    e = n/x/(-n)**2 - 1/n/x
    assert cse(e, optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)]) == \
        ([], [0])
Example #18
0
def test_dont_cse_derivative():
    from sumpy.symbolic import Derivative
    f = Function("f")

    deriv = Derivative(f(x+y), x)

    name_val, (expr,) = cse(x + y + deriv)

    assert name_val == []
    assert expr == x + y + deriv
Example #19
0
def test_dont_cse_derivative():
    from sumpy.symbolic import Derivative
    f = Function("f")

    deriv = Derivative(f(x+y), x)

    name_val, (expr,) = cse(x + y + deriv)

    assert name_val == []
    assert expr == x + y + deriv
Example #20
0
def test_cse_Indexed():  # noqa
    from sympy import IndexedBase, Idx
    len_y = 5
    y = IndexedBase('y', shape=(len_y,))
    x = IndexedBase('x', shape=(len_y,))
    Dy = IndexedBase('Dy', shape=(len_y-1,))  # noqa
    i = Idx('i', len_y-1)

    expr1 = (y[i+1]-y[i])/(x[i+1]-x[i])
    expr2 = 1/(x[i+1]-x[i])
    replacements, reduced_exprs = cse([expr1, expr2])
    assert len(replacements) > 0
Example #21
0
def test_cse_Indexed():  # noqa
    from sympy import IndexedBase, Idx
    len_y = 5
    y = IndexedBase('y', shape=(len_y,))
    x = IndexedBase('x', shape=(len_y,))
    Dy = IndexedBase('Dy', shape=(len_y-1,))  # noqa
    i = Idx('i', len_y-1)

    expr1 = (y[i+1]-y[i])/(x[i+1]-x[i])
    expr2 = 1/(x[i+1]-x[i])
    replacements, reduced_exprs = cse([expr1, expr2])
    assert len(replacements) > 0
Example #22
0
def test_pow_invpow():
    assert cse(1/x**2 + x**2) == \
        ([(x0, x**2)], [x0 + 1/x0])
    assert cse(x**2 + (1 + 1/x**2)/x**2) == \
        ([(x0, x**2), (x1, 1/x0)], [x0 + x1*(x1 + 1)])
    assert cse(1/x**2 + (1 + 1/x**2)*x**2) == \
        ([(x0, x**2), (x1, 1/x0)], [x0*(x1 + 1) + x1])
    assert cse(cos(1/x**2) + sin(1/x**2)) == \
        ([(x0, x**(-2))], [sin(x0) + cos(x0)])
    assert cse(cos(x**2) + sin(x**2)) == \
        ([(x0, x**2)], [sin(x0) + cos(x0)])
    assert cse(y/(2 + x**2) + z/x**2/y) == \
        ([(x0, x**2)], [y/(x0 + 2) + z/(x0*y)])
    assert cse(exp(x**2) + x**2*cos(1/x**2)) == \
        ([(x0, x**2)], [x0*cos(1/x0) + exp(x0)])
    assert cse((1 + 1/x**2)/x**2) == \
        ([(x0, x**(-2))], [x0*(x0 + 1)])
    assert cse(x**(2*y) + x**(-2*y)) == \
        ([(x0, x**(2*y))], [x0 + 1/x0])
Example #23
0
def test_pow_invpow():
    assert cse(1/x**2 + x**2) == \
        ([(x0, x**2)], [x0 + 1/x0])
    assert cse(x**2 + (1 + 1/x**2)/x**2) == \
        ([(x0, x**2), (x1, 1/x0)], [x0 + x1*(x1 + 1)])
    assert cse(1/x**2 + (1 + 1/x**2)*x**2) == \
        ([(x0, x**2), (x1, 1/x0)], [x0*(x1 + 1) + x1])
    assert cse(cos(1/x**2) + sin(1/x**2)) == \
        ([(x0, x**(-2))], [sin(x0) + cos(x0)])
    assert cse(cos(x**2) + sin(x**2)) == \
        ([(x0, x**2)], [sin(x0) + cos(x0)])
    assert cse(y/(2 + x**2) + z/x**2/y) == \
        ([(x0, x**2)], [y/(x0 + 2) + z/(x0*y)])
    assert cse(exp(x**2) + x**2*cos(1/x**2)) == \
        ([(x0, x**2)], [x0*cos(1/x0) + exp(x0)])
    assert cse((1 + 1/x**2)/x**2) == \
        ([(x0, x**(-2))], [x0*(x0 + 1)])
    assert cse(x**(2*y) + x**(-2*y)) == \
        ([(x0, x**(2*y))], [x0 + 1/x0])
Example #24
0
def test_issue_4499():
    # previously, this gave 16 constants
    from sympy.abc import a, b
    from sympy import Tuple, S
    B = Function('B')  # noqa
    G = Function('G')  # noqa
    t = Tuple(
        *(a, a + S(1)/2, 2*a, b, 2*a - b + 1, (sqrt(z)/2)**(-2*a + 1)*B(2*a
        - b, sqrt(z))*B(b - 1, sqrt(z))*G(b)*G(2*a - b + 1),
        sqrt(z)*(sqrt(z)/2)**(-2*a + 1)*B(b, sqrt(z))*B(2*a - b,
        sqrt(z))*G(b)*G(2*a - b + 1), sqrt(z)*(sqrt(z)/2)**(-2*a + 1)*B(b - 1,
        sqrt(z))*B(2*a - b + 1, sqrt(z))*G(b)*G(2*a - b + 1),
        (sqrt(z)/2)**(-2*a + 1)*B(b, sqrt(z))*B(2*a - b + 1,
        sqrt(z))*G(b)*G(2*a - b + 1), 1, 0, S(1)/2, z/2, -b + 1, -2*a + b,
        -2*a))  # noqa
    c = cse(t)
    assert len(c[0]) == 11
Example #25
0
def test_cse_single():
    # Simple substitution.
    e = Add(Pow(x + y, 2), sqrt(x + y))
    substs, reduced = cse([e])
    assert substs == [(x0, x + y)]
    assert reduced == [sqrt(x0) + x0**2]
Example #26
0
def test_name_conflict():
    z1 = x0 + y
    z2 = x2 + x3
    l_ = [cos(z1) + z1, cos(z2) + z2, x0 + x2]
    substs, reduced = cse(l_)
    assert [e.subs(dict(substs)) for e in reduced] == l_
Example #27
0
def test_nested_substitution():
    # Substitution within a substitution.
    e = Add(Pow(w*x + y, 2), sqrt(w*x + y))
    substs, reduced = cse([e])
    assert substs == [(x0, w*x + y)]
    assert reduced == [sqrt(x0) + x0**2]
Example #28
0
def test_name_conflict_cust_symbols():
    z1 = x0 + y
    z2 = x2 + x3
    l = [cos(z1) + z1, cos(z2) + z2, x0 + x2]
    substs, reduced = cse(l, symbols("x:10"))
    assert [e.subs(dict(substs)) for e in reduced] == l
Example #29
0
def test_symbols_exhausted_error():
    l = cos(x+y)+x+y+cos(w+y)+sin(w+y)
    sym = [x, y, z]
    with pytest.raises(ValueError):
        print(cse(l, symbols=sym))
Example #30
0
def test_name_conflict_cust_symbols():
    z1 = x0 + y
    z2 = x2 + x3
    l_ = [cos(z1) + z1, cos(z2) + z2, x0 + x2]
    substs, reduced = cse(l_, symbols("x:10"))
    assert [e.subs(dict(substs)) for e in reduced] == l_
Example #31
0
def test_name_conflict():
    z1 = x0 + y
    z2 = x2 + x3
    l = [cos(z1) + z1, cos(z2) + z2, x0 + x2]
    substs, reduced = cse(l)
    assert [e.subs(dict(substs)) for e in reduced] == l
Example #32
0
def test_issue_4203():
    assert cse(sin(x**x)/x**x) == ([(x0, x**x)], [sin(x0)/x0])
Example #33
0
def test_symbols_exhausted_error():
    l_ = cos(x+y)+x+y+cos(w+y)+sin(w+y)
    sym = [x, y, z]
    with pytest.raises(ValueError):
        print(cse(l_, symbols=sym))
Example #34
0
def test_cse_single():
    # Simple substitution.
    e = Add(Pow(x + y, 2), sqrt(x + y))
    substs, reduced = cse([e])
    assert substs == [(x0, x + y)]
    assert reduced == [sqrt(x0) + x0**2]
Example #35
0
def test_multiple_expressions():
    e1 = (x + y)*z
    e2 = (x + y)*w
    substs, reduced = cse([e1, e2])
    assert substs == [(x0, x + y)]
    assert reduced == [x0*z, x0*w]
    l_ = [w*x*y + z, w*y]
    substs, reduced = cse(l_)
    rsubsts, _ = cse(reversed(l_))
    assert substs == rsubsts
    assert reduced == [z + x*x0, x0]
    l_ = [w*x*y, w*x*y + z, w*y]
    substs, reduced = cse(l_)
    rsubsts, _ = cse(reversed(l_))
    assert substs == rsubsts
    assert reduced == [x1, x1 + z, x0]
    f = Function("f")
    l_ = [f(x - z, y - z), x - z, y - z]
    substs, reduced = cse(l_)
    rsubsts, _ = cse(reversed(l_))
    assert substs == [(x0, -z), (x1, x + x0), (x2, x0 + y)]
    assert rsubsts == [(x0, -z), (x1, x0 + y), (x2, x + x0)]
    assert reduced == [f(x1, x2), x1, x2]
    l_ = [w*y + w + x + y + z, w*x*y]
    assert cse(l_) == ([(x0, w*y)], [w + x + x0 + y + z, x*x0])
    assert cse([x + y, x + y + z]) == ([(x0, x + y)], [x0, z + x0])
    assert cse([x + y, x + z]) == ([], [x + y, x + z])
    assert cse([x*y, z + x*y, x*y*z + 3]) == \
        ([(x0, x*y)], [x0, z + x0, 3 + x0*z])
Example #36
0
def test_nested_substitution():
    # Substitution within a substitution.
    e = Add(Pow(w*x + y, 2), sqrt(w*x + y))
    substs, reduced = cse([e])
    assert substs == [(x0, w*x + y)]
    assert reduced == [sqrt(x0) + x0**2]
Example #37
0
def test_issue_4203():
    assert cse(sin(x**x)/x**x) == ([(x0, x**x)], [sin(x0)/x0])
Example #38
0
def test_multiple_expressions():
    e1 = (x + y)*z
    e2 = (x + y)*w
    substs, reduced = cse([e1, e2])
    assert substs == [(x0, x + y)]
    assert reduced == [x0*z, x0*w]
    l = [w*x*y + z, w*y]
    substs, reduced = cse(l)
    rsubsts, _ = cse(reversed(l))
    assert substs == rsubsts
    assert reduced == [z + x*x0, x0]
    l = [w*x*y, w*x*y + z, w*y]
    substs, reduced = cse(l)
    rsubsts, _ = cse(reversed(l))
    assert substs == rsubsts
    assert reduced == [x1, x1 + z, x0]
    f = Function("f")
    l = [f(x - z, y - z), x - z, y - z]
    substs, reduced = cse(l)
    rsubsts, _ = cse(reversed(l))
    assert substs == [(x0, -z), (x1, x + x0), (x2, x0 + y)]
    assert rsubsts == [(x0, -z), (x1, x0 + y), (x2, x + x0)]
    assert reduced == [f(x1, x2), x1, x2]
    l = [w*y + w + x + y + z, w*x*y]
    assert cse(l) == ([(x0, w*y)], [w + x + x0 + y + z, x*x0])
    assert cse([x + y, x + y + z]) == ([(x0, x + y)], [x0, z + x0])
    assert cse([x + y, x + z]) == ([], [x + y, x + z])
    assert cse([x*y, z + x*y, x*y*z + 3]) == \
        ([(x0, x*y)], [x0, z + x0, 3 + x0*z])