Examples & Tutorials
Comprehensive examples demonstrating Symmetrica's capabilities.
New! Check out our
Complete Examples Catalog with all 13 runnable examples, source code links, and detailed instructions.
Building Expressions
Basic Operations
use expr_core::Store;
let mut st = Store::new();
let x = st.sym("x");
let y = st.sym("y");
// Addition
let sum = st.add(vec![x, y, st.int(5)]);
println!("{}", st.to_string(sum)); // 5 + x + y
// Multiplication
let product = st.mul(vec![st.int(2), x, y]);
println!("{}", st.to_string(product)); // 2 * x * y
// Power
let squared = st.pow(x, st.int(2));
println!("{}", st.to_string(squared)); // x^2
// Rational numbers
let half = st.rat(1, 2);
let expr = st.mul(vec![half, x]);
println!("{}", st.to_string(expr)); // 1/2 * x
Nested Expressions
// Build (x + 1)² * (y - 2)
let x_plus_1 = st.add(vec![x, st.int(1)]);
let squared = st.pow(x_plus_1, st.int(2));
let y_minus_2 = st.add(vec![y, st.int(-2)]);
let result = st.mul(vec![squared, y_minus_2]);
println!("{}", st.to_string(result));
// (1 + x)^2 * (-2 + y)
Functions
// Trigonometric functions
let sin_x = st.func("sin", vec![x]);
let cos_x = st.func("cos", vec![x]);
// Exponential and logarithm
let exp_x = st.func("exp", vec![x]);
let ln_x = st.func("ln", vec![x]);
// Composition
let sin_squared = st.pow(st.func("sin", vec![x]), st.int(2));
println!("{}", st.to_string(sin_squared));
// sin(x)^2
Simplification
Like Terms
use simplify::simplify;
// Collect like terms
let expr = st.add(vec![x, x, x]);
let result = simplify(&mut st, expr);
println!("{}", st.to_string(result)); // 3 * x
// Combine powers
let expr = st.mul(vec![
st.pow(x, st.int(2)),
st.pow(x, st.int(3))
]);
let result = simplify(&mut st, expr);
println!("{}", st.to_string(result)); // x^5
Logarithm Rules
use assumptions::{Context, Prop};
let mut ctx = Context::new();
ctx.assume("x", Prop::Positive);
ctx.assume("y", Prop::Positive);
// ln(x * y) → ln(x) + ln(y)
let product = st.mul(vec![x, y]);
let ln_product = st.func("ln", vec![product]);
let result = simplify_with(&mut st, ln_product, &ctx);
println!("{}", st.to_string(result));
// ln(x) + ln(y)
Trigonometric Identities
// exp(ln(x)) → x (with positive assumption)
ctx.assume("x", Prop::Positive);
let ln_x = st.func("ln", vec![x]);
let exp_ln = st.func("exp", vec![ln_x]);
let result = simplify_with(&mut st, exp_ln, &ctx);
println!("{}", st.to_string(result)); // x
Substitution
Symbol Substitution
use pattern::subst_symbol;
// Substitute x → 2y + 1 in x² + 3x
let expr = st.add(vec![
st.pow(x, st.int(2)),
st.mul(vec![st.int(3), x])
]);
let two_y_plus_1 = st.add(vec![
st.mul(vec![st.int(2), y]),
st.int(1)
]);
let result = subst_symbol(&mut st, expr, "x", two_y_plus_1);
let simplified = simplify(&mut st, result);
println!("{}", st.to_string(simplified));
// 1 + 8 * y + 6 * y^2 + 4 * y^2
Function Composition
// f(x) = x², g(x) = x + 1
// Compute f(g(x))
let f = st.pow(x, st.int(2));
let g = st.add(vec![x, st.int(1)]);
let composition = subst_symbol(&mut st, f, "x", g);
println!("{}", st.to_string(composition));
// (1 + x)^2
Differentiation
Basic Derivatives
use calculus::diff;
// d/dx (x³ + 2x² + x + 1)
let expr = st.add(vec![
st.pow(x, st.int(3)),
st.mul(vec![st.int(2), st.pow(x, st.int(2))]),
x,
st.int(1)
]);
let derivative = diff(&mut st, expr, "x");
let result = simplify(&mut st, derivative);
println!("{}", st.to_string(result));
// 1 + 4 * x + 3 * x^2
Chain Rule
// d/dx sin(x²)
let x_squared = st.pow(x, st.int(2));
let expr = st.func("sin", vec![x_squared]);
let derivative = diff(&mut st, expr, "x");
println!("{}", st.to_string(derivative));
// cos(x^2) * 2 * x
Product Rule
// d/dx (x² * sin(x))
let x_squared = st.pow(x, st.int(2));
let sin_x = st.func("sin", vec![x]);
let expr = st.mul(vec![x_squared, sin_x]);
let derivative = diff(&mut st, expr, "x");
let result = simplify(&mut st, derivative);
println!("{}", st.to_string(result));
Integration
Power Rule
use calculus::integrate;
// ∫ x² dx
let expr = st.pow(x, st.int(2));
let integral = integrate(&mut st, expr, "x").unwrap();
println!("{}", st.to_string(integral));
// 1/3 * x^3
// ∫ 1/x dx
let inv_x = st.pow(x, st.int(-1));
let integral = integrate(&mut st, inv_x, "x").unwrap();
println!("{}", st.to_string(integral));
// ln(x)
Trigonometric Integrals
// ∫ sin(x) dx
let expr = st.func("sin", vec![x]);
let integral = integrate(&mut st, expr, "x").unwrap();
println!("{}", st.to_string(integral));
// -cos(x)
// ∫ sin(2x) dx
let two_x = st.mul(vec![st.int(2), x]);
let expr = st.func("sin", vec![two_x]);
let integral = integrate(&mut st, expr, "x").unwrap();
println!("{}", st.to_string(integral));
// -1/2 * cos(2 * x)
Integration by Parts
// ∫ x * ln(x) dx
let ln_x = st.func("ln", vec![x]);
let expr = st.mul(vec![x, ln_x]);
let integral = integrate(&mut st, expr, "x").unwrap();
let result = simplify(&mut st, integral);
println!("{}", st.to_string(result));
Series Expansion
use calculus::maclaurin;
// Taylor series for exp(x) at 0
let expr = st.func("exp", vec![x]);
let series = maclaurin(&st, expr, "x", 5).unwrap();
// Print coefficients
for (k, (n, d)) in series.coeffs.iter().enumerate() {
if *n != 0 {
if *d == 1 {
println!("x^{}: {}", k, n);
} else {
println!("x^{}: {}/{}", k, n, d);
}
}
}
// x^0: 1
// x^1: 1
// x^2: 1/2
// x^3: 1/6
// x^4: 1/24
// x^5: 1/120
Polynomial Operations
Factorization
use polys::factor;
// Factor x² - 1
let expr = st.add(vec![
st.pow(x, st.int(2)),
st.int(-1)
]);
let factors = factor(&st, expr, "x").unwrap();
for factor in factors {
println!("{}", st.to_string(factor));
}
// (x - 1) * (x + 1)
Partial Fractions
use polys::partial_fractions_simple;
// Decompose (2x + 3) / (x² + 3x + 2)
let num = st.add(vec![st.mul(vec![st.int(2), x]), st.int(3)]);
let den = st.add(vec![
st.pow(x, st.int(2)),
st.mul(vec![st.int(3), x]),
st.int(2)
]);
let result = partial_fractions_simple(&mut st, num, den, "x").unwrap();
println!("{}", st.to_string(result));
Equation Solving
Quadratic Equations
use solver::solve_univariate;
// Solve x² - 5x + 6 = 0
let eq = st.add(vec![
st.pow(x, st.int(2)),
st.mul(vec![st.int(-5), x]),
st.int(6)
]);
let roots = solve_univariate(&mut st, eq, "x").unwrap();
for root in roots {
println!("x = {}", st.to_string(root));
}
// x = 2, x = 3
Cubic Equations
// Solve x³ - 6x² + 11x - 6 = 0
let eq = st.add(vec![
st.pow(x, st.int(3)),
st.mul(vec![st.int(-6), st.pow(x, st.int(2))]),
st.mul(vec![st.int(11), x]),
st.int(-6)
]);
let roots = solve_univariate(&mut st, eq, "x").unwrap();
for root in roots {
println!("x = {}", st.to_string(root));
}
// x = 1, x = 2, x = 3
Matrix Operations
use matrix::{Matrix, determinant, solve_system};
// Create a 2×2 matrix
let mat = Matrix::from_rows(vec![
vec![st.int(2), st.int(1)],
vec![st.int(1), st.int(3)]
]);
// Compute determinant
let det = determinant(&mut st, &mat);
println!("det = {}", st.to_string(det)); // 5
// Solve Ax = b
let b = vec![st.int(5), st.int(6)];
let solution = solve_system(&mut st, &mat, &b).unwrap();
for (i, val) in solution.iter().enumerate() {
println!("x_{} = {}", i, st.to_string(*val));
}
Pattern Matching
use pattern::ac::{match_expr, Pat};
use std::collections::HashMap;
// Pattern: x + ?a
let pattern = Pat::Add(vec![
Pat::Symbol("x".into()),
Pat::Any("a".into())
]);
// Expression: x + 5
let expr = st.add(vec![x, st.int(5)]);
// Match
if let Some(bindings) = match_expr(&st, &pattern, expr) {
let a_value = bindings.get("a").unwrap();
println!("Matched! a = {}", st.to_string(*a_value));
}
Domain-Aware Simplification
use assumptions::{Context, Prop};
use simplify::simplify_with;
let mut ctx = Context::new();
ctx.assume("x", Prop::Positive);
// √(x²) with x > 0
let x_squared = st.pow(x, st.int(2));
let sqrt = st.pow(x_squared, st.rat(1, 2));
let result = simplify_with(&mut st, sqrt, &ctx);
println!("{}", st.to_string(result)); // x
// Without assumption (real but sign unknown)
ctx = Context::new();
ctx.assume("x", Prop::Real);
let result = simplify_with(&mut st, sqrt, &ctx);
println!("{}", st.to_string(result)); // abs(x)
Piecewise Functions
// Define absolute value: |x| = piecewise((x >= 0, x), (else, -x))
let zero = st.int(0);
let cond = st.func(">=", vec![x, zero]);
let neg_x = st.mul(vec![st.int(-1), x]);
let else_cond = st.func("else", vec![]);
let abs_x = st.piecewise(vec![(cond, x), (else_cond, neg_x)]);
// Simplify with True condition
let true_cond = st.func("True", vec![]);
let pw = st.piecewise(vec![(true_cond, x)]);
let result = simplify(&mut st, pw);
println!("{}", st.to_string(result)); // x (collapsed)
Tip: All examples are available in the
examples directory
of the repository. You can run them with
cargo run --example example_name
.