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:

a2b2=(a+b)(ab)a^2 - b^2 = (a + b)(a - b)
- Perfect Square:
a2+2ab+b2=(a+b)2a^2 + 2ab + b^2 = (a + b)^2
- Power Rule:
ddx(xn)=nxn1\frac{d}{dx}(x^n) = nx^{n-1}
- Chain Rule:
ddxf(g(x))=f(g(x))g(x)\frac{d}{dx}f(g(x)) = f'(g(x)) \cdot g'(x)
- Pythagorean Identity:
sin2(x)+cos2(x)=1\sin^2(x) + \cos^2(x) = 1

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));

🔗 Related Topics