Fast polynomial and rational evaluation library
Project description
Rust Poly
Fast polynomial and rational evaluation for Python written in Rust.
Usage
Basics
>>> from rust_poly import ExpressionTree
We can construct a polynomial with the ExpressionTree
constructor.
>>> poly = ExpressionTree([1, 2, 3])
>>> print(poly)
1 + 2x₁¹ + 3x₁², dtype = i64
ExpressionTree
objects can be called on arrays and broadcast over the last dimension.
>>> poly([2])
array(17)
>>> poly([[1], [2], [3]])
array([ 6, 17, 34])
>>> poly([[[1], [2]], [[3], [4]]])
array([[ 6, 17],
[34, 57]])
The last dimension of the argument must equal the dimension of the expression.
>>> poly([1, 2, 3])
Traceback (most recent call last):
...
ValueError: Incompatible shape for evaluation
ExpressionTree
objects can be composed and are lazily evaluated.
>>> print(poly * poly)
(1 + 2x₁¹ + 3x₁²) * (1 + 2x₁¹ + 3x₁²), dtype = i64
>>> (poly * poly)([2])
array(289)
ExpressionTree
objects can be "expanded".
>>> print((poly * poly).expand())
1 + 4x₁¹ + 10x₁² + 12x₁³ + 9x₁⁴, dtype = i64
ExpressionTree
objects can be scaled, added, subtracted, divided, and multiplied lazily.
>>> p1 = ExpressionTree([1, 2])
>>> print(p1)
1 + 2x₁¹, dtype = i64
>>> p2 = ExpressionTree([3, 4, 5])
>>> print(p2)
3 + 4x₁¹ + 5x₁², dtype = i64
>>> print(5 * p1)
5 * (1 + 2x₁¹), dtype = i64
>>> print(p1 + p2)
(1 + 2x₁¹) + (3 + 4x₁¹ + 5x₁²), dtype = i64
>>> print(p1 - p2)
(1 + 2x₁¹) - (3 + 4x₁¹ + 5x₁²), dtype = i64
>>> print(p1 * p2)
(1 + 2x₁¹) * (3 + 4x₁¹ + 5x₁²), dtype = i64
>>> print(p1 / p2)
(1 + 2x₁¹) / (3 + 4x₁¹ + 5x₁²), dtype = i64
Different data types (float, int, and complex) can be handled.
>>> poly([2.0])
array(17.)
>>> poly([2.0 + 0j])
array(17.+0.j)
>>> floatpoly = ExpressionTree([1.0, 2.0])
>>> print((floatpoly + poly).expand())
2 + 4x₁¹ + 3x₁², dtype = f64
Higher-dimensional polynomials
Polynomials can be defined with many dimensions.
>>> p2d = ExpressionTree([[1, 2], [3, 4]])
>>> print(p2d)
1 + 2x₂¹ + 3x₁¹ + 4x₁¹x₂¹, dtype = i64
>>> p2d.dimension
2
When evaluating higher dimension arrays, the last dimension of the expression to be evaluated must match the dimension of the array.
>>> p2d([1, 2])
array(16)
>>> p2d([[1], [2]])
Traceback (most recent call last):
...
ValueError: Incompatible shape for evaluation
>>> p2d([[1, 2, 3], [2, 3, 4]])
Traceback (most recent call last):
...
ValueError: Incompatible shape for evaluation
Polynomial dimension must match for composition.
>>> p2d + p1
Traceback (most recent call last):
...
ValueError: Incompatible dimensions for composition
Other operations
Differentiation and integration are supported. Integer polynomials are automatically converted to floats with this method.
>>> print(p1.deriv([1]))
deriv(1 + 2x₁¹, [1]), dtype = f64
>>> print(p1.deriv([1]).expand())
2, dtype = f64
>>> print(p1.deriv([0]).expand())
1 + 2x₁¹, dtype = f64
>>> print(p2.deriv([1]))
deriv(3 + 4x₁¹ + 5x₁², [1]), dtype = f64
>>> print(p2.deriv([1]).expand())
4 + 10x₁¹, dtype = f64
>>> print(p1.integ([1]).expand())
1x₁¹ + 1x₁², dtype = f64
>>> print(p1.deriv([-1]).expand())
1x₁¹ + 1x₁², dtype = f64
The syntax for multi-dimensional derivatives and integrals is similar:
>>> print(p2d.deriv([1, 0]).expand())
3 + 4x₂¹, dtype = f64
>>> print(p2d.deriv([0, 1]).expand())
2 + 4x₁¹, dtype = f64
More complex example
Quick example of computing a stiffness matrix:
from rust_poly import ExpressionTree as Polynomial, from_terms
import numpy as np
terms = {"x1": 0, "x2": 1, "x1a": 2, "x2a": 3,
"x1b": 4, "x2b": 5, "x1c": 6, "x2c": 7,
"nu": 8, "none": None}
def get_term(term):
t = [0] * (len(terms) - 1)
if terms[term] is not None:
t[terms[term]] = 1
return tuple(t)
def get_term_array(term):
return np.array(get_term(term))
def get_poly(**kwargs):
return from_terms(
{get_term(key): val for key, val in kwargs.items()}
)
# Stiffness matrix interpolation functions
Na = (get_poly(x2=1, x2b=-1) *get_poly(x1c=1, x1b=-1)
-get_poly(x1=1, x1b=-1) *get_poly(x2c=1, x2b=-1)
) / (get_poly(x2a=1, x2b=-1) *get_poly(x1c=1, x1b=-1)
-get_poly(x1a=1, x1b=-1) *get_poly(x2c=1, x2b=-1))
Nb = (get_poly(x2=1, x2c=-1) *get_poly(x1a=1, x1c=-1)
-get_poly(x1=1, x1c=-1) *get_poly(x2a=1, x2c=-1)
) / (get_poly(x2b=1, x2c=-1) *get_poly(x1a=1, x1c=-1)
-get_poly(x1b=1, x1c=-1) *get_poly(x2a=1, x2c=-1))
Nc = (get_poly(x2=1, x2a=-1) *get_poly(x1b=1, x1a=-1)
-get_poly(x1=1, x1a=-1) *get_poly(x2b=1, x2a=-1)
) / (get_poly(x2c=1, x2a=-1) *get_poly(x1b=1, x1a=-1)
-get_poly(x1c=1, x1a=-1) *get_poly(x2b=1, x2a=-1))
# Strain-displacement matrix
B = np.full((3, 6), Polynomial.zero(len(terms) - 1) / Polynomial.one(len(terms) - 1))
B[0, 0] = Na.deriv(get_term_array('x1'))
B[0, 2] = Nb.deriv(get_term_array('x1'))
B[0, 4] = Nc.deriv(get_term_array('x1'))
B[1, 1] = Na.deriv(get_term_array('x2'))
B[1, 3] = Nb.deriv(get_term_array('x2'))
B[1, 5] = Nc.deriv(get_term_array('x2'))
B[2, 0] = Na.deriv(get_term_array('x2'))
B[2, 1] = Na.deriv(get_term_array('x1'))
B[2, 2] = Nb.deriv(get_term_array('x2'))
B[2, 3] = Nb.deriv(get_term_array('x1'))
B[2, 4] = Nc.deriv(get_term_array('x2'))
B[2, 5] = Nc.deriv(get_term_array('x1'))
# Material constitutive matrix (plane stress)
D = np.full(
(3, 3),
Polynomial.zero(len(terms) - 1) / Polynomial.one(len(terms) - 1)
)
D[0, 0] = D[1, 1] = get_poly(nu=0, none=1)
D[1, 0] = D[0, 1] = get_poly(nu=1)
D[2, 2] = get_poly(nu=-0.5, none=0.5)
D = D / (get_poly(none=1, nu=1) * get_poly(none=1, nu=-1))
# Coordinate Determinant
Det = (
get_poly(x1a=1) * get_poly(x2b=1, x2c=-1)
+ get_poly(x1b=1) * get_poly(x2c=1, x2a=-1)
+ get_poly(x1c=1) * get_poly(x2a=1, x2b=-1)
)
# Compute an abstract representation for the stiffness matrix of a constant
# strain triangular element
K = (B.T @ D @ B) / Det
# Specialize the stiffness matrix for a particular element
coords = np.array([0, -1, 2, 0, 0, 1, 0.25])
indices = np.array([2, 3, 4, 5, 6, 7, 8])
vfunc = np.vectorize(lambda a: a.partial(indices, coords).expand().to_constant())
K_special = vfunc(K)
expected = np.array([
[ 2.5 , 1.25 , -2. , -1.5 , -0.5 , 0.25 ],
[ 1.25 , 4.375, -1. , -0.75 , -0.25 , -3.625],
[-2. , -1. , 4. , 0. , -2. , 1. ],
[-1.5 , -0.75 , 0. , 1.5 , 1.5 , -0.75 ],
[-0.5 , -0.25 , -2. , 1.5 , 2.5 , -1.25 ],
[ 0.25 , -3.625, 1. , -0.75 , -1.25 , 4.375]
]) / (0.9375 * 64)
assert np.allclose(expected, K_special)
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
Built Distributions
File details
Details for the file rust_poly-0.1.5.tar.gz
.
File metadata
- Download URL: rust_poly-0.1.5.tar.gz
- Upload date:
- Size: 8.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f18e57fca671f4d15a0a59b50fbe1b065c6a87f5dd31b7b5a26f08f4ab9d003c |
|
MD5 | f480542598f07733c14549016dd2e3c2 |
|
BLAKE2b-256 | 675e476564bf7326f505f71ac4845be6438eb0758ca657a7f6c23cf4f5f05ad7 |
File details
Details for the file rust_poly-0.1.5-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.whl
.
File metadata
- Download URL: rust_poly-0.1.5-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 557.4 kB
- Tags: PyPy, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | af7281625ca5330e6500555830556f94e891c31ab8be4680ba8fb750920788a3 |
|
MD5 | e144152239b66ba625bcca569ae1054e |
|
BLAKE2b-256 | a2d9fbee8825067c6d8466dc53042587f97877b01ecbb9b7bf524b82ee4502d1 |
File details
Details for the file rust_poly-0.1.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl
.
File metadata
- Download URL: rust_poly-0.1.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 557.0 kB
- Tags: CPython 3.10, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 66e0e036bdcc89abce563a61ec5393d9e4f9208cd7a81fa1891022ec64a79927 |
|
MD5 | b799ad62618b543163d56179a77147e3 |
|
BLAKE2b-256 | 501e7f687d155f3ba56149bbc17d96f539f7bdb9e8b60480dadfd3011de92b46 |
File details
Details for the file rust_poly-0.1.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl
.
File metadata
- Download URL: rust_poly-0.1.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 557.5 kB
- Tags: CPython 3.9, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2cd316523643f53ac1593f74467d223bc0611a010eeeb75ef43f120da917d6c9 |
|
MD5 | 99d0175a2fbd4ee8637ce95af51b3ffe |
|
BLAKE2b-256 | 7f9ba333b4a9f6b0ac704e308909063d213e441c8be1a3469a6ed9c89f133d21 |
File details
Details for the file rust_poly-0.1.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
.
File metadata
- Download URL: rust_poly-0.1.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 556.9 kB
- Tags: CPython 3.8, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c4df8caf0c0fcec94e35e81ba01879317082616fe7240b0cec17b9800985ae3e |
|
MD5 | 705d009847a9c89337dfad0dc3660321 |
|
BLAKE2b-256 | b260378f862c09c58eea18066dfb9329a7daad85b2b4a067ea1b895e3c9d459c |
File details
Details for the file rust_poly-0.1.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
.
File metadata
- Download URL: rust_poly-0.1.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 556.8 kB
- Tags: CPython 3.7m, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0bb50edb575e01ef36f4b2b2b4172a5e63a18558f11e4aec191adb625b1845f3 |
|
MD5 | f25fc38c1eb2a210e1f403a8a1e7a86b |
|
BLAKE2b-256 | 19a9db5a040ae27a6d6be2ff88651d583795323b57d727906e04165925c900ad |
File details
Details for the file rust_poly-0.1.5-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
.
File metadata
- Download URL: rust_poly-0.1.5-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 555.0 kB
- Tags: CPython 3.6m, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.8.0 pkginfo/1.8.2 readme-renderer/32.0 requests/2.27.1 requests-toolbelt/0.9.1 urllib3/1.26.8 tqdm/4.62.3 importlib-metadata/4.10.1 keyring/23.5.0 rfc3986/2.0.0 colorama/0.4.4 CPython/3.9.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6f128b66a64a8982343959b602a8a3ce6f44cb6e90ce526ab3b27b57399f3f9e |
|
MD5 | b67f785e1cbe0e9215761e478589eaa5 |
|
BLAKE2b-256 | e6e0f43f604beb8b3d3c79dddf5fc87661f1cf8c1d2b08737a54168f935da9eb |