@@ -1672,80 +1672,136 @@ def composition(self, ex, operator):
16721672 else :
16731673 return res
16741674
1675- class SubstituteFunction (Converter ):
1676- def __init__ (self , ex , original , new ):
1675+
1676+ class ExpressionTreeWalker (Converter ):
1677+ def __init__ (self , ex ):
16771678 """
1678- A class that walks the tree and replaces occurrences of a
1679- function with another.
1679+ A class that walks the tree. Mainly for subclassing.
16801680
16811681 EXAMPLES::
16821682
1683- sage: from sage.symbolic.expression_conversions import SubstituteFunction
1684- sage: foo = function('foo'); bar = function('bar')
1685- sage: s = SubstituteFunction(foo(x), foo, bar)
1686- sage: s(1/foo(foo(x)) + foo(2))
1687- 1/bar(bar(x)) + bar(2)
1683+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1684+ sage: from sage.symbolic.random_tests import random_expr
1685+ sage: ex = sin(atan(0,hold=True)+hypergeometric((1,),(1,),x))
1686+ sage: s = ExpressionTreeWalker(ex)
1687+ sage: bool(s() == ex)
1688+ True
1689+ sage: foo = random_expr(20, nvars=2)
1690+ sage: s = ExpressionTreeWalker(foo)
1691+ sage: bool(s() == foo)
1692+ True
16881693 """
1689- self .original = original
1690- self .new = new
16911694 self .ex = ex
16921695
16931696 def symbol (self , ex ):
16941697 """
16951698 EXAMPLES::
16961699
1697- sage: from sage.symbolic.expression_conversions import SubstituteFunction
1698- sage: foo = function('foo'); bar = function('bar')
1699- sage: s = SubstituteFunction(foo(x), foo, bar)
1700- sage: s.symbol(x)
1701- x
1700+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1701+ sage: s = ExpressionTreeWalker(x)
1702+ sage: bool(s.symbol(x) == x)
1703+ True
17021704 """
17031705 return ex
17041706
17051707 def pyobject (self , ex , obj ):
17061708 """
17071709 EXAMPLES::
17081710
1709- sage: from sage.symbolic.expression_conversions import SubstituteFunction
1710- sage: foo = function('foo'); bar = function('bar')
1711- sage: s = SubstituteFunction(foo(x), foo, bar)
1711+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
17121712 sage: f = SR(2)
1713- sage: s.pyobject(f, f.pyobject())
1714- 2
1715- sage: _.parent()
1716- Symbolic Ring
1713+ sage: s = ExpressionTreeWalker(f)
1714+ sage: bool(s.pyobject(f, f.pyobject()) == f.pyobject())
1715+ True
17171716 """
17181717 return ex
17191718
17201719 def relation (self , ex , operator ):
17211720 """
17221721 EXAMPLES::
17231722
1724- sage: from sage.symbolic.expression_conversions import SubstituteFunction
1725- sage: foo = function('foo'); bar = function('bar')
1726- sage: s = SubstituteFunction(foo(x), foo, bar)
1723+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1724+ sage: foo = function('foo')
17271725 sage: eq = foo(x) == x
1728- sage: s.relation(eq, eq.operator())
1729- bar(x) == x
1726+ sage: s = ExpressionTreeWalker(eq)
1727+ sage: s.relation(eq, eq.operator()) == eq
1728+ True
17301729 """
17311730 return operator (self (ex .lhs ()), self (ex .rhs ()))
17321731
17331732 def arithmetic (self , ex , operator ):
17341733 """
1734+ EXAMPLES::
1735+
1736+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1737+ sage: foo = function('foo')
1738+ sage: f = x*foo(x) + pi/foo(x)
1739+ sage: s = ExpressionTreeWalker(f)
1740+ sage: bool(s.arithmetic(f, f.operator()) == f)
1741+ True
1742+ """
1743+ return reduce (operator , map (self , ex .operands ()))
1744+
1745+ def composition (self , ex , operator ):
1746+ """
1747+ EXAMPLES::
1748+
1749+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1750+ sage: foo = function('foo')
1751+ sage: f = foo(atan2(0, 0, hold=True))
1752+ sage: s = ExpressionTreeWalker(f)
1753+ sage: bool(s.composition(f, f.operator()) == f)
1754+ True
1755+ """
1756+ from sage .symbolic .function import Function
1757+ if isinstance (operator , Function ):
1758+ return operator (* map (self , ex .operands ()), hold = True )
1759+ else :
1760+ return operator (* map (self , ex .operands ()))
1761+
1762+ def derivative (self , ex , operator ):
1763+ """
1764+ EXAMPLES::
1765+
1766+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1767+ sage: foo = function('foo')
1768+ sage: f = foo(x).diff(x)
1769+ sage: s = ExpressionTreeWalker(f)
1770+ sage: bool(s.derivative(f, f.operator()) == f)
1771+ True
1772+ """
1773+ return operator (* map (self , ex .operands ()))
1774+
1775+ def tuple (self , ex ):
1776+ """
1777+ EXAMPLES::
1778+
1779+ sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
1780+ sage: foo = function('foo')
1781+ sage: f = hypergeometric((1,2,3,),(x,),x)
1782+ sage: s = ExpressionTreeWalker(f)
1783+ sage: bool(s() == f)
1784+ True
1785+ """
1786+ return ex .operands ()
1787+
1788+ class SubstituteFunction (ExpressionTreeWalker ):
1789+ def __init__ (self , ex , original , new ):
1790+ """
1791+ A class that walks the tree and replaces occurrences of a
1792+ function with another.
1793+
17351794 EXAMPLES::
17361795
17371796 sage: from sage.symbolic.expression_conversions import SubstituteFunction
17381797 sage: foo = function('foo'); bar = function('bar')
17391798 sage: s = SubstituteFunction(foo(x), foo, bar)
1740- sage: f = x*foo(x) + pi/foo(x)
1741- sage: s.arithmetic(f, f.operator())
1742- x*bar(x) + pi/bar(x)
1799+ sage: s(1/foo(foo(x)) + foo(2))
1800+ 1/bar(bar(x)) + bar(2)
17431801 """
1744- if operator == add_vararg :
1745- operator = _operator .add
1746- elif operator == mul_vararg :
1747- operator = _operator .mul
1748- return reduce (operator , map (self , ex .operands ()))
1802+ self .original = original
1803+ self .new = new
1804+ self .ex = ex
17491805
17501806 def composition (self , ex , operator ):
17511807 """
@@ -1798,3 +1854,4 @@ def derivative(self, ex, operator):
17981854 return operator .change_function (self .new )(* map (self ,ex .operands ()))
17991855 else :
18001856 return operator (* map (self , ex .operands ()))
1857+
0 commit comments