1 | initial version |
To every expression one can associate a syntactic tree.
The function you have in mind seems to be counting the size
of that tree; not only the leaves but all the tree's vertices.
With that in mind, I would not call it LeafCount
.
Sage may have the function you need; I know it has
an ExpressionTreeWalker
.
Anyway, let us write a small tree_size
function.
It gives the tree size of a symbolic expression, as well as of a list, tuple, or vector of symbolic expressions.
def tree_size(expr):
try:
x, aa = expr.operator(), expr.operands()
except AttributeError:
return 1 + sum(tree_size(a) for a in expr)
if x is None:
return 1
else:
return 1 + sum(tree_size(a) for a in aa)
Here is a companion function for the string length:
def string_size(expr):
return len(str(expr))
Let us define a list of the test cases in the question.
a, b, x = SR.var('a, b, x')
ee = [
x,
1/2*(log(b*x + a) - log(b*x - a))/(a*b),
arctan(b*x/a)/(a*b),
-1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x))),
[-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)],
]
and run the function on them:
sage: print('\n'.join(f'* {e}\n {tree_size(e)}, {string_size(e)}' for e in ee))
* x
1, 1
* 1/2*(log(b*x + a) - log(b*x - a))/(a*b)
25, 39
* arctan(b*x/a)/(a*b)
14, 19
* -1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x)))
31, 75
* [-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)]
68, 117
Perfect match with the desired values!
2 | No.2 Revision |
To every expression one can associate a syntactic tree.
The function you have in mind seems to be counting the size
of that tree; not only the leaves but all the tree's vertices.
With that in mind, I would not call it LeafCount
.
Sage may have the function you need; I know or it has
an may be
easy to define using Sage's ExpressionTreeWalker
.
and "map reduce".
Anyway, let us write a small tree_size
function.
It gives the tree size of a symbolic expression, as well as of a list, tuple, or vector of symbolic expressions.
def tree_size(expr):
try:
x, aa = expr.operator(), expr.operands()
except AttributeError:
return 1 + sum(tree_size(a) for a in expr)
if x is None:
return 1
else:
return 1 + sum(tree_size(a) for a in aa)
Here is a companion function for the string length:
def string_size(expr):
return len(str(expr))
Let us define a list of the test cases in the question.
a, b, x = SR.var('a, b, x')
ee = [
x,
1/2*(log(b*x + a) - log(b*x - a))/(a*b),
arctan(b*x/a)/(a*b),
-1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x))),
[-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)],
]
and run the function on them:
sage: print('\n'.join(f'* {e}\n {tree_size(e)}, {string_size(e)}' for e in ee))
* x
1, 1
* 1/2*(log(b*x + a) - log(b*x - a))/(a*b)
25, 39
* arctan(b*x/a)/(a*b)
14, 19
* -1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x)))
31, 75
* [-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)]
68, 117
Perfect match with the desired values!
3 | No.3 Revision |
To every expression one can associate a syntactic tree.
The function you have in mind seems to be counting the size
of that tree; not only the leaves but all the tree's vertices.
With that in mind, I would not call it LeafCount
.
Sage may have the function you need; or it may be
easy to define using Sage's ExpressionTreeWalker
and "map reduce".
Anyway, let us write a small tree_size
function.
It gives the tree size of a symbolic expression, as well as of a list, tuple, or vector of symbolic expressions.
def tree_size(expr):
try:
x, aa = expr.operator(), expr.operands()
except AttributeError:
try:
return 1 + sum(tree_size(a) for a in expr)
if x is None:
return 1
else:
return 1 + sum(tree_size(a) for a in aa)
Here is a companion function for the string length:
def string_size(expr):
return len(str(expr))
Let us define a list of the test cases in the question.
a, b, x = SR.var('a, b, x')
ee = [
x,
1/2*(log(b*x + a) - log(b*x - a))/(a*b),
arctan(b*x/a)/(a*b),
-1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x))),
[-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)],
]
and run the function on them:
sage: print('\n'.join(f'* {e}\n {tree_size(e)}, {string_size(e)}' for e in ee))
* x
1, 1
* 1/2*(log(b*x + a) - log(b*x - a))/(a*b)
25, 39
* arctan(b*x/a)/(a*b)
14, 19
* -1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x)))
31, 75
* [-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)]
68, 117
Perfect match with the desired values!
4 | No.4 Revision |
To every expression one can associate a syntactic tree.
The function you have in mind seems to be counting the size
of that tree; not only the leaves but all the tree's vertices.
With that in mind, I would not call it LeafCount
.
Sage may have the function you need; or it may be
easy to define using Sage's ExpressionTreeWalker
and "map reduce".
Anyway, let us write a small tree_size
function.
It gives the tree size of a symbolic expression, as well as of a list, tuple, or vector of symbolic expressions.
def tree_size(expr):
try:
r"""
Return the tree size of this expression.
""""
if expr not in SR:
# deal with lists, tuples, vectors
return 1 + sum(tree_size(a) for a in expr)
expr = SR(expr)
x, aa = expr.operator(), expr.operands()
except AttributeError:
try:
return 1 + sum(tree_size(a) for a in expr)
if x is None:
return 1
else:
return 1 + sum(tree_size(a) for a in aa)
Here is a companion function for the string length:
def string_size(expr):
return len(str(expr))
Let us define a list of the test cases in the question.
a, b, x = SR.var('a, b, x')
ee = [
x,
1/2*(log(b*x + a) - log(b*x - a))/(a*b),
arctan(b*x/a)/(a*b),
-1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x))),
[-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)],
]
and run the function on them:
sage: print('\n'.join(f'* {e}\n {tree_size(e)}, {string_size(e)}' for e in ee))
* x
1, 1
* 1/2*(log(b*x + a) - log(b*x - a))/(a*b)
25, 39
* arctan(b*x/a)/(a*b)
14, 19
* -1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x)))
31, 75
* [-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)]
68, 117
Perfect match with the desired values!
5 | No.5 Revision |
To every expression one can associate a syntactic tree.
The function you have in mind seems to be counting the size
of that tree; not only the leaves but all the tree's vertices.
With that in mind, I would not call it LeafCount
.
Sage may have the function you need; or it may be
easy to define using Sage's ExpressionTreeWalker
and "map reduce".
Anyway, let us write a small tree_size
function.
It gives the tree size of a symbolic expression, as well as of a list, tuple, or vector of symbolic expressions.
def tree_size(expr):
r"""
Return the tree size of this expression.
""""
"""
if expr not in SR:
# deal with lists, tuples, vectors
return 1 + sum(tree_size(a) for a in expr)
expr = SR(expr)
x, aa = expr.operator(), expr.operands()
if x is None:
return 1
else:
return 1 + sum(tree_size(a) for a in aa)
Here is a companion function for the string length:
def string_size(expr):
return len(str(expr))
Let us define a list of the test cases in the question.
a, b, x = SR.var('a, b, x')
ee = [
x,
1/2*(log(b*x + a) - log(b*x - a))/(a*b),
arctan(b*x/a)/(a*b),
-1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x))),
[-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)],
]
and run the function on them:
sage: print('\n'.join(f'* {e}\n {tree_size(e)}, {string_size(e)}' for e in ee))
* x
1, 1
* 1/2*(log(b*x + a) - log(b*x - a))/(a*b)
25, 39
* arctan(b*x/a)/(a*b)
14, 19
* -1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x)))
31, 75
* [-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)]
68, 117
Perfect match with the desired values!
6 | No.6 Revision |
To every expression one can associate a syntactic tree.
The function you have in mind seems to be counting the size
You are asking for the size of that tree; not only the leaves but tree.
Since all the tree's vertices.
With that in mind, tree vertices count I would not call it LeafCount
.
Sage may have the function you need; or it may be
easy to define using Sage's ExpressionTreeWalker
and "map reduce".
Anyway, "tree size" rather than "leaf count".
So let us write a small tree_size
function.
It I don't know whether Sage already has such a function,
or whether a shorter one might use Sage's "expression tree walker"
and "map reduce".
The function below gives the tree size of a symbolic expression, expression,
as well as
as of a list, tuple, or vector of symbolic expressions.expressions,
or any Sage object that can be converted to a symbolic expression.
def tree_size(expr):
r"""
Return the tree size of this expression.
"""
if expr not in SR:
# deal with lists, tuples, vectors
return 1 + sum(tree_size(a) for a in expr)
expr = SR(expr)
x, aa = expr.operator(), expr.operands()
if x is None:
return 1
else:
return 1 + sum(tree_size(a) for a in aa)
Here is a companion function for the string length:
def string_size(expr):
r"""
Return the length of the string representation of this expression.
"""
return len(str(expr))
Let us define a list of the test cases in the question.
a, b, x = SR.var('a, b, x')
ee = [
x,
1/2*(log(b*x + a) - log(b*x - a))/(a*b),
arctan(b*x/a)/(a*b),
-1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x))),
[-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)],
]
and run the function on them:
sage: print('\n'.join(f'* {e}\n {tree_size(e)}, {string_size(e)}' for e in ee))
* x
1, 1
* 1/2*(log(b*x + a) - log(b*x - a))/(a*b)
25, 39
* arctan(b*x/a)/(a*b)
14, 19
* -1/12*sqrt(3)*arctan(1/12*(7*sqrt(3)*cos(x)^2 - 4*sqrt(3))/(cos(x)*sin(x)))
31, 75
* [-sqrt(-a*b)*log((a*x - b - 2*sqrt(-a*b)*sqrt(x))/(a*x + b))/(a*b),
-2*sqrt(a*b)*arctan(sqrt(a*b)/(a*sqrt(x)))/(a*b)]
68, 117
Perfect match with the desired values!
Now also works for the follow-up requests in the comment:
sage: [tree_size(a) for a in [1, 1/2, 3.4, i, CC(3, 2)]]
[1, 1, 1, 1, 1]
sage: x = polygen(ZZ)
sage: p = x - x^2
sage: p
-x^2 + x
sage: tree_size(p)
7
sage: f = (x - x^2) / (1 - 3*x)
sage: f
(-x^2 + x)/(-3*x + 1)
sage: tree_size(f)
15
Related:
num_leaves
method.
By the way, if you have interesting complicated expressions in QQbar,
see Fredrik Johansson's request for benchmark problems on sage-devel.