Skip to main content

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

rust_poly-0.1.5.tar.gz (8.2 MB view details)

Uploaded Source

Built Distributions

rust_poly-0.1.5-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.whl (557.4 kB view details)

Uploaded PyPy manylinux: glibc 2.5+ x86-64

rust_poly-0.1.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl (557.0 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.5+ x86-64

rust_poly-0.1.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl (557.5 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.5+ x86-64

rust_poly-0.1.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl (556.9 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.5+ x86-64

rust_poly-0.1.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (556.8 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.5+ x86-64

rust_poly-0.1.5-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl (555.0 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.5+ x86-64

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

Hashes for rust_poly-0.1.5.tar.gz
Algorithm Hash digest
SHA256 f18e57fca671f4d15a0a59b50fbe1b065c6a87f5dd31b7b5a26f08f4ab9d003c
MD5 f480542598f07733c14549016dd2e3c2
BLAKE2b-256 675e476564bf7326f505f71ac4845be6438eb0758ca657a7f6c23cf4f5f05ad7

See more details on using hashes here.

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

Hashes for rust_poly-0.1.5-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 af7281625ca5330e6500555830556f94e891c31ab8be4680ba8fb750920788a3
MD5 e144152239b66ba625bcca569ae1054e
BLAKE2b-256 a2d9fbee8825067c6d8466dc53042587f97877b01ecbb9b7bf524b82ee4502d1

See more details on using hashes here.

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

Hashes for rust_poly-0.1.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 66e0e036bdcc89abce563a61ec5393d9e4f9208cd7a81fa1891022ec64a79927
MD5 b799ad62618b543163d56179a77147e3
BLAKE2b-256 501e7f687d155f3ba56149bbc17d96f539f7bdb9e8b60480dadfd3011de92b46

See more details on using hashes here.

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

Hashes for rust_poly-0.1.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 2cd316523643f53ac1593f74467d223bc0611a010eeeb75ef43f120da917d6c9
MD5 99d0175a2fbd4ee8637ce95af51b3ffe
BLAKE2b-256 7f9ba333b4a9f6b0ac704e308909063d213e441c8be1a3469a6ed9c89f133d21

See more details on using hashes here.

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

Hashes for rust_poly-0.1.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 c4df8caf0c0fcec94e35e81ba01879317082616fe7240b0cec17b9800985ae3e
MD5 705d009847a9c89337dfad0dc3660321
BLAKE2b-256 b260378f862c09c58eea18066dfb9329a7daad85b2b4a067ea1b895e3c9d459c

See more details on using hashes here.

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

Hashes for rust_poly-0.1.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 0bb50edb575e01ef36f4b2b2b4172a5e63a18558f11e4aec191adb625b1845f3
MD5 f25fc38c1eb2a210e1f403a8a1e7a86b
BLAKE2b-256 19a9db5a040ae27a6d6be2ff88651d583795323b57d727906e04165925c900ad

See more details on using hashes here.

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

Hashes for rust_poly-0.1.5-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 6f128b66a64a8982343959b602a8a3ce6f44cb6e90ce526ab3b27b57399f3f9e
MD5 b67f785e1cbe0e9215761e478589eaa5
BLAKE2b-256 e6e0f43f604beb8b3d3c79dddf5fc87661f1cf8c1d2b08737a54168f935da9eb

See more details on using hashes here.

Supported by

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