Python API Guide
Topic:
bindings.python
Complete guide to using MathHook from Python via PyO3 bindings. Provides comprehensive documentation for the Python API including installation, quick start, API reference, performance comparisons with SymPy, and integration patterns.
Python API Guide
Complete guide to using MathHook from Python via PyO3 bindings.
Installation
pip install mathhook
Requirements:
- Python 3.8 or higher
- pip 20.0 or higher (for binary wheel support)
Platform Support:
- Linux (x86_64, aarch64)
- macOS (Intel, Apple Silicon)
- Windows (x86_64)
Quick Start
from mathhook import Symbol, parse, simplify
# Create symbols
x = Symbol('x')
y = Symbol('y')
# Build expressions
expr = x**2 + 2*x + 1
# Simplify
simplified = simplify(expr)
print(simplified) # (x + 1)^2
Why MathHook for Python?
Performance Comparison
100x Faster Than SymPy for large expressions:
import time
from mathhook import parse, simplify
# Large polynomial expression
expr_str = " + ".join([f"{i}*x**{i}" for i in range(100)])
# MathHook
start = time.time()
expr = parse(expr_str)
result = simplify(expr)
mathhook_time = time.time() - start
print(f"MathHook: {mathhook_time:.4f}s")
# Typical: MathHook 0.001s vs SymPy 0.1s (100x faster)
When to Use MathHook vs SymPy
Use MathHook when:
- Performance is critical (real-time applications, large expressions)
- You need symbolic preprocessing for numerical simulations
- Working with expressions with >50 terms
- Building interactive applications (web, Jupyter with fast response)
Use SymPy when:
- Need advanced features: logic, sets, abstract algebra
- Educational prototyping (rich ecosystem)
- Assumption system is critical
- Working with small expressions where speed doesn't matter
Use Both:
- Prototype with SymPy, optimize with MathHook for production
- Use MathHook for hot loops, SymPy for one-time complex operations
Examples
Basic Symbol Creation and Expression Building
Create symbols and build expressions using operator overloading
Rust
#![allow(unused)] fn main() { use mathhook::symbol; use mathhook::expr; let x = symbol!(x); let y = symbol!(y); // Build expressions let expr = expr!(x^2 + 2*x + 1); let expr2 = expr!((x + 1) * (x - 1)); let expr3 = expr!(x / (x + 1)); let expr4 = expr!(-x); }
Python
from mathhook import Symbol
x = Symbol('x')
y = Symbol('y')
# Arithmetic operators
expr = x**2 + 2*x + 1
expr2 = (x + 1) * (x - 1)
expr3 = x / (x + 1)
expr4 = -x
JavaScript
const { Symbol, parse } = require('mathhook');
const x = new Symbol('x');
const y = new Symbol('y');
// Parse expressions
const expr = parse('x^2 + 2*x + 1');
const expr2 = parse('(x + 1) * (x - 1)');
const expr3 = parse('x / (x + 1)');
const expr4 = parse('-x');
Expression Simplification
Simplify algebraic expressions using MathHook
Rust
#![allow(unused)] fn main() { use mathhook::{expr, symbol, simplify}; let x = symbol!(x); let expr = expr!(x + x); let result = simplify(expr); // 2*x let expr2 = expr!((x + 1) * (x - 1)); let result2 = simplify(expr2); // x^2 - 1 }
Python
from mathhook import parse, simplify
expr = parse("x + x")
result = simplify(expr) # 2*x
expr = parse("(x + 1) * (x - 1)")
result = simplify(expr) # x^2 - 1
JavaScript
const { parse, simplify } = require('mathhook');
const expr = parse('x + x');
const result = simplify(expr); // 2*x
const expr2 = parse('(x + 1) * (x - 1)');
const result2 = simplify(expr2); // x^2 - 1
Symbolic Differentiation
Compute derivatives symbolically
Rust
#![allow(unused)] fn main() { use mathhook::{expr, symbol, derivative}; let x = symbol!(x); let expr = expr!(x^3); // First derivative let df = derivative(&expr, &x, 1); // Result: 3*x^2 // Second derivative let d2f = derivative(&expr, &x, 2); // Result: 6*x // Partial derivatives let y = symbol!(y); let expr2 = expr!(x^2 * y); let df_dx = derivative(&expr2, &x, 1); // 2*x*y let df_dy = derivative(&expr2, &y, 1); // x^2 }
Python
from mathhook import Symbol, derivative
x = Symbol('x')
expr = x**3
# First derivative
df = derivative(expr, x)
print(df) # 3*x^2
# Second derivative
d2f = derivative(expr, x, order=2)
print(d2f) # 6*x
# Partial derivatives
y = Symbol('y')
expr = x**2 * y
df_dx = derivative(expr, x) # 2*x*y
df_dy = derivative(expr, y) # x^2
JavaScript
const { Symbol, parse, derivative } = require('mathhook');
const x = new Symbol('x');
const expr = parse('x^3');
// First derivative
const df = derivative(expr, x);
console.log(df.toString()); // 3*x^2
// Second derivative
const d2f = derivative(expr, x, { order: 2 });
console.log(d2f.toString()); // 6*x
Equation Solving
Solve algebraic equations symbolically
Rust
#![allow(unused)] fn main() { use mathhook::{expr, symbol, solve}; let x = symbol!(x); // Linear equation: 2*x + 3 = 7 let solutions = solve(expr!(2*x + 3), expr!(7), &x); // Result: [x = 2] // Quadratic equation: x^2 - 5*x + 6 = 0 let solutions = solve(expr!(x^2 - 5*x + 6), expr!(0), &x); // Result: [x = 2, x = 3] }
Python
from mathhook import Symbol, solve
x = Symbol('x')
# Linear equation: 2*x + 3 = 7
solutions = solve(2*x + 3, 7, x)
print(solutions) # [x = 2]
# Quadratic equation: x^2 - 5*x + 6 = 0
solutions = solve(x**2 - 5*x + 6, 0, x)
print(solutions) # [x = 2, x = 3]
# Multiple variables
y = Symbol('y')
solutions = solve([x + y - 5, x - y - 1], [x, y])
print(solutions) # {x: 3, y: 2}
JavaScript
const { Symbol, parse, solve } = require('mathhook');
const x = new Symbol('x');
// Quadratic equation: x^2 - 5*x + 6 = 0
const expr = parse('x^2 - 5*x + 6');
const solutions = solve(expr, x);
solutions.forEach(sol => {
console.log(sol.toString());
});
// Output: x = 2, x = 3
Integration with NumPy
Convert symbolic expressions to NumPy functions for numerical evaluation
Python
import numpy as np
from mathhook import Symbol, lambdify
x = Symbol('x')
expr = x**2 + 2*x + 1
# Convert to NumPy-compatible function
f = lambdify(expr, [x], 'numpy')
# Evaluate on NumPy array
x_values = np.linspace(-5, 5, 100)
y_values = f(x_values)
# Use with NumPy operations
mean = np.mean(y_values)
std = np.std(y_values)
Evaluation with Context
Advanced evaluation with custom contexts and variable substitutions
Python
from mathhook import PyExpression as Expression, EvalContext
x = Expression.symbol("x")
y = Expression.symbol("y")
# Formula: x² + 2xy + y²
expr = x.pow(Expression.integer(2)).add(
Expression.integer(2).multiply(x).multiply(y)
).add(y.pow(Expression.integer(2)))
# Create numerical context with variable substitutions
ctx = EvalContext.numeric({
"x": Expression.integer(3),
"y": Expression.integer(4)
})
# Evaluate: (3)² + 2(3)(4) + (4)² = 9 + 24 + 16 = 49
result = expr.evaluate_with_context(ctx)
print(result) # 49
# Symbolic evaluation (no numerical conversion)
ctx_symbolic = EvalContext.symbolic()
result_symbolic = expr.evaluate_with_context(ctx_symbolic)
print(result_symbolic) # x^2 + 2*x*y + y^2 (still symbolic)
JavaScript
const { JsExpression, EvalContext, symbols } = require('mathhook');
function symbol(name) {
const [sym] = symbols(name);
return sym;
}
const x = symbol('x');
const y = symbol('y');
// Formula: x² + 2xy + y²
const expr = x.pow(JsExpression.integer(2))
.add(JsExpression.integer(2).multiply(x).multiply(y))
.add(y.pow(JsExpression.integer(2)));
// Create numerical context with variable substitutions
const ctx = EvalContext.numeric([
['x', JsExpression.integer(3)],
['y', JsExpression.integer(4)]
]);
// Evaluate: (3)² + 2(3)(4) + (4)² = 9 + 24 + 16 = 49
const result = expr.evaluateWithContext(ctx);
console.log(result.toSimple()); // '49'
API Reference
- Rust:
mathhook - Python:
mathhook - JavaScript:
mathhook-node