Skip to main content

MathJSON Solver

PyPI PyPI Downloads Python 3.7+

Heads up: Version 2 introduces a breaking change (see CHANGELOG.md) as part of steering back towards greater compatibility with CortexJS MathJSON: Log is now log base 10 instead of natural log. Stuck on pre-2.0.0 expressions but want the functions added in 2.x? Pass legacy_v1=True to create_solver() (see Migrating from 1.x) instead of hand-migrating every expression. Bugfix releases for the 1.x line also continue on the 1.x branch.

A reliable Python library for numerically evaluating mathematical expressions in MathJSON format. Perfect for applications that need to safely execute user-provided formulas, calculate dynamic equations, or process mathematical data.

What is MathJSON? MathJSON represents mathematical expressions as JSON arrays, like ["Add", 1, 2, 3] for 1+2+3. This format is safe, structured, and easy to generate programmatically.

Table of Contents

Installation

pip install mathjson-solver

Requirements: Python 3.10+

Optional:

  • pip install mathjson-solver[integration] (installs numpy; only required for TrapezoidalIntegrate)
  • pip install mathjson-solver[regex] (installs google-re2; only required for RegExp/IsMatch/StringMatch/StringMatchAll)

Quick Start

from mathjson_solver import create_solver, MathJSONException

# Define variables and create solver
parameters = {"x": 2, "y": 3}
solver = create_solver(parameters)

# Evaluate expressions
basic_math = solver(["Add", "x", "y", 4])
print(basic_math)  # 9 (because 2+3+4=9)

# More complex expressions
result = solver(["Multiply", ["Add", "x", 1], ["Subtract", "y", 1]])
print(result)  # 6 (because (2+1) * (3-1) = 6)

# Handle errors gracefully
try:
    solver(["Divide", 1, 0])
except MathJSONException as e:
    print(f"Math error: {e}")
    # Math error: Problem in Divide. ['Divide', 1, 0]. division by zero

Think Functional: MathJSON Solver embraces functional programming principles. Instead of writing loops and modifying variables, you compose expressions that transform data. Functions like Map, Reduce, and Filter let you process arrays elegantly, while immutable operations ensure predictable, side-effect-free calculations. Don't worry if you're new to functional programming — the examples will guide you naturally into this powerful paradigm.

# Functional approach: transform data with expressions
solver(["Map", ["Array", 1, 2, 3, 4], ["Multiply"], 2])  # [2, 4, 6, 8]
solver(["Reduce", ["Array", 1, 2, 3, 4], 0, ["Add", "acc", "item"],
        ["Variable", "acc"], ["Variable", "item"], ["Variable", "i"]])  # 10

# CortexJS-style forms also work: a lambda via Function, and a 2-argument Reduce
solver(["Map", ["Array", 1, 2, 3, 4], ["Function", ["Multiply", "_", 2]]])  # [2, 4, 6, 8]
solver(["Reduce", ["Array", 1, 2, 3, 4], ["Add"]])                          # 10

Migrating from 1.x

Version 2.0.0's only breaking change is Log: pre-2.0.0 it was always natural log, ["Log", x] == math.log(x). From 2.0.0 on it matches CortexJS["Log", x] is log base 10, ["Log", x, b] is log base b — and natural log moved to Ln.

If you have existing expressions built for 1.x and don't want to hand-edit every Log node just to pick up functions added in 2.x (Product, the CortexJS forms of If/Map/Filter/Reduce, the new aliases, etc.), pass legacy_v1=True when creating the solver. It rewrites every ["Log", x] to ["Ln", x] before evaluating, so old expressions keep producing the same results without modification:

solver = create_solver(parameters, legacy_v1=True)
solver(["Log", 8])  # 2.0794... (natural log, matching pre-2.0.0 behavior)

You can also run the rewrite yourself and inspect or store the translated expression:

from mathjson_solver import translate_v1_mathjson

translate_v1_mathjson(["Add", ["Log", 8], 1])  # ["Add", ["Ln", 8], 1]

legacy_v1=True only affects Log. Every other 1.x expression already evaluates identically on 2.x without any translation.

Supported Operations

The library supports a comprehensive set of mathematical operations:

  • Arithmetic: Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round, Floor, Ceil
  • Trigonometry: Sin, Cos, Tan, Arcsin, Arccos, Arctan, Arctan2, Cot, Sec, Csc (+ inverses), Sinh, Cosh, Tanh, Coth, Sech, Csch (+ inverses), Hypot, Sinc
  • Logarithms: Log (base 10, or base b), Log2/Lb, Log10/Lg, Ln (natural log), LogOnePlus, Exp
  • Comparison: Equal, StrictEqual, IdenticallyEqual, NotEqual, Greater, GreaterEqual, Less, LessEqual, Congruent
  • Logic & Sets: Any, All, Not, And, Or, Xor, Nand, Nor, Implies, Equivalent, In/Element, NotIn/NotElement, ContainsAnyOf, ContainsAllOf, ContainsNoneOf, bare True/False literals, Union, Intersection, SetMinus, SymmetricDifference (over arrays - no dedicated Set type)
  • Statistics: Average/Mean, Max, Min (both list and variadic forms), Median, Mode, Variance, StandardDeviation, PopulationVariance, PopulationStandardDeviation, Quartiles, InterquartileRange, Covariance, Correlation, Length/Count
  • Functional Programming: Map/StrictMap, Reduce, Filter, Product (all also accept CortexJS calling conventions, including Function lambdas)
  • Arrays: Array/List creation, GenerateRange, Range, AtIndex, At, Slice, Appended/Append, First, Second, Third, Last, Rest, Most, Reverse, Sort, Unique, Dedup, Join, Zip, IsEmpty, CumulativeSum, CumulativeProduct, Take, Drop, TakeWhile, DropWhile, Contains, IndexOf, IndexWhere, Find, CountIf, Position, RotateLeft, RotateRight, MaxBy, MinBy, ArgMax, ArgMin, Ordering, FlatMap, Scan, Differences, Fold, Insert, DeleteAt, ReplaceAt, Partition, Chunk, GroupBy, ChunkBy, Tally
  • Control Flow: If statements (Python pair form and CortexJS flat form), Switch/StrictSwitch (value-equality case dispatch), Which (CortexJS flat condition/value chain), Constants definition
  • Type Conversion: Int, Float, Str, IsDefined
  • Strings: String, StringJoin, ToUpperCase, ToLowerCase, CaseFold, Trim, TrimStart, TrimEnd, StringSplit, StringReplace, StringCompare, StringRepeat, PadStart, PadEnd, Characters/GraphemeClusters, Utf8, Utf16, UnicodeScalars, StringFrom, IntegerString, DigitsFrom, NumberFrom
  • Pattern Matching (requires the optional regex extra, pip install mathjson-solver[regex]): RegExp, IsMatch, StringMatch, StringMatchAll — backed by RE2 rather than Python's re, for a hard guarantee against catastrophic backtracking (no backreferences/lookaround, as a deliberate trade-off for that guarantee)
  • Date/Time: Strptime, Strftime, Today, Now, TimeDelta functions (Weeks, Days, Hours, Minutes)
  • Number Theory: Chop, Mod, Clamp, GCD, LCM, Factorial, Binomial, IsPrime, Erf, Erfc, Rational, Numerator, Denominator, MachineEpsilon, CatalanConstant, EulerGamma
  • Integration (requires the optional integration extra, pip install mathjson-solver[integration]): TrapezoidalIntegrate. Also in this group but with no extra dependency: Interp, FindIntervalIndex, Variable references
  • Advanced: HasMatchingSublist for pattern matching
  • Constants: Pi, Degrees, ExponentialE, GoldenRatio

View complete documentation with examples →

Error Handling

MathJSON Solver raises MathJSONException for invalid expressions or mathematical errors:

from mathjson_solver import create_solver, MathJSONException

solver = create_solver({})

# Handle specific math errors
try:
    result = solver(["Sqrt", -1])  # Invalid: square root of negative
except MathJSONException as e:
    print(f"Cannot evaluate: {e}")

# Handle malformed expressions
try:
    result = solver(["UnknownFunction", 1, 2])
except MathJSONException as e:
    print(f"Unsupported operation: {e}")

Use Cases

  • Dynamic Formulas: Let users create custom calculations in web applications
  • Scientific Computing: Evaluate mathematical models with variable parameters
  • Business Logic: Process complex pricing rules or scoring algorithms
  • Data Processing: Apply mathematical transformations to datasets
  • Health Applications: Calculate medical scores, dosages, or risk assessments

Testing

Install development dependencies and run tests:

# Install pytest if not already installed
pip install pytest

# Run tests from project directory
pytest

# Run with coverage
pytest --cov=mathjson_solver

Community

Contributing

We welcome contributions! Please feel free to:

  • Report bugs or request features via GitHub Issues
  • Submit pull requests with improvements

Related Projects

We also created londec — evaluate tree-structured conditions against an ordered history of events. It uses mathjson-solver internally.

License

View license information

References

This library implements the MathJSON format as defined by the CortexJS Compute Engine. Since 2.0.0, mathjson-solver has been steering towards greater compatibility with CortexJS's calling conventions and function set — while remaining an independent Python implementation, not a port or dependency of CortexJS.

Scope: mathjson-solver targets compatibility with CortexJS's array-form calling conventions and standard function names — not the full Compute Engine, which is a symbolic CAS.


Made with ❤️ by Longenesis

Download files

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

Source Distribution

mathjson_solver-2.2.1.tar.gz (75.2 kB view details)

Uploaded Source

Built Distribution

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

mathjson_solver-2.2.1-py3-none-any.whl (28.6 kB view details)

Uploaded Python 3

File details

Details for the file mathjson_solver-2.2.1.tar.gz.

File metadata

  • Download URL: mathjson_solver-2.2.1.tar.gz
  • Upload date:
  • Size: 75.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.4

File hashes

Hashes for mathjson_solver-2.2.1.tar.gz
Algorithm Hash digest
SHA256 96f52f45b952b6bf7cc94424ffd9bc5dd2eca0e0b2c9bb01f7af3036b7af08de
MD5 82c0110f2150f1b1692b0dad7bbc855d
BLAKE2b-256 fe0f34ff7447fa8aabe3c2f8dd747dede91241335e9d6be73f4ad86f958edaa0

See more details on using hashes here.

File details

Details for the file mathjson_solver-2.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for mathjson_solver-2.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f3f3d60d17209bee2550814451aa859f75309a73e33ee50c74c010c28d02c79f
MD5 18926db514d9188961a3cf98eed97b4f
BLAKE2b-256 8e5921fa11ac1619512e2b468b2973a165064bd8097ddc8a5e6011915c734086

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.2.1 This release

2 files

2.2.0

2 files

2.1.1

2 files

1.20.2

2 files

1.20.1

2 files

1.20.0

2 files

1.19.0

2 files

1.18.0

2 files

1.17.0

2 files

1.16.1

2 files

1.16.0

2 files

1.15.1

2 files

1.15.0

2 files

1.14.0

2 files

1.13.0

2 files

1.12.1

2 files

1.12.0

2 files

1.11.0

2 files

1.10.0

2 files

1.9.1

2 files

1.9.0

2 files

1.8.0

2 files

1.7.0

2 files

1.6.1

2 files

1.6.0

2 files

1.5.0

2 files

1.4.2

2 files

1.4.1

2 files

1.4.0

2 files

1.3.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.1

2 files

1.0.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