Skip to main content

SimpliPy:
Efficient Simplification of Mathematical Expressions

PyPI version PyPI license Documentation Status

pytest quality checks CodeQL Advanced

Publications

  • Saegert & Köthe 2026, Breaking the Simplification Bottleneck in Amortized Neural Symbolic Regression (preprint, under review) https://arxiv.org/abs/2602.08885

Usage

pip install simplipy

The compiled Rust extension (simplipy._core) is required: the inline phase (simplify, conversions, validation) runs on it exclusively, and there is no pure-Python fallback. Prebuilt wheels are published for Linux (x86_64/aarch64), macOS (x86_64/arm64) and Windows (x64) on CPython ≥ 3.11, so pip install simplipy does not compile anything for most users. Installing from the source distribution (an unsupported platform, or --no-binary) requires a Rust toolchain (rustup, MSRV 1.83). If the extension is missing at runtime, constructing an engine raises ImportError.

import simplipy as sp

engine = sp.SimpliPyEngine.load("acj-4-3", install=True)   # a published ruleset artifact

# Simplify prefix expressions
engine.simplify(('/', '<constant>', '*', '/', '*', 'x3', '<constant>', 'x3', 'log', 'x3'))
# > ('<mul>', '<constant>', '<div>', 'log', 'x3', '</mul>')

# Simplify infix expressions
engine.simplify('x3 * sin(<constant> + 1) / (x3 * x3)')
# > '<constant>/x3'

Token input returns the engine's native tagged form by default (n-ary +/* bags are delimited: <add> ... </add>, <mul> ... </mul>; tagged output is accepted back as input). The form parameter selects a different projection of the same canonical answer:

expr = ('/', '<constant>', '*', '/', '*', 'x3', '<constant>', 'x3', 'log', 'x3')

engine.simplify(expr, form='infix')      # the pretty rendering (a str)
# > '<constant>/log(x3)'

engine.simplify(expr, form='explicit')   # binary prefix -- what is_valid / prefix_to_infix read
# > ('/', '<constant>', 'log', 'x3')

Normalization

The root-exported normalize_skeleton, normalize_expression, and normalize_variable_token helpers (also available as simplipy.normalization) canonicalize a prefix token sequence so that two expressions that are "the same" up to variable renaming / constant values compare equal. They are pure-string helpers with no engine state, so consumers such as holdout matching and symbolic-recovery scoring share identical behavior by construction.

import simplipy as sp

# Skeleton form: variables -> x{n}, numeric literals -> <constant>
sp.normalize_skeleton(['+', 'v1', '2.5'])
# > ['+', 'x1', '<constant>']

# Expression form: variables canonicalized, numeric literals kept intact
sp.normalize_expression(['+', 'V1', '2.5'])
# > ['+', 'x1', '2.5']

# Classify / canonicalize a single token -> (normalized_token, is_variable)
sp.normalize_variable_token('X3')
# > ('x3', True)
sp.normalize_variable_token('sin')
# > ('sin', False)

More examples can be found in the documentation.

Performance

As of 0.6.0 the simplify hot path defers match-time certificates to completed matches (memoized generationally, never stopping memoization), memoizes whole fixpoint passes and rule-normal subtrees, and runs on interned token ids (~20× fewer allocations per call) — all at byte-identical outputs. On a 65,536-expression training-prior benchmark (measured at 0.11.0), large certificate-bearing rulesets simplify ~59× faster than 0.5.0 and certificate-free rulesets ~2.3× faster; see the CHANGELOG for details. Since 0.7.0 there is a single compiled engine line; the published ruleset artifacts (acj-2-1, acj-3-2, acj-4-3, …) are the distinguishing factor between engines. Rule application always considers every pattern in the loaded artifact (the former max_pattern_length knob was removed in 0.10.0). (To reproduce the historical dev_7-3 / v23.0-era behavior byte-for-byte, install simplipy<=0.6.0.)

Simplification time and ratio ECDFs: SimpliPy 0.11.0 vs SymPy across three axes (mined rulesets, safe vs aggressive, search budget) on 64k Lample-Charton expressions from the Flash-ANSR v23.0 prior

Empirical Cumulative Distribution Functions (ECDFs) of simplification wall-clock time (top row) and simplification ratio |simp| / |orig| in prefix tokens (bottom row, inset: zoom on the low-ratio tail), over 65,536 randomly generated Lample-Charton expressions sampled from the Flash-ANSR v23.0 training prior (0 to 17 unique variables, 1 to 35 symbols [Saegert & Köthe 2026]). Three axes vary SimpliPy (green) while SymPy [Meurer et al. 2017] (orange ratio=None / red ratio=1) is the fixed reference: Mined Rulesets — the 2-1/3-2/4-3 ruleset artifacts, every pattern active (darker = larger); Safe vs Aggressive4-3 in the deployed SOUND mode vs the training-only LOSSY mode; Search Budget4-3 SOUND at node budgets 1 to 48. SimpliPy is timed per call (perf_counter, gc off); SymPy is given each <constant> as a free symbol and simplified symbolically inside a per-expression worker with a 1 s timeout, then scored by its native prefix length; SymPy's workers run 24-wide while SimpliPy is timed single-threaded. Expressions SymPy does not finish inside its budget are scored as what they are — infinite time, ratio 1 (not simplified) — and stay in the denominator, so its time curve plateaus at the fraction it completed and its ratio curve carries a step at exactly 1; renormalising over only its successes would inflate its low-ratio tail. The measured quantities are the two ECDFs; the plot, not this caption, reports what they show.

Development

Setup

To set up the development environment, run the following commands:

pip install -e .[dev]
pre-commit install

Tests

Test the package with pytest:

pytest tests --cov src --cov-report html

or to skip integration tests,

pytest tests --cov src --cov-report html -m "not integration"

Citation

@misc{saegert2026breakingsimplificationbottleneckamortized,
  title   = {Breaking the Simplification Bottleneck in Amortized Neural Symbolic Regression},
  author  = {Paul Saegert and Ullrich Köthe},
  year    = {2026},
  eprint  = {2602.08885},
  archivePrefix =  {arXiv},
  primaryClass  = {cs.LG},
  url     = {https://arxiv.org/abs/2602.08885},
}

% Optionally
@software{simplipy-2025,
    author = {Paul Saegert},
    title = {Efficient Simplification of Mathematical Expressions},
    year = 2026,
    publisher = {GitHub},
    version = {0.12.0},
    url = {https://github.com/psaegert/simplipy}
}

Download files

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

Source Distribution

simplipy-0.12.0.tar.gz (3.0 MB view details)

Uploaded Source

Built Distributions

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

simplipy-0.12.0-cp311-abi3-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.11+Windows x86-64

simplipy-0.12.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

simplipy-0.12.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

simplipy-0.12.0-cp311-abi3-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

simplipy-0.12.0-cp311-abi3-macosx_10_12_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file simplipy-0.12.0.tar.gz.

File metadata

  • Download URL: simplipy-0.12.0.tar.gz
  • Upload date:
  • Size: 3.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for simplipy-0.12.0.tar.gz
Algorithm Hash digest
SHA256 fcc848355634bfe408f170faec7e0b7c246c34360be334eaaef516714bf7e820
MD5 6f36989708007ca22d5c963259ec3da3
BLAKE2b-256 037078bca289dc94b621a47bee810d5c42a4a9dbe715890027e1bf27df6e8ac9

See more details on using hashes here.

Provenance

The following attestation bundles were made for simplipy-0.12.0.tar.gz:

Publisher: publish.yml on psaegert/simplipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file simplipy-0.12.0-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: simplipy-0.12.0-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for simplipy-0.12.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 3f385866e26482ce82ca9a9ebcc4a00c3d8b4915412b8721a25ea3aa305c075a
MD5 826926159f41bdec2e65697213c3609a
BLAKE2b-256 3609fd26b47d866a56bd29e6ec0fe1049954401cdfe8e052fc46f2b8b67285e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for simplipy-0.12.0-cp311-abi3-win_amd64.whl:

Publisher: publish.yml on psaegert/simplipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file simplipy-0.12.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simplipy-0.12.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c795c4f1b628425fecdcb74a549ca8c7015d277b81510afe7c0fc352fd13157f
MD5 6712d9366b78a867164a73ccb9948d6a
BLAKE2b-256 580c8810e459d50208da837567c395254ff7719ad40346ab96f3c7b026e4e72f

See more details on using hashes here.

Provenance

The following attestation bundles were made for simplipy-0.12.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on psaegert/simplipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file simplipy-0.12.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for simplipy-0.12.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 14c2f0aaa423cef1f95189c10a8136ac7ce80e84df81293dc1f939b2283c796a
MD5 8584e575f2aaea983b186db136e1ed88
BLAKE2b-256 f37ddfb4c581b4b3331b198be46d932b47df38a871009ece5a6e7c82f28a87e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for simplipy-0.12.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on psaegert/simplipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file simplipy-0.12.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for simplipy-0.12.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 14949efff1ae568fbcb9fe3a8c024b35cc6940d670a505b605e73e3f49adf4e0
MD5 cfc6a529f6e747ce361b59f3c4c3866e
BLAKE2b-256 207dd1b333fc42d66e8dcf6a1bd279c25120e59eac683d6b044c0cfb671ef435

See more details on using hashes here.

Provenance

The following attestation bundles were made for simplipy-0.12.0-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on psaegert/simplipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file simplipy-0.12.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for simplipy-0.12.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 e3162ecb059a06cac5dc7f1351d97fd4d47febef1644d884674fea0ee1924a5c
MD5 9807d72e6575fa2fd80304333018d2a1
BLAKE2b-256 ff87e79d59e7d4994398fb376a0556ca08f5dce2f7774077148d05984d7e2405

See more details on using hashes here.

Provenance

The following attestation bundles were made for simplipy-0.12.0-cp311-abi3-macosx_10_12_x86_64.whl:

Publisher: publish.yml on psaegert/simplipy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.14.6

6 files

0.14.5

6 files

0.14.4

6 files

0.14.2

6 files

0.14.1

6 files

0.14.0

6 files

0.13.1

6 files

0.13.0

6 files

This release

0.12.0 This release

6 files

0.11.0

6 files

0.10.1

6 files

0.10.0

6 files

0.9.1

6 files

0.9.0

6 files

0.8.0

6 files

0.7.1

6 files

0.7.0

6 files

0.4.2

6 files

0.4.1

6 files

0.4.0

6 files

0.3.1

6 files

0.3.0

6 files

0.2.15

2 files

0.2.14

2 files

0.2.13

2 files

0.2.12

2 files

0.2.11

2 files

0.2.10

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

0.2.4

2 files

0.2.3

2 files

0.2.2

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page