Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit fa73285

Browse files
committed
17759: convenience class symbolic ExpressionTreeWalker(Converter)
2 parents 86787f2 + 16aa81d commit fa73285

File tree

1 file changed

+93
-36
lines changed

1 file changed

+93
-36
lines changed

src/sage/symbolic/expression_conversions.py

Lines changed: 93 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)