Coefficients
Run Symbolica in your browser
Python examples with a Run button can be edited and run here. The first run loads Python, Symbolica, hover documentation, and code completion.
Use display(expr) to pretty-print an intermediate result. The last expression is displayed automatically.
By default a coefficient of a term in Symbolica is a rational number. For example in the expression
the coefficients are
For many applications it is favourable to extend the coefficient ring to include variables. If we consider
For example, when coding the following iterative replacement rule:
a possible Symbolica code is:
from symbolica import *
ep, m, n_ = Expression.symbol('ep', 'm', 'n_')
topo = Expression.symbol('topo')
T = Transformer()
e = T.repeat(
T.stats('ibp',
T.expand().
replace(topo(n_),
topo(n_ - 1) * (2 + (4-2*ep) - 2 * n_) /
(2*(n_ - 1)) / m**2,
n_ > 1))
)(topo(10))
eOutput
1/72*ep*m^-18*topo(1)+223/10080*ep^2*m^-18*topo(1)+1/5670*ep^3*m^-18*topo(1)
-101/5760*ep^4*m^-18*topo(1)-229/17280*ep^5*m^-18*topo(1)-13/2880*ep^6*m^-18*topo(1)
-7/8640*ep^7*m^-18*topo(1)-1/13440*ep^8*m^-18*topo(1)-1/362880*ep^9*m^-18*topo(1)
At each stage, the pattern matcher will match and replace a topo(n) in every term, and will create new terms for every power of ep.
This overhead can be avoided by considering ep to be a part of the coefficient. Then we have topo(2)*ep+topo(2) = topo(2)*(ep+1).
We use Expression.COEFF (Atom::COEFF in Rust) that converts its rational polynomial argument to a coefficient:
e = T.repeat(
T.stats('ibp_num',
T.replace(topo(n_),
topo(n_ - 1)
*Expression.COEFF((2 + (4-2*ep) -
2 * n_)/(2*(n_ - 1))) / m**2,
n_ > 1))
)(topo(10))
print(e)This code is much faster and the expression looks like:
[(5040*ep+8028*ep^2+64*ep^3-6363*ep^4-4809*ep^5-1638*ep^6-294*ep^7-27*ep^8-ep^9)/362880]*m^-18*topo(1)
where [...] indicates that the contained rational polynomial is a coefficient.
Since it is a coefficient, we cannot pattern match on the internal structure. To do these operations,
we can convert back from a number to an atom using from_coeff:
e = e.replace(n_, n_.hold(T.from_coeff()), n_.req_type(AtomType.Num))Output
1/362880*m^-18*(5040*ep+8028*ep^2+64*ep^3-6363*ep^4-4809*ep^5-1638*ep^6-294*ep^7-27*ep^8-ep^9)*topo(1)
Coefficient rings
The coefficient ring can also be changed using the set_coefficient_ring function which takes the variables that should be considered part of the coefficient as an argument. It will then rewrite the expression.
from symbolica import Expression
x, y, z = Expression.symbol('x', 'y', 'z')
e = x*z+x*(y+2)**-1*(y+z+1)
e.set_coefficient_ring([y, z])use std::sync::Arc;
use symbolica::prelude::*;
fn main() {
let expr = parse!("x*z+x*(y+2)^-1*(y+z+1)");
println!("> In: {}", expr);
let expr_yz = expr.set_coefficient_ring(
&Arc::new(vec![
symbol!("y").into(),
symbol!("z").into(),
]),
);
println!("> Coefficient ring y,z: {}", expr_yz);
}Output
[(1+3*z+y+y*z)/(2+y)]*x