Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help



Expression Evaluation

Topic: operations.evaluation

MathHook provides two fundamental operations for working with expressions:

  1. Evaluation - Compute numerical values with domain checking
  2. Simplification - Algebraic reduction while staying symbolic

Understanding when to use each operation is critical for correct mathematical computation.

Mathematical Definition

Function Evaluation:

Evaluation with Context: For expression and substitutions :

Domain Constraints:

  • requires in
  • requires (pole at 0)
  • has poles at
  • require in

Quick Decision Guide

Need a numerical value? ├─ YES → Use evaluate() or evaluate_with_context() │ ├─ With variables? → evaluate_with_context(context) │ └─ Constants only? → evaluate() │ └─ NO → Need algebraic simplification? ├─ YES → Use simplify() └─ NO → Keep expression as-is

Key Differences

OperationPurposeDomain CheckingSubstitutionReturns
evaluate()Numerical computation✅ Yes❌ NoResult<Expression, MathError>
evaluate_with_context()Substitution + computation✅ Yes✅ YesResult<Expression, MathError>
simplify()Algebraic reduction❌ No❌ NoExpression

Domain Constraints Checked

  • sqrt(x): Requires x ≥ 0 in real domain
  • log(x): Requires x > 0 (pole at 0)
  • tan(x): Has poles at π/2 + nπ
  • arcsin(x), arccos(x): Require |x| ≤ 1 in real domain
  • Division by zero: Checked in x/y and x^(-n)

Evaluation Context Options

#![allow(unused)]
fn main() {
pub struct EvalContext {
    pub variables: HashMap<String, Expression>,  // Variable substitutions
    pub precision: u32,                          // Numerical precision
    pub simplify_first: bool,                    // Simplify before evaluation?
    pub numeric: bool,                           // Perform numerical evaluation?
}
}

Examples

Constants Evaluate to Numbers

Direct evaluation of constant expressions

Rust
#![allow(unused)]
fn main() {
use mathhook::prelude::*;

let sum = expr!(2 + 3);
assert_eq!(sum.evaluate().unwrap(), expr!(5));

// Domain checking catches errors
let sqrt_neg = expr!(sqrt(-1));
assert!(matches!(sqrt_neg.evaluate(), Err(MathError::DomainError { .. })));

}
Python
from mathhook import expr

sum_expr = expr('2 + 3')
assert sum_expr.evaluate() == 5

# Domain checking catches errors
sqrt_neg = expr('sqrt(-1)')
try:
    sqrt_neg.evaluate()
    assert False, "Should raise domain error"
except MathError:
    pass

JavaScript
const { expr } = require('mathhook');

const sum = expr('2 + 3');
assert(sum.evaluate() === 5);

// Domain checking catches errors
const sqrtNeg = expr('sqrt(-1)');
try {
    sqrtNeg.evaluate();
    throw new Error("Should raise domain error");
} catch (e) {
    // Expected MathError
}

Evaluation with Context (Substitution)

Substitute variable values and evaluate

Rust
#![allow(unused)]
fn main() {
use mathhook_core::core::expression::eval_numeric::EvalContext;
use mathhook::prelude::*;
use std::collections::HashMap;

let x = symbol!(x);

// Substitute x = 3 and evaluate
let mut vars = HashMap::new();
vars.insert("x".to_string(), Expression::integer(3));
let ctx = EvalContext::numeric(vars);

let expr = Expression::pow(x.clone(), Expression::integer(2));
assert_eq!(expr.evaluate_with_context(&ctx).unwrap(), Expression::integer(9));

}
Python
from mathhook import symbol, Expression

x = symbol('x')
expr = x ** 2

# Substitute x = 3 and evaluate
ctx = {'x': 3}
result = expr.evaluate_with_context(ctx)
assert result == 9

JavaScript
const { symbol } = require('mathhook');

const x = symbol('x');
const expr = x.pow(2);

// Substitute x = 3 and evaluate
const ctx = { x: 3 };
const result = expr.evaluateWithContext(ctx);
assert(result === 9);

Simplification Without Domain Checking

Simplify operates purely symbolically without domain validation

Rust
#![allow(unused)]
fn main() {
use mathhook::prelude::*;
use mathhook_core::simplify::Simplify;

let x = symbol!(x);

// Combine like terms
let sum = expr!(x + x);
assert_eq!(sum.simplify(), expr!(2 * x));

// Apply identities
assert_eq!(expr!(x * 1).simplify(), expr!(x));
assert_eq!(expr!(0 * x).simplify(), expr!(0));

}
Python
from mathhook import symbol

x = symbol('x')

# Combine like terms
sum_expr = x + x
assert sum_expr.simplify() == 2 * x

# Apply identities
assert (x * 1).simplify() == x
assert (0 * x).simplify() == 0

JavaScript
const { symbol } = require('mathhook');

const x = symbol('x');

// Combine like terms
const sumExpr = x.add(x);
assert(sumExpr.simplify().equals(x.mul(2)));

// Apply identities
assert(x.mul(1).simplify().equals(x));
assert(x.mul(0).simplify().equals(0));

Performance

Time Complexity: O(n) for expression tree size n

API Reference

  • Rust: mathhook_core::core::expression::eval_numeric::evaluate
  • Python: mathhook.evaluate
  • JavaScript: mathhook.evaluate

See Also