Skip to main content

A Pythonic Interface for Symbolic and Numerical Mathematics

Project description

logo

MathFlow ๐Ÿงฎ

A Pythonic Interface for Symbolic and Numerical Mathematics

MathFlow bridges the gap between symbolic mathematics (SymPy) and numerical computations (NumPy/SciPy), offering a unified interface that maintains mathematical rigor while providing practical tools for real-world problems.

Static Badge License: MIT

Ready to revolutionize your mathematical computing workflow?

pip install mathflow

Have Questions? Take a look at the Q&A: Questions & Answers: Addressing Potential Concerns

โœจ Key Features

  • ๐Ÿ”’ Operative Closure: Mathematical operations return new Expression objects by default, maintaining functional programming principles
  • โšก Mutability Control: Choose between immutable (default) and mutable expressions for different workflows
  • ๐Ÿ”— Seamless Numerical Integration: Every symbolic expression has a .n attribute providing numerical methods without manual lambdification (uses cached lambdified expression when needed)
  • ๐ŸŽจ Enhanced Printing: Flexible output formatting through the .print attribute (LaTeX, pretty printing, code generation)
  • ๐Ÿ“ก Signal System: Qt-like signals for tracking expression mutations and clones, enabling reactive programming
  • ๐Ÿ”„ Automatic Type Conversions: Seamlessly and automatically converts between internal Poly and Expr representations based on context
  • ๐Ÿ“ฆ Lightweight: ~0.5 MB itself, ~100 MB including dependencies
  • ๐Ÿงฉ Fully backward compatible: Seamlessly integrate SymPy and MathFlow in the same script. All methods that work on SymPy Expr or Poly objects work on MathFlow objects
  • ๐Ÿ” Exploratory: Full IDE support, enabling easy tool finding and minimizing the learning curve.

๐Ÿš€ Quick Start

from mathflow import Expression, Polynomial, Rational

# Create expressions naturally
f = Expression("2x^2 + 3x + \frac{1}{2}")  # latex is automatically parsed
g = Expression("sin(x) + cos(x)")

# Automatic operative closure - operations return new objects of the same type
h = f + g  # f and g remain unchanged
hprime = h.diff()  # hprime is still an Expression object

# Numerical evaluation made easy
result = f(2.5)  # Numerically evaluate at x = 2.5

# Use the .n attribute to access fast numerical methods
numerical_roots = f.n.all_roots()
# Call f's n-prefixed methods to use variable precision numerical methods
precise_roots = f.nsolve_all(prec=50)  # 50 digits of accuracy

# quick and easy printing
f.print()
f.print('latex')
f.print('mathematica_code')
# or
print(f.print.latex())    # LaTeX output
print(f.print.ccode())    # c code output

๐ŸŽฏ Numerical Computing

MathFlow excels at bridging symbolic and numerical mathematics:

f = Expression("x^3 - 2x^2 + x - 1")

# Root finding
all_roots = f.n.all_roots(bounds=(-5, 5))
specific_root = f.nsolve_all(bounds=(-5, 5), prec=50)  # High-precision solve

# Numerical calculus
derivative_func = f.n.derivative_lambda(df_order=2)  # 2nd derivative numerical function  
integral_result = f.n.integrate(-1, 1)               # Definite integral  

# Optimization
minimum = f.n.minimize(bounds=[(-2, 2)])

๐Ÿ“š Core Classes

graph BT
    %% Visual hierarchy with correct arrow semantics
    sympy.Expr
    sympy.Poly
    BaseExpression
    Expression
    Polynomial
    Rational
    Function
    
    %% Arrows still point child โ†’ parent
    BaseExpression -.-> sympy.Expr
    BaseExpression -.-> sympy.Poly
    Expression --> n
    n --> |lambdified numerical representation| A["f(x)"]
    n -.-> scipy.numerical_methods
    Expression --> BaseExpression
    Polynomial --> Expression
    Rational --> Expression
    Function --> |Only an Alias| Expression

Diagram Notes

  • Dotted arrows mean "proxy to".
  • Additional methods are not shown, only the core structure.

Expression

The primary class for general symbolic expressions with numerical and printing capabilities.

# Create from string with natural notation
expr = Expression("2x^2 + ln(|x-1|)")

# Or from SymPy objects
from sympy import sin, cos
expr = Expression(sin(x) + cos(x))

# Symbolic operations
derivative = expr.diff(x)
expanded = expr.expand()

# Numerical methods via .n attribute
roots = expr.n.all_roots(bounds=(-10, 10))
integral = expr.n.quad(0, 1)  # Numerical integration

Polynomial

Specialized Expression subclass with polynomial-specific functionality.

# Create from coefficients (ascending order by default)
poly = Polynomial.from_coeffs([1, 2, 3])  # 1 + 2x + 3xยฒ

# Create from roots
poly = Polynomial.from_roots([1, 2, 3])   # (x-1)(x-2)(x-3)  

# Access polynomial-specific methods
coeffs = poly.all_coeffs()
degree = poly.degree()
roots = poly.n.all_poly_roots()  # Optimized polynomial root finding

Rational

For rational functions (quotients of polynomials).

# Create from numerator and denominator coefficients  
rational = Rational.from_coeffs([1, 2], [1, 1, 1])  # (1 + 2x)/(1 + x + xยฒ)  
  
# Access numerator and denominator as Expression objects  
num = rational.numerator  
den = rational.denominator  
  
# Partial fraction decomposition
poles = den.n.all_roots()  # numerically find the poles.
pf = rational.partial_fractions(x)

๐Ÿ”ง Advanced Features

Mutability Control

# Immutable (default)
f = Expression("x^2")
g = f + 1  # f unchanged, g is new Expression object

# Mutable Mode (f is modified in-place)
f = Expression("(x-1)^2", mutable=True)
f += 1
f.expand()

Flexible String Parsing

# Natural mathematical notation
expr = Expression("2x^2 + ln(|x-1|)")

# LaTeX input support
expr = Expression(r"\frac{x^2+1}{x-1}")

# Implicit multiplication
expr = Expression("2x sin(x)")

Signal System for Reactive Programming

def on_change(expr):  # runs whenever an operation changes f
    print(f"Expression changed to: {expr}")  
f = Expression("x^2")  
f.on_self_mutated.connect(on_change)  
f.on_self_cloned.connect(on_change)
f += 1  # on_change() is called

Padรฉ Approximations (Useful in Engineering Applications)

# High-quality Padรฉ approximants for function approximation
f = Expression("exp(x)")
pade_approx = f.pade(m=3, n=3, x0=0)  # [3/3] Padรฉ approximant around x=0
  
# Multiple backends available (returns Expression by default, but you can change return type)
pade_fast = f.pade(3, 3, backend='mpmath')      # Fast numerical
pade_exact = f.pade(3, 3, backend='symbolic')   # Exact symbolic
pade_verbose = f.pade(3, 3, backend='verbose')  # Educational output

When backend='verbose', each step is displayed as the Padรฉ approximation is computed.

f = Expression("sqrt(x)")
p = f.pade(2, 2, x0=1, backend='verbose')

For example, the above displays this:

Step 1. Create rational function with numerator P and denominator Q, each with unknown coefficients:
(a0 + a1*h + a2*h^2)/(1 + b1*h + b2*h^2)

Step 2. Equate the rational function to the taylor series A so that the unknown coefficients may be solved:
(a0 + a1*h + a2*h^2)/(1 + b1*h + b2*h^2)  =  1 + 1/2*h + -1/8*h^2 + 1/16*h^3 + -5/128*h^4

Step 3. Multiply the rhs by the denominator of the lhs to get the equation in the form P = QA:
a0 + a1*h + a2*h^2  =  (1 + b1*h + b2*h^2) (1 + 1/2*h + -1/8*h^2 + 1/16*h^3 + -5/128*h^4)

Step 4. Expand the RHS by performing discrete convolution on the coefficient vectors of Q and A (using a table):
	Q's coeffs = [1, b1, b2]
	A's coeffs = [1, 1/2, -1/8, 1/16, -5/128]
โ•ญโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚    โ”‚ 1   โ”‚ 1/2    โ”‚ -1/8      โ”‚ 1/16    โ”‚ -5/128      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1  โ”‚ 1   โ”‚ 1*1/2  โ”‚ 1*(-1/8)  โ”‚ 1*1/16  โ”‚ 1*(-5/128)  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ b1 โ”‚ b1  โ”‚ b1*1/2 โ”‚ b1*(-1/8) โ”‚ b1*1/16 โ”‚ b1*(-5/128) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ b2 โ”‚ b2  โ”‚ b2*1/2 โ”‚ b2*(-1/8) โ”‚ b2*1/16 โ”‚ b2*(-5/128) โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Step 5. Get the sum of the anti-diagonals from the above table to form the new coeffs (only as many terms as unknown coeffs we need to solve for, in this case 5):
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ Term   โ”‚ Coeff                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ h^0    โ”‚ 1                    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ h^1    โ”‚ b1 + 1/2             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ h^2    โ”‚ b1/2 + b2 - 1/8      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ h^3    โ”‚ -b1/8 + b2/2 + 1/16  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ h^4    โ”‚ b1/16 - b2/8 - 5/128 โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Step 6. Use these coefficients to setup a system of equations:
a0 = 1
a1 = b1 + 1/2
a2 = b1/2 + b2 - 1/8
 0 = -b1/8 + b2/2 + 1/16
 0 = b1/16 - b2/8 - 5/128

Step 7. Solving the above system yields:
a0 = 1
a1 = 5/4
a2 = 5/16
b1 = 3/4
b2 = 1/16

Step 8. Substituting these values back into the original rational function yields:
(1 + 5/4*h + 5/16*h^2)/(1 + 3/4*h + 1/16*h^2)

Step 9. `h` may be substituted for the original (x-c), and then expanded. `c` is the point at which both the Taylor series and the Padรฉ approximation are centered at:
(1 + 5/4*(x-c) + 5/16*(x-c)^2)/(1 + 3/4*(x-c) + 1/16*(x-c)^2)

๐Ÿ—๏ธ Design Philosophy

MathFlow follows several key principles:

  1. Intuitive API: Mathematical operations should feel natural in Python, providing an "exploratory" experience
  2. Performance: Automatic optimizations (Horner's method, efficient algorithms, automatic numerical computing when needed)
  3. Flexibility: Support both functional and imperative programming styles
  4. Extensibility: Easy integration with other mathematical libraries
  5. Type Safety: Comprehensive type and method hints for full IDE support

๐Ÿš€ Next Steps & Our Vision

  • Provide a better testing suite to ensure all edge cases are taken care of
  • Integrate AI by introducing an .ai() method that calls a local instance of Mathฮฃtral and Project Numina models over ollama. It would be given context of both the expressions structure and its mathematical properties. One could also use it construct expressions using natural language.

AI Integration Example

>>> f = Expression("A polynomial with the first five prime numbers as coefficients")
>>> f.ai("Have you seen a polynomial with such properties before?")
...
>>> fp = f.diff()
>>> fp.ai("How have the coefficients changed?")
...

๐Ÿค Contributing

We welcome contributions! Soon, we will publish a list of documents covering contribution guidelines here. Come back later if you are interested in contributing!

๐Ÿ“‹ Dependencies

  • SymPy: Symbolic mathematics engine
    • mpmath: High-precision arithmetic
  • SciPy: Advanced numerical algorithms
    • NumPy: Numerical array operations
  • tabulate: Pretty table printing (for verbose modes)

๐Ÿ“„ License (MIT)

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

๐Ÿ™ Acknowledgments

  • Built on the excellent SymPy symbolic mathematics library
  • Numerical computing powered by NumPy and SciPy
  • High-precision arithmetic via mpmath

[^1]:

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

mathflow-0.1.4.tar.gz (107.5 kB view details)

Uploaded Source

Built Distribution

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

mathflow-0.1.4-py3-none-any.whl (108.6 kB view details)

Uploaded Python 3

File details

Details for the file mathflow-0.1.4.tar.gz.

File metadata

  • Download URL: mathflow-0.1.4.tar.gz
  • Upload date:
  • Size: 107.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for mathflow-0.1.4.tar.gz
Algorithm Hash digest
SHA256 9823b34535168f3b6bf122e54ddbd156b7f01514ecf66312222479b9a25f4b42
MD5 277f7741d5a27e92bfd7f4565426431f
BLAKE2b-256 5b7d0398544f46279ae82ae93fba3c44b9d3d741a9ad7b8e364263522d724b9a

See more details on using hashes here.

File details

Details for the file mathflow-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: mathflow-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 108.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for mathflow-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 83b3dc5f8d438af1b3aa1f706170b39ae5b4c058385ba7bf810339f8994c0d77
MD5 e45b8bc6275329c60662246659dcf9da
BLAKE2b-256 276a9bfd24a57e4f9d6f981d580b22bc99dafb773a899dd7d4093027be98f4bf

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