def test_issue_7840(): # daveknippers' example C393 = sympify( \ 'Piecewise((C391 - 1.65, C390 < 0.5), (Piecewise((C391 - 1.65, \ C391 > 2.35), (C392, True)), True))' ) C391 = sympify( \ 'Piecewise((2.05*C390**(-1.03), C390 < 0.5), (2.5*C390**(-0.625), True))' ) C393 = C393.subs('C391', C391) # 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'), true)), Equality(Symbol('mode'), \ Symbol('AUTO'))), (Symbol('OFF'), true)), 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
def test_issue_11230(): # a specific test that always failed a, b, f, k, l, i = symbols('a b f k l i') p = [a * b * f * k * l, a * i * k**2 * l, f * i * k**2 * l] R, C = cse(p) assert not any(i.is_Mul for a in C for i in a.args) # random tests for the issue from sympy.core.random import choice from sympy.core.function import expand_mul s = symbols('a:m') # 35 Mul tests, none of which should ever fail ex = [Mul(*[choice(s) for i in range(5)]) for i in range(7)] for p in subsets(ex, 3): p = list(p) R, C = cse(p) assert not any(i.is_Mul for a in C for i in a.args) for ri in reversed(R): for i in range(len(C)): C[i] = C[i].subs(*ri) assert p == C # 35 Add tests, none of which should ever fail ex = [Add(*[choice(s[:7]) for i in range(5)]) for i in range(7)] for p in subsets(ex, 3): p = list(p) R, C = cse(p) assert not any(i.is_Add for a in C for i in a.args) for ri in reversed(R): for i in range(len(C)): C[i] = C[i].subs(*ri) # use expand_mul to handle cases like this: # p = [a + 2*b + 2*e, 2*b + c + 2*e, b + 2*c + 2*g] # x0 = 2*(b + e) is identified giving a rebuilt p that # is now `[a + 2*(b + e), c + 2*(b + e), b + 2*c + 2*g]` assert p == [expand_mul(i) for i in C]
def genEval(self): text = " bool evaluate(\n" args=[] for name,v in self.variables: if v.is_Matrix: args.append(" const Eigen::MatrixXd & %s" % name) else: args.append(" double %s" % name) args.append(" bool evalF=true,bool evalJ=true") text += ",\n".join(args) + ") {\n" text += " if (evalF) {\n" (interm, expr) = cse(self.function,numbered_symbols("__x")); for dummy,exp in interm: text += " double %s = %s;\n" % (str(dummy),ccode(exp)) for i in range(self.function.rows): text += " F(%d) = %s;\n" % (i,ccode(expr[0][i])) text += " }\n" text += " if (evalJ) {\n" (interm, expr) = cse(self.J,numbered_symbols("__x")); for dummy,exp in interm: text += " double %s = %s;\n" % (str(dummy),ccode(exp)) for i in range(self.J.rows): for j in range(self.J.cols): text += " J(%d,%d) = %s;\n" % (i,j,ccode(expr[0][i,j])) text += " }\n" text += " return true;\n" text += " }\n" return text
def test_cse_ignore(): exprs = [exp(y)*(3*y + 3*sqrt(x+1)), exp(y)*(5*y + 5*sqrt(x+1))] subst1, red1 = cse(exprs) assert any(y in sub.free_symbols for _, sub in subst1), "cse failed to identify any term with y" subst2, red2 = cse(exprs, ignore=(y,)) # y is not allowed in substitutions assert not any(y in sub.free_symbols for _, sub in subst2), "Sub-expressions containing y must be ignored" assert any(sub - sqrt(x + 1) == 0 for _, sub in subst2), "cse failed to identify sqrt(x + 1) as sub-expression"
def test_cse_MatrixSymbol(): # MatrixSymbols have non-Basic args, so make sure that works A = MatrixSymbol("A", 3, 3) assert cse(A) == ([], [A]) n = symbols('n', integer=True) B = MatrixSymbol("B", n, n) assert cse(B) == ([], [B])
def test_bypass_non_commutatives(): A, B, C = symbols('A B C', commutative=False) l = [A * B * C, A * C] assert cse(l) == ([], l) l = [A * B * C, A * B] assert cse(l) == ([], l) l = [B * C, A * B * C] assert cse(l) == ([], l)
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])
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] subst42, (red42, ) = cse([42]) # issue_15082 assert len(subst42) == 0 and red42 == 42 subst_half, (red_half, ) = cse([0.5]) assert len(subst_half) == 0 and red_half == 0.5
def test_issue_10228(): assert cse([x * y**2 + x * y]) == ([(x0, x * y)], [x0 * y + x0]) assert cse([x + y, 2 * x + y]) == ([(x0, x + y)], [x0, x + x0]) assert cse((w + 2 * x + y + z, w + x + 1)) == ([(x0, w + x)], [x0 + x + y + z, x0 + 1]) assert cse(((w + x + y + z) * (w - x)) / (w + x)) == ([(x0, w + x)], [ (x0 + y + z) * (w - x) / x0 ]) a, b, c, d, f, g, j, m = symbols('a, b, c, d, f, g, j, m') exprs = (d * g**2 * j * m, 4 * a * f * g * m, a * b * c * f**2) assert cse(exprs) == ([(x0, g * m), (x1, a * f)], [d * g * j * x0, 4 * x0 * x1, b * c * f * x1])
def test_cse_single2(): # Simple substitution, test for being able to pass the expression directly e = Add(Pow(x + y, 2), sqrt(x + y)) substs, reduced = cse(e) assert substs == [(x0, x + y)] assert reduced == [sqrt(x0) + x0**2] substs, reduced = cse(Matrix([[1]])) assert isinstance(reduced[0], Matrix) subst42, (red42, ) = cse(42) # issue 15082 assert len(subst42) == 0 and red42 == 42 subst_half, (red_half, ) = cse(0.5) # issue 15082 assert len(subst_half) == 0 and red_half == 0.5
def test_cse_MatrixSymbol(): # MatrixSymbols have non-Basic args, so make sure that works A = MatrixSymbol("A", 3, 3) assert cse(A) == ([], [A]) n = symbols('n', integer=True) B = MatrixSymbol("B", n, n) assert cse(B) == ([], [B]) assert cse(A[0] * A[0]) == ([], [A[0] * A[0]]) assert cse(A[0, 0] * A[0, 1] + A[0, 0] * A[0, 1] * A[0, 2]) == ([ (x0, A[0, 0] * A[0, 1]) ], [x0 * A[0, 2] + x0])
def test_cse_MatrixExpr(): A = MatrixSymbol('A', 3, 3) y = MatrixSymbol('y', 3, 1) expr1 = (A.T * A).I * A * y expr2 = (A.T * A) * A * y replacements, reduced_exprs = cse([expr1, expr2]) assert len(replacements) > 0 replacements, reduced_exprs = cse([expr1 + expr2, expr1]) assert replacements replacements, reduced_exprs = cse([A**2, A + A**2]) assert replacements
def test_derivative_subs(): f = Function('f') g = Function('g') assert Derivative(f(x), x).subs(f(x), y) != 0 # need xreplace to put the function back, see #13803 assert Derivative(f(x), x).subs(f(x), y).xreplace({y: f(x)}) == \ Derivative(f(x), x) # issues 5085, 5037 assert cse(Derivative(f(x), x) + f(x))[1][0].has(Derivative) assert cse(Derivative(f(x, y), x) + Derivative(f(x, y), y))[1][0].has(Derivative) eq = Derivative(g(x), g(x)) assert eq.subs(g, f) == Derivative(f(x), f(x)) assert eq.subs(g(x), f(x)) == Derivative(f(x), f(x)) assert eq.subs(g, cos) == Subs(Derivative(y, y), y, cos(x))
def trigsimp(expr, deep=False, recursive=False): """ Usage ===== trigsimp(expr) -> reduces expression by using known trig identities Notes ===== deep ........ apply trigsimp inside functions recursive ... use common subexpression elimination (cse()) and apply trigsimp recursively (recursively==True is quite expensive operation if the expression is large) Examples ======== >>> from sympy import * >>> x = Symbol('x') >>> y = Symbol('y') >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e) 2 >>> trigsimp(log(e)) log(2*cos(x)**2 + 2*sin(x)**2) >>> trigsimp(log(e), deep=True) log(2) """ from sympy.core.basic import S sin, cos, tan, cot = C.sin, C.cos, C.tan, C.cot if recursive: w, g = cse(expr) g = trigsimp_nonrecursive(g[0]) for sub in reversed(w): g = g.subs(sub[0], sub[1]) g = trigsimp_nonrecursive(g) result = g else: result = trigsimp_nonrecursive(expr, deep) # do some final simplifications like sin/cos -> tan: a,b,c = map(Wild, 'abc') matchers = ( (a*sin(b)**c/cos(b)**c, a*tan(b)**c), ) for pattern, simp in matchers: res = result.match(pattern) if res is not None: # if c is missing or zero, do nothing: if (not c in res) or res[c] == 0: continue # if "a" contains the argument of sin/cos "b", skip the # simplification: if res[a].has(res[b]): continue # simplify and finish: result = simp.subs(res) break return result
def test_issue_8891(): for cls in (MutableDenseMatrix, MutableSparseMatrix, ImmutableDenseMatrix, ImmutableSparseMatrix): m = cls(2, 2, [x + y, 0, 0, 0]) res = cse([x + y, m]) ans = ([(x0, x + y)], [x0, cls([[x0, 0], [0, 0]])]) assert res == ans assert isinstance(res[1][-1], cls)
def test_cse_ignore_issue_15002(): l = [ w*exp(x)*exp(-z), exp(y)*exp(x)*exp(-z) ] substs, reduced = cse(l, ignore=(x,)) rl = [e.subs(reversed(substs)) for e in reduced] assert rl == l
def test_dont_cse_tuples(): from sympy.core.function import Subs f = Function("f") g = Function("g") name_val, (expr, ) = cse( Subs(f(x, y), (x, y), (0, 1)) + Subs(g(x, y), (x, y), (0, 1))) assert name_val == [] assert expr == (Subs(f(x, y), (x, y), (0, 1)) + Subs(g(x, y), (x, y), (0, 1))) name_val, (expr, ) = cse( Subs(f(x, y), (x, y), (0, x + y)) + Subs(g(x, y), (x, y), (0, x + y))) assert name_val == [(x0, x + y)] assert expr == Subs(f(x, y), (x, y), (0, x0)) + \ Subs(g(x, y), (x, y), (0, x0))
def test_issue_11577(): def check(eq): r, c = cse(eq) assert eq.count_ops() >= \ len(r) + sum([i[1].count_ops() for i in r]) + \ count_ops(c) eq = x**5 * y**2 + x**5 * y + x**5 assert cse(eq) == ([(x0, x**4), (x1, x * y)], [x**5 + x0 * x1 * y + x0 * x1]) # ([(x0, x**5*y)], [x0*y + x0 + x**5]) or # ([(x0, x**5)], [x0*y**2 + x0*y + x0]) check(eq) eq = x**2 / (y + 1)**2 + x / (y + 1) assert cse(eq) == ([(x0, y + 1)], [x**2 / x0**2 + x / x0]) # ([(x0, x/(y + 1))], [x0**2 + x0]) check(eq)
def trigsimp(expr, deep=False, recursive=False): """ == Usage == trigsimp(expr) -> reduces expression by using known trig identities == Notes == deep: - Apply trigsimp inside functions recursive: - Use common subexpression elimination (cse()) and apply trigsimp recursively (recursively==True is quite expensive operation if the expression is large) == Examples == >>> from sympy import * >>> x = Symbol('x') >>> y = Symbol('y') >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e) 2 >>> trigsimp(log(e)) log(2*cos(x)**2 + 2*sin(x)**2) >>> trigsimp(log(e), deep=True) log(2) """ from sympy.core.basic import S sin, cos, tan, cot = C.sin, C.cos, C.tan, C.cot if recursive: w, g = cse(expr) g = trigsimp_nonrecursive(g[0]) for sub in reversed(w): g = g.subs(sub[0], sub[1]) g = trigsimp_nonrecursive(g) result = g else: result = trigsimp_nonrecursive(expr, deep) # do some final simplifications like sin/cos -> tan: a, b, c = map(Wild, 'abc') matchers = ((a * sin(b)**c / cos(b)**c, a * tan(b)**c), ) for pattern, simp in matchers: res = result.match(pattern) if res is not None: # if c is missing or zero, do nothing: if (not c in res) or res[c] == 0: continue # if "a" contains the argument of sin/cos "b", skip the # simplification: if res[a].has(res[b]): continue # simplify and finish: result = simp.subs(res) break return result
def cse(self, symbols=None, optimizations=None, postprocess=None, order='canonical'): """ Return a new code block with common subexpressions eliminated See the docstring of :func:`sympy.simplify.cse_main.cse` for more information. Examples ======== >>> from sympy import symbols, sin >>> from sympy.codegen.ast import CodeBlock, Assignment >>> x, y, z = symbols('x y z') >>> c = CodeBlock( ... Assignment(x, 1), ... Assignment(y, sin(x) + 1), ... Assignment(z, sin(x) - 1), ... ) ... >>> c.cse() CodeBlock(Assignment(x, 1), Assignment(x0, sin(x)), Assignment(y, x0 + 1), Assignment(z, x0 - 1)) """ # TODO: Check that the symbols are new from sympy.simplify.cse_main import cse if not all(isinstance(i, Assignment) for i in self.args): # Will support more things later raise NotImplementedError( "CodeBlock.cse only supports Assignments") if any(isinstance(i, AugmentedAssignment) for i in self.args): raise NotImplementedError( "CodeBlock.cse doesn't yet work with AugmentedAssignments") for i, lhs in enumerate(self.left_hand_sides): if lhs in self.left_hand_sides[:i]: raise NotImplementedError( "Duplicate assignments to the same " "variable are not yet supported (%s)" % lhs) replacements, reduced_exprs = cse(self.right_hand_sides, symbols=symbols, optimizations=optimizations, postprocess=postprocess, order=order) assert len(reduced_exprs) == 1 new_block = tuple( Assignment(var, expr) for var, expr in zip(self.left_hand_sides, reduced_exprs[0])) new_assignments = tuple(Assignment(*i) for i in replacements) return self.topological_sort(new_assignments + new_block)
def test_cse_Indexed(): len_y = 5 y = IndexedBase('y', shape=(len_y, )) x = IndexedBase('x', shape=(len_y, )) 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
def test_issue_6559(): assert (-12 * x + y).subs(-x, 1) == 12 + y # though this involves cse it generated a failure in Mul._eval_subs x0, x1 = symbols('x0 x1') e = -log(-12 * sqrt(2) + 17) / 24 - log(-2 * sqrt(2) + 3) / 12 + sqrt(2) / 3 # XXX modify cse so x1 is eliminated and x0 = -sqrt(2)? assert cse(e) == ([ (x0, sqrt(2)) ], [x0 / 3 - log(-12 * x0 + 17) / 24 - log(-2 * x0 + 3) / 12])
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]) assert cse(((w + x + y + z)*(w - y - z))/(w + x)**3) == \ ([(x0, w + x), (x1, y + z)], [(w - x1)*(x0 + x1)/x0**3])
def test_cse_list(): _cse = lambda x: cse(x, list=False) assert _cse(x) == ([], x) assert _cse('x') == ([], 'x') it = [x] for c in (list, tuple, set): assert _cse(c(it)) == ([], c(it)) #Tuple works different from tuple: assert _cse(Tuple(*it)) == ([], Tuple(*it)) d = {x: 1} assert _cse(d) == ([], d)
def test_cse__performance(): nexprs, nterms = 3, 20 x = symbols('x:%d' % nterms) exprs = [ reduce(add, [x[j] * (-1)**(i + j) for j in range(nterms)]) for i in range(nexprs) ] assert (exprs[0] + exprs[1]).simplify() == 0 subst, red = cse(exprs) assert len(subst) > 0, "exprs[0] == -exprs[2], i.e. a CSE" for i, e in enumerate(red): assert (e.subs(reversed(subst)) - exprs[i]).simplify() == 0
def Main(): #Read("spec.in") #Read("spec_warp_simpler.in") #Read("spec_warpPerspective.in") Read("spec_rotate.in") if False: [(c_name, c_code), (h_name, c_header)] = codegen([("xdst", eqList[0]), ("ydst", eqList[1])], "C", "test", header=False, empty=False) print("c_code = %s" % c_code) print("eqList = %s" % str(eqList)) resEqSysMat = eqs2matrix(eqs=eqList, unknownSymbols=(xdst, ydst), augment=True) print("resEqSysMat = %s" % str(resEqSysMat)) from sympy import Matrix, solve_linear_system res = solve_linear_system(resEqSysMat, xdst, ydst) print("The result is (xdst, ydst) = %s" % str(res)) print("res[xdst] = %s" % str(res[xdst])) print("res[ydst] = %s" % str(res[ydst])) #sympy.simplify.cse_main.cse(res[xdst], res[ydst]) expListWithBoundedVars = cse([res[xdst], res[ydst]]) print("After performing CSE, we have: %s" % str(expListWithBoundedVars)) print("expListWithBoundedVars[0] (the bounded vars) = %s" % str(expListWithBoundedVars[0])) print("expListWithBoundedVars[1][0] = %s" % str(expListWithBoundedVars[1][0])) eFinal = [] for e in expListWithBoundedVars[0]: eFinal.append((str(e[0]), e[1])) #expListWithBoundedVars[0] + \ expListWithBoundedVars = eFinal + \ [("xdst", expListWithBoundedVars[1][0])] + \ [("ydst", expListWithBoundedVars[1][1])] print("expListWithBoundedVars = %s" % str(expListWithBoundedVars)) [(c_name, c_code), (h_name, c_header)] = codegen(expListWithBoundedVars, "C", "final_test", header=False, empty=False) print("c_code = %s" % c_code)
def test_cse_release_variables(): from sympy.simplify.cse_main import cse_release_variables _0, _1, _2, _3, _4 = symbols('_:5') eqs = [(x + y - 1)**2, x, x + y, (x + y) / (2 * x + 1) + (x + y - 1)**2, (2 * x + 1)**(x + y)] r, e = cse(eqs, postprocess=cse_release_variables) # this can change in keeping with the intention of the function assert r, e == ([(x0, x + y), (x1, (x0 - 1)**2), (x2, 2 * x + 1), (_3, x0 / x2 + x1), (_4, x2**x0), (x2, None), (_0, x1), (x1, None), (_2, x0), (x0, None), (_1, x)], (_0, _1, _2, _3, _4)) r.reverse() assert eqs == [i.subs(r) for i in e]
def genEval(self): text = " bool evaluate(\n" args=[] for name,v,lD in self.variables: if isinstance(v, Matrix): args.append(" const Eigen::Matrix<double, %d, 1> & %s" % (v.rows, name)) else: args.append(" double %s" % name) args.append(" Eigen::Matrix<double, %d, 1> * F" % self.function.rows) for name,v,localDim in self.variables: if isinstance(v, Matrix): args.append(" Eigen::Matrix<double, %d, %d> * J%s" % (self.J.rows, localDim, name)) else: args.append(" Eigen::Matrix<double, %d, 1> * J%s" % (self.J.rows, name)) text += ",\n".join(args) + ") {\n" text += " if (F) {\n" (interm, expr) = cse(self.function,numbered_symbols("__x")); for dummy,exp in interm: text += " double %s = %s;\n" % (str(dummy),ccode(exp)) for i in range(self.function.rows): text += " (*F)(%d) = %s;\n" % (i,ccode(expr[0][i])) text += " }\n" text += " if (%s) {\n" % " && ".join([ "J" + name for name,v,lD in self.variables ]) (interm, expr) = cse(self.J,numbered_symbols("__x")); for dummy,exp in interm: text += " double %s = %s;\n" % (str(dummy),ccode(exp)) colBase = 0; for name,v,localDim in self.variables: for i in range(self.J.rows): for j in range(0, localDim): text += " (*J%s)(%d,%d) = %s;\n" % (name, i,j,ccode(expr[0][i,colBase + j])) colBase+=localDim text += " }\n" text += " return true;\n" text += " }\n" return text
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])
def build_cse_fn(symname, symfunc, symbolslist): tmpsyms = numbered_symbols("R") symbols, simple = cse(symfunc, symbols=tmpsyms) code = "double %s(%s)\n" % (str(symname), ", ".join( "double const& %s" % x for x in symbolslist)) code += "{\n" for s in symbols: code += " double %s = %s;\n" % (ccode(s[0]), ccode(s[1])) code += " double result = %s;\n" % ccode(simple[0]) code += " return result;\n" code += "}\n" return code
def cse(self, symbols=None, optimizations=None, postprocess=None, order='canonical'): """ Return a new code block with common subexpressions eliminated See the docstring of :func:`sympy.simplify.cse_main.cse` for more information. Examples ======== >>> from sympy import symbols, sin >>> from sympy.codegen.ast import CodeBlock, Assignment >>> x, y, z = symbols('x y z') >>> c = CodeBlock( ... Assignment(x, 1), ... Assignment(y, sin(x) + 1), ... Assignment(z, sin(x) - 1), ... ) ... >>> c.cse() CodeBlock(Assignment(x, 1), Assignment(x0, sin(x)), Assignment(y, x0 + 1), Assignment(z, x0 - 1)) """ # TODO: Check that the symbols are new from sympy.simplify.cse_main import cse if not all(isinstance(i, Assignment) for i in self.args): # Will support more things later raise NotImplementedError("CodeBlock.cse only supports Assignments") if any(isinstance(i, AugmentedAssignment) for i in self.args): raise NotImplementedError("CodeBlock.cse doesn't yet work with AugmentedAssignments") for i, lhs in enumerate(self.left_hand_sides): if lhs in self.left_hand_sides[:i]: raise NotImplementedError("Duplicate assignments to the same " "variable are not yet supported (%s)" % lhs) replacements, reduced_exprs = cse(self.right_hand_sides, symbols=symbols, optimizations=optimizations, postprocess=postprocess, order=order) assert len(reduced_exprs) == 1 new_block = tuple(Assignment(var, expr) for var, expr in zip(self.left_hand_sides, reduced_exprs[0])) new_assignments = tuple(Assignment(*i) for i in replacements) return self.topological_sort(new_assignments + new_block)
def Main(): #Read("spec.in") #Read("spec_warp_simpler.in") #Read("spec_warpPerspective.in") Read("spec_rotate.in") if False: [(c_name, c_code), (h_name, c_header)] = codegen( [("xdst", eqList[0]), ("ydst", eqList[1])], "C", "test", header=False, empty=False) print("c_code = %s" % c_code) print("eqList = %s" % str(eqList)) resEqSysMat = eqs2matrix(eqs=eqList, unknownSymbols=(xdst, ydst), augment=True) print("resEqSysMat = %s" % str(resEqSysMat)) from sympy import Matrix, solve_linear_system res = solve_linear_system(resEqSysMat, xdst, ydst) print("The result is (xdst, ydst) = %s" % str(res)) print("res[xdst] = %s" % str(res[xdst])) print("res[ydst] = %s" % str(res[ydst])) #sympy.simplify.cse_main.cse(res[xdst], res[ydst]) expListWithBoundedVars = cse([res[xdst], res[ydst]]) print("After performing CSE, we have: %s" % str(expListWithBoundedVars)) print("expListWithBoundedVars[0] (the bounded vars) = %s" % str(expListWithBoundedVars[0])) print("expListWithBoundedVars[1][0] = %s" % str(expListWithBoundedVars[1][0])) eFinal = [] for e in expListWithBoundedVars[0]: eFinal.append( (str(e[0]), e[1]) ) #expListWithBoundedVars[0] + \ expListWithBoundedVars = eFinal + \ [("xdst", expListWithBoundedVars[1][0])] + \ [("ydst", expListWithBoundedVars[1][1])] print("expListWithBoundedVars = %s" % str(expListWithBoundedVars)) [(c_name, c_code), (h_name, c_header)] = codegen( expListWithBoundedVars, "C", "final_test", header=False, empty=False) print("c_code = %s" % c_code)
def test_issue_4499(): # previously, this gave 16 constants from sympy.abc import a, b B = Function('B') G = Function('G') t = Tuple(* (a, a + S.Half, 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.Half, z/2, -b + 1, -2*a + b, -2*a)) c = cse(t) ans = ( [(x0, 2*a), (x1, -b + x0), (x2, x1 + 1), (x3, b - 1), (x4, sqrt(z)), (x5, B(x3, x4)), (x6, (x4/2)**(1 - x0)*G(b)*G(x2)), (x7, x6*B(x1, x4)), (x8, B(b, x4)), (x9, x6*B(x2, x4))], [(a, a + S.Half, x0, b, x2, x5*x7, x4*x7*x8, x4*x5*x9, x8*x9, 1, 0, S.Half, z/2, -x3, -x1, -x0)]) assert ans == c
def trigsimp_old(expr, **opts): """ reduces expression by using known trig identities Notes ===== deep: - Apply trigsimp inside all objects with arguments recursive: - Use common subexpression elimination (cse()) and apply trigsimp recursively (this is quite expensive if the expression is large) method: - Determine the method to use. Valid choices are 'matching' (default), 'groebner', 'combined', 'fu' and 'futrig'. If 'matching', simplify the expression recursively by pattern matching. If 'groebner', apply an experimental groebner basis algorithm. In this case further options are forwarded to ``trigsimp_groebner``, please refer to its docstring. If 'combined', first run the groebner basis algorithm with small default parameters, then run the 'matching' algorithm. 'fu' runs the collection of trigonometric transformations described by Fu, et al. (see the `fu` docstring) while `futrig` runs a subset of Fu-transforms that mimic the behavior of `trigsimp`. compare: - show input and output from `trigsimp` and `futrig` when different, but returns the `trigsimp` value. Examples ======== >>> from sympy import trigsimp, sin, cos, log, cosh, sinh, tan, cot >>> from sympy.abc import x, y >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e, old=True) 2 >>> trigsimp(log(e), old=True) log(2*sin(x)**2 + 2*cos(x)**2) >>> trigsimp(log(e), deep=True, old=True) log(2) Using `method="groebner"` (or `"combined"`) can sometimes lead to a lot more simplification: >>> e = (-sin(x) + 1)/cos(x) + cos(x)/(-sin(x) + 1) >>> trigsimp(e, old=True) (1 - sin(x))/cos(x) + cos(x)/(1 - sin(x)) >>> trigsimp(e, method="groebner", old=True) 2/cos(x) >>> trigsimp(1/cot(x)**2, compare=True, old=True) futrig: tan(x)**2 cot(x)**(-2) """ old = expr first = opts.pop('first', True) if first: if not expr.has(*_trigs): return expr trigsyms = set().union(*[t.free_symbols for t in expr.atoms(*_trigs)]) if len(trigsyms) > 1: from sympy.simplify.simplify import separatevars d = separatevars(expr) if d.is_Mul: d = separatevars(d, dict=True) or d if isinstance(d, dict): expr = 1 for k, v in d.items(): # remove hollow factoring was = v v = expand_mul(v) opts['first'] = False vnew = trigsimp(v, **opts) if vnew == v: vnew = was expr *= vnew old = expr else: if d.is_Add: for s in trigsyms: r, e = expr.as_independent(s) if r: opts['first'] = False expr = r + trigsimp(e, **opts) if not expr.is_Add: break old = expr recursive = opts.pop('recursive', False) deep = opts.pop('deep', False) method = opts.pop('method', 'matching') def groebnersimp(ex, deep, **opts): def traverse(e): if e.is_Atom: return e args = [traverse(x) for x in e.args] if e.is_Function or e.is_Pow: args = [trigsimp_groebner(x, **opts) for x in args] return e.func(*args) if deep: ex = traverse(ex) return trigsimp_groebner(ex, **opts) trigsimpfunc = { 'matching': (lambda x, d: _trigsimp(x, d)), 'groebner': (lambda x, d: groebnersimp(x, d, **opts)), 'combined': (lambda x, d: _trigsimp(groebnersimp(x, d, polynomial=True, hints=[2, tan]), d)) }[method] if recursive: w, g = cse(expr) g = trigsimpfunc(g[0], deep) for sub in reversed(w): g = g.subs(sub[0], sub[1]) g = trigsimpfunc(g, deep) result = g else: result = trigsimpfunc(expr, deep) if opts.get('compare', False): f = futrig(old) if f != result: print('\tfutrig:', f) return result
def trigsimp_old(expr, **opts): """ reduces expression by using known trig identities Notes ===== deep: - Apply trigsimp inside all objects with arguments recursive: - Use common subexpression elimination (cse()) and apply trigsimp recursively (this is quite expensive if the expression is large) method: - Determine the method to use. Valid choices are 'matching' (default), 'groebner', 'combined', 'fu' and 'futrig'. If 'matching', simplify the expression recursively by pattern matching. If 'groebner', apply an experimental groebner basis algorithm. In this case further options are forwarded to ``trigsimp_groebner``, please refer to its docstring. If 'combined', first run the groebner basis algorithm with small default parameters, then run the 'matching' algorithm. 'fu' runs the collection of trigonometric transformations described by Fu, et al. (see the `fu` docstring) while `futrig` runs a subset of Fu-transforms that mimic the behavior of `trigsimp`. compare: - show input and output from `trigsimp` and `futrig` when different, but returns the `trigsimp` value. Examples ======== >>> from sympy import trigsimp, sin, cos, log, cosh, sinh, tan, cot >>> from sympy.abc import x, y >>> e = 2*sin(x)**2 + 2*cos(x)**2 >>> trigsimp(e, old=True) 2 >>> trigsimp(log(e), old=True) log(2*sin(x)**2 + 2*cos(x)**2) >>> trigsimp(log(e), deep=True, old=True) log(2) Using `method="groebner"` (or `"combined"`) can sometimes lead to a lot more simplification: >>> e = (-sin(x) + 1)/cos(x) + cos(x)/(-sin(x) + 1) >>> trigsimp(e, old=True) (1 - sin(x))/cos(x) + cos(x)/(1 - sin(x)) >>> trigsimp(e, method="groebner", old=True) 2/cos(x) >>> trigsimp(1/cot(x)**2, compare=True, old=True) futrig: tan(x)**2 cot(x)**(-2) """ old = expr first = opts.pop('first', True) if first: if not expr.has(*_trigs): return expr trigsyms = set().union(*[t.free_symbols for t in expr.atoms(*_trigs)]) if len(trigsyms) > 1: from sympy.simplify.simplify import separatevars d = separatevars(expr) if d.is_Mul: d = separatevars(d, dict=True) or d if isinstance(d, dict): expr = 1 for k, v in d.items(): # remove hollow factoring was = v v = expand_mul(v) opts['first'] = False vnew = trigsimp(v, **opts) if vnew == v: vnew = was expr *= vnew old = expr else: if d.is_Add: for s in trigsyms: r, e = expr.as_independent(s) if r: opts['first'] = False expr = r + trigsimp(e, **opts) if not expr.is_Add: break old = expr recursive = opts.pop('recursive', False) deep = opts.pop('deep', False) method = opts.pop('method', 'matching') def groebnersimp(ex, deep, **opts): def traverse(e): if e.is_Atom: return e args = [traverse(x) for x in e.args] if e.is_Function or e.is_Pow: args = [trigsimp_groebner(x, **opts) for x in args] return e.func(*args) if deep: ex = traverse(ex) return trigsimp_groebner(ex, **opts) trigsimpfunc = { 'matching': (lambda x, d: _trigsimp(x, d)), 'groebner': (lambda x, d: groebnersimp(x, d, **opts)), 'combined': (lambda x, d: _trigsimp( groebnersimp(x, d, polynomial=True, hints=[2, tan]), d)) }[method] if recursive: w, g = cse(expr) g = trigsimpfunc(g[0], deep) for sub in reversed(w): g = g.subs(sub[0], sub[1]) g = trigsimpfunc(g, deep) result = g else: result = trigsimpfunc(expr, deep) if opts.get('compare', False): f = futrig(old) if f != result: print('\tfutrig:', f) return result
def cse_print(expr): cses, simple_expr = cse(expr) print print sympy.pretty(simple_expr) pp(cses) print