RootSum – sums over the roots of a polynomial.¶
A RootSumFunction represents a symbolic expression of the form
where \(P\) is a univariate polynomial, the sum runs over all roots \(r\) of \(P\) (counted with multiplicity), and \(f\) is a symbolic expression that may involve \(r\) and any number of free variables.
Such expressions arise, for example, as antiderivatives of rational functions whose denominator does not factor over the coefficient field. They are produced by Maxima, FriCAS, Wolfram and SymPy. The classical example (see also R. Fateman, “Simplifying RootSum Expressions”) is
The root variable is bound. Substitution acts on free occurrences only,
and alpha-renames the root variable when needed to avoid capture. Bound
names are normalized at construction, so alpha-equivalent root sums have
identical symbolic representations. As with other symbolic expressions,
variables() lists all occurring symbols; use free_variables() to
obtain the unbound ones.
INPUT:
poly– a univariate polynomial, given as a symbolic expression, for exampler^3 + a*r + 1root_var– the symbolic variable that is summed over; it must occur inpolysummand– a symbolic expression inroot_var(and possibly other free variables) giving the term to sum
OUTPUT:
A symbolic expression representing \(\sum_{r:P(r)=0} f(r)\).
EXAMPLES:
sage: from sage.symbolic.rootsum import root_sum
sage: var('x a r')
(x, a, r)
sage: P = r^3 + a*r + 1
sage: rs = root_sum(P, r, log(x - r)/(a + 3*r^2))
sage: rs
root_sum(r^3 + a*r + 1, r, log(-r + x)/(3*r^2 + a))
>>> from sage.all import *
>>> from sage.symbolic.rootsum import root_sum
>>> var('x a r')
(x, a, r)
>>> P = r**Integer(3) + a*r + Integer(1)
>>> rs = root_sum(P, r, log(x - r)/(a + Integer(3)*r**Integer(2)))
>>> rs
root_sum(r^3 + a*r + 1, r, log(-r + x)/(3*r^2 + a))
from sage.symbolic.rootsum import root_sum
var('x a r')
P = r^3 + a*r + 1
rs = root_sum(P, r, log(x - r)/(a + 3*r^2))
rs
The three operands are accessible directly:
sage: rs.operands()[0]
r^3 + a*r + 1
sage: rs.operands()[1]
r
sage: rs.operands()[2]
log(-r + x)/(3*r^2 + a)
>>> from sage.all import *
>>> rs.operands()[Integer(0)]
r^3 + a*r + 1
>>> rs.operands()[Integer(1)]
r
>>> rs.operands()[Integer(2)]
log(-r + x)/(3*r^2 + a)
rs.operands()[0] rs.operands()[1] rs.operands()[2]
Substituting a free variable preserves the expression:
sage: rs.subs(a == 0)
root_sum(r^3 + 1, r, 1/3*log(-r + x)/r^2)
>>> from sage.all import *
>>> rs.subs(a == Integer(0))
root_sum(r^3 + 1, r, 1/3*log(-r + x)/r^2)
rs.subs(a == 0)
A low-degree polynomial evaluates explicitly when its roots are available:
sage: root_sum(r^2 - 1, r, r^2)
2
>>> from sage.all import *
>>> root_sum(r**Integer(2) - Integer(1), r, r**Integer(2))
2
root_sum(r^2 - 1, r, r^2)
A quintic stays unevaluated:
sage: root_sum(r^5 - r + 1, r, sin(r))
root_sum(r^5 - r + 1, r, sin(r))
>>> from sage.all import *
>>> root_sum(r**Integer(5) - r + Integer(1), r, sin(r))
root_sum(r^5 - r + 1, r, sin(r))
root_sum(r^5 - r + 1, r, sin(r))
The derivative of a root sum is again a root sum, taken under the sum:
sage: rs.diff(x)
1/(x^3 + a*x + 1)
>>> from sage.all import *
>>> rs.diff(x)
1/(x^3 + a*x + 1)
rs.diff(x)
The motivating application is antidifferentiation of rational functions. The derivative of the returned root sum equals the integrand:
sage: # needs sympy
sage: F = integrate(1/(x^3 + a*x + 1), x, algorithm='sympy')
sage: D = F.diff(x)
sage: val = root_sum.evaluate(D.subs(a == 1, x == 1), prec=100)
sage: abs(val - 1/3) < 1e-25
True
>>> from sage.all import *
>>> # needs sympy
>>> F = integrate(Integer(1)/(x**Integer(3) + a*x + Integer(1)), x, algorithm='sympy')
>>> D = F.diff(x)
>>> val = root_sum.evaluate(D.subs(a == Integer(1), x == Integer(1)), prec=Integer(100))
>>> abs(val - Integer(1)/Integer(3)) < RealNumber('1e-25')
True
# needs sympy F = integrate(1/(x^3 + a*x + 1), x, algorithm='sympy') D = F.diff(x) val = root_sum.evaluate(D.subs(a == 1, x == 1), prec=100) abs(val - 1/3) < 1e-25
- class sage.symbolic.rootsum.RootSumFunction[source]¶
Bases:
BuiltinFunctionThe symbolic function
root_sum.See the module docstring for details.
- evaluate(expr, prec=53)[source]¶
Numerically evaluate an expression containing root sums.
Exact squarefree decomposition preserves multiplicities before numerical root finding.
precis working bit precision; it does not certify the relative error of a nearly cancelling sum.EXAMPLES:
sage: r = var('r') sage: rs = root_sum(r^5-r+1, r, sin(r)) sage: root_sum.evaluate(rs, prec=100) -0.041691470337868009879662475806 sage: root_sum.evaluate(root_sum((r-1)^5, r, r)) 5.00000000000000 sage: root_sum.evaluate(1 + rs, prec=100) 0.95830852966213199012033752419
>>> from sage.all import * >>> r = var('r') >>> rs = root_sum(r**Integer(5)-r+Integer(1), r, sin(r)) >>> root_sum.evaluate(rs, prec=Integer(100)) -0.041691470337868009879662475806 >>> root_sum.evaluate(root_sum((r-Integer(1))**Integer(5), r, r)) 5.00000000000000 >>> root_sum.evaluate(Integer(1) + rs, prec=Integer(100)) 0.95830852966213199012033752419
r = var('r') rs = root_sum(r^5-r+1, r, sin(r)) root_sum.evaluate(rs, prec=100) root_sum.evaluate(root_sum((r-1)^5, r, r)) root_sum.evaluate(1 + rs, prec=100)