
Research
/Security News
60 Malicious Ruby Gems Used in Targeted Credential Theft Campaign
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
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.
Ready to revolutionize your mathematical computing workflow?
pip install mathflow
Have Questions? Take a look at the Q&A: Questions & Answers: Addressing Potential Concerns
.n
attribute providing numerical methods without manual lambdification (uses cached lambdified expression when needed).print
attribute (LaTeX, pretty printing, code generation)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
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)])
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.
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
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
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)
# 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()
# 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)")
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
# 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)
MathFlow follows several key principles:
.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?")
...
We welcome contributions! Soon, we will publish a list of documents covering contribution guidelines here. Come back later if you are interested in contributing!
This project is licensed under the MIT License - see the LICENSE file for details.
FAQs
A Pythonic Interface for Symbolic and Numerical Mathematics
We found that mathflow demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A RubyGems malware campaign used 60 malicious packages posing as automation tools to steal credentials from social media and marketing tool users.
Security News
The CNA Scorecard ranks CVE issuers by data completeness, revealing major gaps in patch info and software identifiers across thousands of vulnerabilities.
Research
/Security News
Two npm packages masquerading as WhatsApp developer libraries include a kill switch that deletes all files if the phone number isn’t whitelisted.