SymPy, NumPy, and SciPy boundaries
Keep exact structure symbolic until a numerical consumer is chosen. Then compile an
explicit numeric contract and verify the numerical result against the original
mathematics.
Inspect the installed version of SymPy, NumPy, and SciPy and exact signatures before
depending on translation mappings or solver options.
Boundary workflow
- State symbols, assumptions, parameter order, units, real/complex domain, and valid
input region in SymPy.
- Simplify or differentiate symbolically only when the transformation preserves the
intended domain. Record excluded singularities introduced or removed by algebra.
- Choose a numeric backend explicitly with
lambdify; use modules="numpy" for
vector evaluation and a SciPy-capable mapping only when required functions are not
provided by NumPy.
- Define the callable's input shapes, broadcasting contract, output shape, dtype, and
behavior at singular or invalid points.
- Feed the callable to SciPy only after adapting its signature to the solver's
contract. Do not rely on implicit symbol order.
- Validate convergence using residuals and constraints. When a solution can be
local or initialization-sensitive, also use multiple starts or a justified
bracket—not the solver success flag alone.
- Cross-check representative results against higher-precision SymPy/mpmath or an
independent formulation.
Read translation.md,
solver-contracts.md, and
verification.md.
Canonical scalar solve
import numpy as np
import sympy as sp
from scipy import optimize
x, a = sp.symbols("x a", real=True)
expr = sp.exp(-a * x) - x
numeric = sp.lambdify((x, a), expr, modules="numpy")
parameter = 2.0
root = optimize.brentq(lambda value: float(numeric(value, parameter)), 0.0, 1.0)
residual = abs(float(numeric(root, parameter)))
if not np.isfinite(root) or residual > 1e-10:
raise RuntimeError(f"unverified root: residual={residual:g}")
Use a bracketed solver when a sign-changing interval is available. Use a local solver
only when an initial estimate and basin assumptions are defensible.
Decision rules
- Many machine-precision evaluations:
lambdify once, then use NumPy arrays.
- One exact or high-precision evaluation: keep SymPy/mpmath rather than forcing NumPy.
- Symbolic Jacobian available and tractable: lambdify it and pass it to the SciPy
algorithm; verify its shape and values with finite differences at sample points.
- Piecewise or branch-sensitive expression: test every branch and boundary; generated
NumPy code may evaluate masked branches and emit warnings.
- Untrusted expression: do not pass it to
sympify/lambdify as a security boundary;
parse against an explicit safe grammar outside this workflow.
Completion checks
- Symbol and parameter ordering is explicit and tested.
- Shape, dtype, domain, and nonfinite behavior are asserted.
- Solver termination, residual, and constraints all pass.
- At least one boundary/singularity case and one independent numerical check pass.
- No result is called exact after it has crossed into floating-point computation.
1---2name: sympy-numpy-scipy-boundaries3description: >-4 Use when symbolic mathematics must cross into NumPy vector evaluation or SciPy5 numerical algorithms: lambdify contracts, domains, dtypes, parameters, residuals,6 tolerances, and symbolic-versus-numeric verification. Do not use for work confined7 entirely to one of those libraries.8---910# SymPy, NumPy, and SciPy boundaries1112Keep exact structure symbolic until a numerical consumer is chosen. Then compile an13explicit numeric contract and verify the numerical result against the original14mathematics.1516Inspect the installed version of SymPy, NumPy, and SciPy and exact signatures before17depending on translation mappings or solver options.1819## Boundary workflow20211. State symbols, assumptions, parameter order, units, real/complex domain, and valid22 input region in SymPy.232. Simplify or differentiate symbolically only when the transformation preserves the24 intended domain. Record excluded singularities introduced or removed by algebra.253. Choose a numeric backend explicitly with `lambdify`; use `modules="numpy"` for26 vector evaluation and a SciPy-capable mapping only when required functions are not27 provided by NumPy.284. Define the callable's input shapes, broadcasting contract, output shape, dtype, and29 behavior at singular or invalid points.305. Feed the callable to SciPy only after adapting its signature to the solver's31 contract. Do not rely on implicit symbol order.326. Validate convergence using residuals and constraints. When a solution can be33 local or initialization-sensitive, also use multiple starts or a justified34 bracket—not the solver success flag alone.357. Cross-check representative results against higher-precision SymPy/mpmath or an36 independent formulation.3738Read [translation.md](references/translation.md),39[solver-contracts.md](references/solver-contracts.md), and40[verification.md](references/verification.md).4142## Canonical scalar solve4344```python45import numpy as np46import sympy as sp47from scipy import optimize4849x, a = sp.symbols("x a", real=True)50expr = sp.exp(-a * x) - x51numeric = sp.lambdify((x, a), expr, modules="numpy")5253parameter = 2.054root = optimize.brentq(lambda value: float(numeric(value, parameter)), 0.0, 1.0)55residual = abs(float(numeric(root, parameter)))56if not np.isfinite(root) or residual > 1e-10:57 raise RuntimeError(f"unverified root: residual={residual:g}")58```5960Use a bracketed solver when a sign-changing interval is available. Use a local solver61only when an initial estimate and basin assumptions are defensible.6263## Decision rules6465- Many machine-precision evaluations: `lambdify` once, then use NumPy arrays.66- One exact or high-precision evaluation: keep SymPy/mpmath rather than forcing NumPy.67- Symbolic Jacobian available and tractable: lambdify it and pass it to the SciPy68 algorithm; verify its shape and values with finite differences at sample points.69- Piecewise or branch-sensitive expression: test every branch and boundary; generated70 NumPy code may evaluate masked branches and emit warnings.71- Untrusted expression: do not pass it to `sympify`/`lambdify` as a security boundary;72 parse against an explicit safe grammar outside this workflow.7374## Completion checks7576- Symbol and parameter ordering is explicit and tested.77- Shape, dtype, domain, and nonfinite behavior are asserted.78- Solver termination, residual, and constraints all pass.79- At least one boundary/singularity case and one independent numerical check pass.80- No result is called exact after it has crossed into floating-point computation.