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



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

See Also