First steps
This page is a short tour of the most common Symbolica operations. For a local setup, see Installation.
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.
Create expressions
Symbols can be used as variables or called as functions. Arithmetic with Symbolica expressions keeps exact integers and rational numbers exact.
In Python, S, E, N, and T are shorthands for Expression.symbol, Expression.parse, Expression.num, and Transformer.
from symbolica import *
x, y, f = S('x', 'y', 'f')
expr = (x + 1)**2 + f(y, x) / 3
expruse symbolica::prelude::*;
fn main() {
let (x, y, f) = symbol!("x", "y", "f");
let expr = (x + 1).pow(2) + function!(f, y, x) / 3;
println!("{expr}");
}Output
1/3*f(y,x)+(1+x)^2
Parse, expand, and collect
Use the parser for compact input, then apply algebraic operations directly to the expression.
from symbolica import *
x, y = S('x', 'y')
expr = E('(x+y)^3 + x*y')
expanded = expr.expand()
print(expanded)
expanded.collect(x)use symbolica::prelude::*;
fn main() {
let expr = parse!("(x+y)^3 + x*y");
let expanded = expr.expand();
println!("{expanded}");
println!("{}", expanded.collect::<u8>(parse!("x")));
}Output
x*y+3*x*y^2+3*x^2*y+x^3+y^3
x*(y+3*y^2)+3*x^2*y+x^3+y^3
Replace expressions
Literal replacements substitute a specific expression everywhere it appears. Wildcards, such as x_, match a class of expressions and are the basis of pattern matching.
from symbolica import *
x, y, f = S('x', 'y', 'f')
expr = f(x) + x
print(expr.replace(x, y + 1))
x_ = S('x_')
expr = E('f(1) + f(2) + f(3)')
expr.replace(f(x_), x_**2)use symbolica::prelude::*;
fn main() {
let x = symbol!("x");
let expr = parse!("f(x) + x");
let shifted = expr.replace(x).with(parse!("y + 1"));
println!("{shifted}");
let expr = parse!("f(1) + f(2) + f(3)");
println!("{}", expr.replace(parse!("f(x_)")).with(parse!("x_^2")));
}Output
1+y+f(1+y)
14
For more control over wildcards and restrictions, see Pattern matching.
Differentiate and factor
Symbolica can differentiate expressions and factor many expressions over the rationals.
from symbolica import *
x, y = S('x', 'y')
expr = E('(x+1)^3 + sin(x)')
print(expr.derivative(x))
poly_expr = E('(x+1)^2*(x+y)').expand()
poly_expr.factor()use symbolica::prelude::*;
fn main() {
let x = symbol!("x");
let expr = parse!("(x+1)^3 + sin(x)");
println!("{}", expr.derivative(x));
let poly_expr = parse!("(x+1)^2*(x+y)").expand();
println!("{}", poly_expr.factor());
}Output
cos(x)+3*(1+x)^2
(1+x)^2*(x+y)
Integrate with steps
Integrate expressions symbolically, and optionally get a step-by-step overview of the integration process.
This example requires a local Symbolica installation with symbolic integration; the current browser build does not include that backend.
from symbolica import *
x = S('x')
expr = (1/(x**2+1)).integrate(x) # atan(x)
result, overview, steps = (x/(x+1)).integrate_with_steps(x)
print(overview)
resultAdd the symbolica-integrate crate to your Cargo.toml to use the integration features. Include the steps feature to enable step-by-step integration.
use symbolica::prelude::*;
use symbolica_integrate::Integrate;
fn main() {
let x = symbol!("x");
let expr = parse!("1/(x^2+1)").integrate(x).unwrap(); // atan(x)
let (result, overview, steps) = parse!("x/(1+x)").integrate_with_steps(x);
println!("{overview}");
}Output
∫ x/(1+x) dx = ∫ 1-1/(1+x) dx
∫ 1-1/(1+x) dx = ∫ 1 dx+∫ 1/(-1-x) dx
∫ 1 dx = x
∫ -1/(1+x) dx = -log(1+x)
= x-log(1+x)
Simplify rational expressions
Use together to put terms over a common denominator, apart for partial fractions, and cancel to remove common factors without expanding everything else. In Python, apart() chooses variables automatically; apart([x, y]) performs multivariate decomposition.
from symbolica import *
x, y, z = S('x', 'y', 'z')
print(E('1/x + (2*x+y+z)/y').together())
print(E('(y+2*x^2+x*y+x*z)/(x*y)').apart(x))
E('1+(y+1)^10*(x+1)/(x^2+2*x+1)').cancel()use symbolica::prelude::*;
fn main() {
let x = symbol!("x");
println!("{}", parse!("1/x + (2*x+y+z)/y").together());
println!("{}", parse!("(y+2*x^2+x*y+x*z)/(x*y)").apart(x));
println!("{}", parse!("1+(y+1)^10*(x+1)/(x^2+2*x+1)").cancel());
}Output
(x*y+x*z+y+2*x^2)/(x*y)
1/x+(2*x+y+z)/y
1+(1+y)^10/(1+x)
Expand series and solve systems
Series expansions return a series object that supports arithmetic and distinguishes known coefficients from the unknown remainder. Symbolica solves supported linear and nonlinear equations exactly. The example below selects one solution branch; for general problems, inspect every branch and its conditions and check solution coverage.
from symbolica import *
x, y, c, f = S('x', 'y', 'c', 'f')
print(E('exp(5+x)/(1-x)').series(x, 0, 3))
sol = Expression.solve([f(c)*x + y + c, y + c**2], [x, y])[0]
soluse symbolica::prelude::*;
fn main() {
let x = symbol!("x");
let series = parse!("exp(5+x)/(1-x)").series(x, 0, 3).unwrap();
println!("{}", series.to_atom());
let equations = [parse!("f(c)*x + y + c"), parse!("y + c^2")];
let variables = [parse!("x"), parse!("y")];
let solutions = Atom::solve(&equations).wrt(&variables).unwrap();
for (var, value) in &solutions[0] {
println!("{var} = {value}");
}
}Output
exp(5)+2*exp(5)*x+5/2*exp(5)*x^2+8/3*exp(5)*x^3+O(x^4)
x = (-c+c^2)/f(c)
y = -c^2
Evaluate numerically
For repeated numerical evaluation, first build an evaluator. Evaluators can optimize expressions and, in Python, can JIT compile on first use.
from symbolica import *
x, y = S('x', 'y')
ev = E('x*y + x^2').evaluator([x, y])
ev.evaluate_with_prec([Float(1), Float(2)], 16)[0]The browser example uses arbitrary-precision evaluation. For NumPy arrays on a local installation, use ev.evaluate([[1.0, 2.0]])[0, 0]; native JIT compilation is unavailable in the browser.
use symbolica::prelude::*;
fn main() {
let params = vec![parse!("x"), parse!("y")];
let mut ev = parse!("x*y + x^2")
.evaluator(¶ms)
.build()
.unwrap()
.map_coeff(&|c| c.re.to_f64());
println!("{}", ev.evaluate_single(&[1.0, 2.0]));
}Output
3
For nested functions, multiple outputs, JIT settings, and code generation, see Numerical evaluation.
Work with polynomials
Expressions can be converted into Symbolica’s polynomial data structures for faster polynomial arithmetic and factorization. See Algebraic numbers to put radicals and exact roots into the coefficient field.
from symbolica import *
x, y = S('x', 'y')
poly = E('(x+1)^2*(x+y)').expand().to_polynomial(vars=[x, y])
print(poly)
print(poly.derivative(x))
poly.factor()use symbolica::prelude::*;
fn main() {
let expr = parse!("(x+1)^2*(x+y)").expand();
let poly: MultivariatePolynomial<_, u8> = expr.to_polynomial(&Z, None);
println!("{poly}");
println!("{}", poly.derivative(0));
let factors = poly.factor();
let rendered = factors
.iter()
.map(|(factor, power)| format!("({factor}, {power})"))
.collect::<Vec<_>>()
.join(", ");
println!("[{rendered}]");
}Output
y+x+2*x*y+2*x^2+x^2*y+x^3
1+2*y+4*x+2*x*y+3*x^2
[(1+x, 2), (y+x, 1)]
Where to go next
- Symbols: define symbols, namespaces, attributes, tags, aliases, and custom behavior.
- Expressions: learn the expression tree, parsing, printing, and normalization.
- Pattern matching: rewrite expressions with wildcards and restrictions.
- Numerical evaluation: turn expressions into fast numerical evaluators.
- Polynomials: use finite fields, rational functions, and polynomial algorithms.