Skip to main content

Fast symbolic differentiation library - Rust-powered Python bindings

Project description

SymbAnaFis: Fast Symbolic Differentiation for Python & Rust

Crates.io PyPI License: MIT

A high-performance symbolic mathematics library written in Rust with Python bindings. SymbAnaFis provides fast symbolic differentiation and simplification.

Installation

Python (Recommended)

pip install symb-anafis

Rust

Add this to your Cargo.toml:

[dependencies]
symb_anafis = "0.2.5"

Quick Start

Python

import symb_anafis

# Differentiation
result = symb_anafis.diff("x^3 + 2*x^2 + x", "x")
print(result)  # Output: 3 * x^2 + 4 * x + 1

# Simplification
result = symb_anafis.simplify("sin(x)^2 + cos(x)^2")
print(result)  # Output: 1

# With constants
result = symb_anafis.diff("a * x^2", "x", fixed_vars=["a"])
print(result)  # Output: 2 * a * x

Rust

use symb_anafis::{diff, simplify};

fn main() {
    // Differentiate sin(x) * x with respect to x
    let derivative = diff(
        "sin(x) * x".to_string(),
        "x".to_string(),
        None, // No fixed variables
        None  // No custom functions
    ).unwrap();

    println!("Derivative: {}", derivative);
    // Output: cos(x) * x + sin(x)

    // Simplify an expression
    let simplified = simplify(
        "x^2 + 2*x + 1".to_string(),
        None, // No fixed variables
        None  // No custom functions
    ).unwrap();

    println!("Simplified: {}", simplified);
    // Output: (x + 1)^2
}

Features

Fast Differentiation

  • Supports all standard calculus rules (product, chain, quotient, power)
  • Handles trigonometric, exponential, and logarithmic functions
  • Support for custom functions and implicit differentiation

Powerful Simplification

  • Automatic constant folding
  • Trigonometric identities (Pythagorean, double angle, etc.)
  • Algebraic simplification (factoring, expanding)
  • Fraction cancellation and rationalization

Flexible API

  • Fixed variables (constants that aren't differentiated)
  • Custom function definitions
  • Domain-safety mode to avoid incorrect simplifications (set SYMB_ANAFIS_DOMAIN_SAFETY=true)

Cross-Language Support

  • Native Rust performance with zero-cost abstractions
  • Python bindings via PyO3
  • Consistent API across languages

Configuration

You can configure safety limits using environment variables:

  • SYMB_ANAFIS_MAX_DEPTH: Maximum AST depth (default: 100)
  • SYMB_ANAFIS_MAX_NODES: Maximum AST node count (default: 10000)
  • SYMB_ANAFIS_DOMAIN_SAFETY: Enable domain-safe mode (default: false)
export SYMB_ANAFIS_MAX_DEPTH=200
export SYMB_ANAFIS_MAX_NODES=50000
export SYMB_ANAFIS_DOMAIN_SAFETY=true

Domain-Safe Mode

Domain-safe mode prevents mathematically incorrect simplifications by skipping rules that could alter the domain of expressions. For example:

  • Without domain safety: sqrt(x^2)x (incorrect when x < 0)
  • With domain safety: sqrt(x^2)abs(x) (correct for all real x)

Enable domain-safe mode when you need guaranteed mathematical correctness:

Python

export SYMB_ANAFIS_DOMAIN_SAFETY=true
python -c "import symb_anafis; print(symb_anafis.simplify('sqrt(x^2)'))"
# Output: abs(x)

Rust

use symb_anafis::simplify;

// Set domain safety via environment variable before compilation
// Or use the internal API (not recommended for external use)
fn main() {
    let result = simplify(
        "sqrt(x^2)".to_string(),
        Some(&["x".to_string()]),
        None
    ).unwrap();
    println!("Result: {}", result);  // With SYMB_ANAFIS_DOMAIN_SAFETY=true: abs(x)
}

Examples

Physics: RC Circuit

Python

# Voltage in RC circuit: V(t) = V₀ * exp(-t/(R*C))
voltage = "V0 * exp(-t / (R * C))"
current = symb_anafis.diff(
    voltage, 
    "t", 
    fixed_vars=["V0", "R", "C"]
)
print(current)  # Current: dV/dt

Rust

use symb_anafis::diff;

fn main() {
    let voltage = "V0 * exp(-t / (R * C))".to_string();
    let current = diff(
        voltage,
        "t".to_string(),
        Some(&["V0".to_string(), "R".to_string(), "C".to_string()]),
        None
    ).unwrap();
    println!("Current: {}", current);
}

Statistics: Normal Distribution

Python

# Normal PDF: f(x) = exp(-(x-μ)²/(2σ²)) / √(2πσ²)
pdf = "exp(-(x - mu)^2 / (2 * sigma^2)) / sqrt(2 * pi * sigma^2)"
derivative = symb_anafis.diff(
    pdf,
    "x",
    fixed_vars=["mu", "sigma"]
)
print(derivative)  # Derivative with respect to x

Rust

use symb_anafis::diff;

fn main() {
    let pdf = "exp(-(x - mu)^2 / (2 * sigma^2)) / sqrt(2 * pi * sigma^2)".to_string();
    let derivative = diff(
        pdf,
        "x".to_string(),
        Some(&["mu".to_string(), "sigma".to_string()]),
        None
    ).unwrap();
    println!("Derivative: {}", derivative);
}

Calculus: Chain Rule

Python

# Chain rule: d/dx[sin(cos(tan(x)))]
result = symb_anafis.diff("sin(cos(tan(x)))", "x")
print(result)

Rust

use symb_anafis::diff;

fn main() {
    let result = diff(
        "sin(cos(tan(x)))".to_string(),
        "x".to_string(),
        None,
        None
    ).unwrap();
    println!("Result: {}", result);
}

API Reference

Python API

diff(formula, var, fixed_vars=None, custom_functions=None) -> str

Differentiate a mathematical expression.

Parameters:

  • formula (str): Mathematical expression (e.g., "x^2 + sin(x)")
  • var (str): Variable to differentiate with respect to
  • fixed_vars (list, optional): Variables that are constants
  • custom_functions (list, optional): User-defined function names

Returns: Simplified derivative as a string

Raises: ValueError if parsing/differentiation fails

Note: Set environment variable SYMB_ANAFIS_DOMAIN_SAFETY=true for domain-safe simplification.

simplify(formula, fixed_vars=None, custom_functions=None) -> str

Simplify a mathematical expression.

Parameters:

  • formula (str): Expression to simplify
  • fixed_vars (list, optional): Variables that are constants
  • custom_functions (list, optional): User-defined function names

Returns: Simplified expression as a string

Note: Set environment variable SYMB_ANAFIS_DOMAIN_SAFETY=true for domain-safe simplification.

parse(formula, fixed_vars=None, custom_functions=None) -> str

Parse and normalize an expression.

Parameters:

  • formula (str): Expression to parse
  • fixed_vars (list, optional): Variables that are constants
  • custom_functions (list, optional): User-defined function names

Returns: Normalized expression string

Rust API

diff(formula: String, var: String, fixed_vars: Option<&[String]>, custom_functions: Option<&[String]>) -> Result<String, DiffError>

Differentiate a mathematical expression.

simplify(formula: String, fixed_vars: Option<&[String]>, custom_functions: Option<&[String]>) -> Result<String, DiffError>

Simplify a mathematical expression. Set environment variable SYMB_ANAFIS_DOMAIN_SAFETY=true for domain-safe mode.

parse(formula: String, fixed_vars: Option<&[String]>, custom_functions: Option<&[String]>) -> Result<Expr, DiffError>

Parse and normalize an expression into an AST.

Advanced Usage

Expression Simplification

You can simplify expressions without differentiation:

Python

result = symb_anafis.simplify("sin(x)^2 + cos(x)^2")
print(result)  # Output: 1

Rust

use symb_anafis::simplify;

fn main() {
    let result = simplify(
        "sin(x)^2 + cos(x)^2".to_string(),
        None,
        None
    ).unwrap();
    println!("Simplified: {}", result);  // Output: 1
}

Multi-Character Symbols

For symbols with multiple characters (like "sigma", "alpha", etc.), pass them as fixed variables to ensure they're treated as single symbols:

Python

# This treats "sigma" as one symbol
result = symb_anafis.simplify("(sigma^2)^2", fixed_vars=["sigma"])
print(result)  # Output: sigma^4

Rust

use symb_anafis::simplify;

fn main() {
    let result = simplify(
        "(sigma^2)^2".to_string(),
        Some(&["sigma".to_string()]),
        None
    ).unwrap();
    println!("Simplified: {}", result);  // Output: sigma^4
}

Fixed Variables and Custom Functions

You can define constants (like a, b) and custom functions (like f(x)) that are treated correctly during differentiation.

Python

result = symb_anafis.diff("a * f(x)", "x", fixed_vars=["a"], custom_functions=["f"])
print(result)  # Output: a * ∂_f(x)/∂_x

Rust

use symb_anafis::diff;

fn main() {
    let result = diff(
        "a * f(x)".to_string(),
        "x".to_string(),
        Some(&["a".to_string()]),
        Some(&["f".to_string()])
    ).unwrap();
    println!("Derivative: {}", result);  // Output: a * ∂_f(x)/∂_x
}

Domain-Safe Simplification

Domain-safe mode prevents mathematically incorrect simplifications:

Python

export SYMB_ANAFIS_DOMAIN_SAFETY=true
python -c "import symb_anafis; print(symb_anafis.simplify('sqrt(x^2)'))"
# Output: abs(x)  (correct for all real x)

Rust

use symb_anafis::simplify;

fn main() {
    // Domain safety is controlled by SYMB_ANAFIS_DOMAIN_SAFETY environment variable
    let result = simplify(
        "sqrt(x^2)".to_string(),
        Some(&["x".to_string()]),
        None
    ).unwrap();
    println!("Result: {}", result);  // abs(x) when domain safety is enabled
}

Supported Functions

  • Trigonometric: sin, cos, tan, cot, sec, csc, asin, acos, atan, acot, asec, acsc
  • Hyperbolic: sinh, cosh, tanh, coth, sech, csch, asinh, acosh, atanh, acoth, asech, acsch
  • Exponential/Logarithmic: exp, ln, log, log10, log2
  • Roots: sqrt, cbrt
  • Absolute Value/Sign: abs, sign
  • Special: sinc, erf, erfc, gamma, digamma, trigamma, tetragamma, polygamma, beta, LambertW, besselj, bessely, besseli, besselk

Note: The polygamma(n, x) function provides derivatives for all polygamma functions. Functions with non-elementary derivatives use custom notation.

Expression Syntax

  • Variables: x, y, sigma, etc.
  • Numbers: 1, 3.14, 1e-5, 2.5e3
  • Operations: +, -, *, /, ^ (power)
  • Functions: sin(), cos(), exp(), ln(), sqrt()
  • Constants: pi, e (automatically recognized)
  • Implicit multiplication: 2x = 2*x, (x+1)(x-1) = (x+1)*(x-1)

Comparison with SymPy

Feature SymbAnaFis SymPy
Speed (diff+simplify) ⭐⭐⭐⭐⭐ ⭐⭐⭐
Differentiation ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Simplification ⭐⭐⭐⭐⭐ ⭐⭐⭐
Python Integration ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Symbolic solving ⭐⭐⭐⭐⭐
Maturity Newer Established

When to use SymbAnaFis:

  • You need fast differentiation + simplification
  • Performance is critical
  • You're working with real-world physics/engineering expressions

When to use SymPy:

  • You need symbolic equation solving
  • You need broader symbolic capabilities
  • You prefer pure Python implementation

Building from Source

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Clone repository
git clone https://github.com/CokieMiner/symb_anafis.git
cd symb_anafis

# Build Python bindings
pip install maturin
maturin develop --release

# Build Rust library
cargo build --release

# Run tests
cargo test --release

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Citation

If you use SymbAnaFis in academic work, please cite:

@software{symb_anafis,
  author = {CokieMiner},
  title = {SymbAnaFis: Fast Symbolic Differentiation Library},
  url = {https://github.com/CokieMiner/symb_anafis},
  year = {2025}
}

Resources


Built with ❤️ in Rust for Python 🚀

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

symb_anafis-0.2.5.tar.gz (129.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

symb_anafis-0.2.5-cp314-cp314-manylinux_2_34_x86_64.whl (517.1 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

symb_anafis-0.2.5-cp314-cp314-macosx_11_0_arm64.whl (507.4 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

symb_anafis-0.2.5-cp312-cp312-manylinux_2_34_x86_64.whl (582.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

symb_anafis-0.2.5-cp39-cp39-win_amd64.whl (437.7 kB view details)

Uploaded CPython 3.9Windows x86-64

File details

Details for the file symb_anafis-0.2.5.tar.gz.

File metadata

  • Download URL: symb_anafis-0.2.5.tar.gz
  • Upload date:
  • Size: 129.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.10.2

File hashes

Hashes for symb_anafis-0.2.5.tar.gz
Algorithm Hash digest
SHA256 48b6459c865cc63dcdac7681da2b538e7ae856c03e84d3a045df9dc4f126c419
MD5 015e78d1d97019845f9aa320857c1d27
BLAKE2b-256 095f1fdd376253ce740cda2d860410a337dd6836a83a1a69ed56091947383927

See more details on using hashes here.

File details

Details for the file symb_anafis-0.2.5-cp314-cp314-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for symb_anafis-0.2.5-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 5b825ca795de701de2ad85958e2eb5ff84d278f7b70354e0f3db57d94a18fc85
MD5 8f40cec03413b23b34cd693b59069043
BLAKE2b-256 0a58d102f6d89437cd0d1b362621a223416deb092118af8465e5a98d3697003a

See more details on using hashes here.

File details

Details for the file symb_anafis-0.2.5-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for symb_anafis-0.2.5-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f1eda07c3962d032d6917e89ad2527f5b0921e5786b14e9f69007db9a86d5a32
MD5 dbdfce70e13007f8244a326f9b3722d9
BLAKE2b-256 aba40332e709f9904c63276eb1357de9e96001ded1da1bfb7056ed3497fd8523

See more details on using hashes here.

File details

Details for the file symb_anafis-0.2.5-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for symb_anafis-0.2.5-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 6a5cde5e5cad5a0632762a9e0d48bf3b0b95353e3ff2a45b4233feeeee989223
MD5 e04204ec815f1b95bc0179223b5593d2
BLAKE2b-256 b962b9b5412e0bb2e2b6ffca372e9ef1dfaca51b30ef87ac68cea362093a8c5d

See more details on using hashes here.

File details

Details for the file symb_anafis-0.2.5-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for symb_anafis-0.2.5-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 8b1faaf8320022ed45668a17973a484a9e2e7d1a8272b7f18f2f732a083c36e2
MD5 a07fd13fdfdf99e5ee07a0712633a074
BLAKE2b-256 1a0873ecb8dcbe243f5d97fba18ca96a2683fe29523a6876842fc44c7f6fff7d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page