Pattern Matching
Pattern matching is a powerful technique in MathHook for identifying, transforming, and simplifying mathematical expressions. MathHook combines Rust's native pattern matching with specialized mathematical pattern recognition to enable sophisticated symbolic manipulation including algebraic identities, calculus rules, and trigonometric transformations.
Mathematical Definition
Common Mathematical Patterns:
- Difference of Squares:
Code Examples
Rust Native Pattern Matching on Expressions
Using Rust's match statement to analyze expression structure
use mathhook::prelude::*;
fn analyze_expression(expr: &Expression) -> String {
match expr {
Expression::Integer(n) => format!("Integer: {}", n),
Expression::Symbol(s) => format!("Variable: {}", s.name()),
Expression::Add(terms) => format!("Sum of {} terms", terms.len()),
Expression::Mul(factors) => format!("Product of {} factors", factors.len()),
Expression::Pow(base, exp) => format!("Power: ({})^({})", base, exp),
Expression::Function { name, args } => {
format!("Function {}: {} args", name, args.len())
}
_ => "Other expression type".to_string(),
}
}
let expr = expr!(x^2 + 2*x + 1);
println!("{}", analyze_expression(&expr));
Algebraic Pattern: Difference of Squares
Recognizing and factoring difference of squares pattern
use mathhook::prelude::*;
let a = symbol!(a);
let b = symbol!(b);
// Pattern: a² - b² = (a + b)(a - b)
let diff_squares = expr!(a^2 - b^2);
let factored = diff_squares.factor();
assert_eq!(factored, expr!((a + b) * (a - b)));
// Recognizes in complex forms
let x = symbol!(x);
let example = expr!(x^4 - 16);
let factored_example = example.factor();
// (x² + 4)(x² - 4)
assert_eq!(factored_example, expr!((x^2 + 4) * (x^2 - 4)));
Calculus Pattern: Power Rule Derivative
Automatic pattern recognition for power rule differentiation
use mathhook::prelude::*;
let x = symbol!(x);
// Pattern: d/dx(x^n) = n*x^(n-1)
let f = expr!(x^5);
let df = f.derivative(&x, 1);
assert_eq!(df, expr!(5 * x^4));
// Works for any power
let sqrt_x = expr!(x^(1/2));
let d_sqrt = sqrt_x.derivative(&x, 1);
assert_eq!(d_sqrt, expr!((1/2) * x^(-1/2)));
Calculus Pattern: Chain Rule
Automatic chain rule application for composite functions
use mathhook::prelude::*;
let x = symbol!(x);
// Pattern: d/dx f(g(x)) = f'(g(x)) * g'(x)
let f = expr!(sin(x^2));
// sin(u) where u = x²
// Derivative: cos(u) * du/dx = cos(x²) * 2x
let df = f.derivative(&x, 1);
assert_eq!(df, expr!(2*x*cos(x^2)));
// Nested composition
let nested = expr!(sin(cos(x)));
let d_nested = nested.derivative(&x, 1);
// cos(cos(x)) * (-sin(x))
assert_eq!(d_nested, expr!(-sin(x)*cos(cos(x))));
Trigonometric Pattern: Pythagorean Identity
Automatic simplification using trigonometric identities
use mathhook::prelude::*;
let x = symbol!(x);
// Pattern: sin²(x) + cos²(x) = 1
let identity = expr!(sin(x)^2 + cos(x)^2);
assert_eq!(identity.simplify(), expr!(1));
// Pattern: 1 + tan²(x) = sec²(x)
let tan_identity = expr!(1 + tan(x)^2);
assert_eq!(tan_identity.simplify(), expr!(sec(x)^2));
// Pattern: 1 + cot²(x) = csc²(x)
let cot_identity = expr!(1 + cot(x)^2);
assert_eq!(cot_identity.simplify(), expr!(csc(x)^2));
Logarithm Pattern: Log Laws
Automatic application of logarithm expansion and combination rules
use mathhook::prelude::*;
let a = symbol!(a);
let b = symbol!(b);
let n = symbol!(n);
// Pattern: ln(a*b) = ln(a) + ln(b)
let log_product = expr!(ln(a*b));
assert_eq!(log_product.expand(), expr!(ln(a) + ln(b)));
// Pattern: ln(a/b) = ln(a) - ln(b)
let log_quotient = expr!(ln(a/b));
assert_eq!(log_quotient.expand(), expr!(ln(a) - ln(b)));
// Pattern: ln(a^n) = n*ln(a)
let log_power = expr!(ln(a^n));
assert_eq!(log_power.expand(), expr!(n*ln(a)));
Custom Pattern Matcher: Polynomial Detection
Implementing custom pattern recognition for polynomial expressions
use mathhook::prelude::*;
/// Pattern matcher for polynomial expressions
fn is_polynomial(expr: &Expression, var: &Symbol) -> bool {
match expr {
// Constant term
Expression::Integer(_) | Expression::Rational(_) => true,
// Variable itself
Expression::Symbol(s) if s == var => true,
// Power of variable
Expression::Pow(base, exp) => {
matches!(**base, Expression::Symbol(ref s) if s == var) &&
matches!(**exp, Expression::Integer(n) if n >= 0)
}
// Sum or product of polynomials
Expression::Add(terms) | Expression::Mul(factors) => {
terms.iter().all(|t| is_polynomial(t, var)) ||
factors.iter().all(|f| is_polynomial(f, var))
}
_ => false,
}
}
let x = symbol!(x);
assert!(is_polynomial(&expr!(x^2 + 3*x + 1), &x));
assert!(!is_polynomial(&expr!(sin(x)), &x));