pipe_command

pipe_command

Pipe commands for functional composition of mathematical operations.

This module provides @Pipe decorated functions that enable chain operations like: expr | pc.subs(vals) | pc.convert_to(units) | pc.N

All functions are designed to work with SymPy expressions and support functional programming patterns for mathematical computation workflows.

Functions

Name Description
order_subs Reorder substitutions using topological order for dependency resolution.
subs Substitute variables in symbolic expressions with values or other expressions.
N Numerically evaluate symbolic expressions to floating-point values.
convert_to Convert quantities to different units while preserving values.
doit Evaluate unevaluated operations in symbolic expressions.
parse_expr Parse mathematical expression strings into SymPy symbolic objects.
quantity_simplify Simplify expressions with units by combining and reducing quantities.
as_two_terms Split expression into magnitude and units components.
as_Mul Create unevaluated multiplication from tuple of expressions.

order_subs

order_subs(subs)

Reorder substitutions using topological order for dependency resolution.

Ensures that substitutions are applied in the correct order when variables depend on each other (e.g., y depends on x, so x must be substituted first).

Parameters

Name Type Description Default
subs dict[Basic, Any] Dictionary of substitutions where keys are variables and values are expressions required

Returns

Name Type Description
list[tuple[Basic, Any]] Ordered list of substitution tuples for exhaustive application

subs

subs(expression, substitution, sorted=True)

Substitute variables in symbolic expressions with values or other expressions.

Applies substitutions to SymPy expressions while handling dependencies between variables. Commonly used in workflows to evaluate symbolic equations with parameters from _p dicts or intermediate expressions from _e dicts. Integrates with pipe operations for functional composition.

NOTE: Returns None if input expression is None, allowing chain operations to gracefully handle missing values.

Parameters

Name Type Description Default
expression Basic SymPy expression to apply substitutions to. Can be any symbolic expression containing variables to be replaced. required
substitution dict[Basic, Any] Dictionary mapping variables (symbols) to their replacement values (numeric values, quantities with units, or other expressions). Non-Basic keys and None values are automatically filtered out. required
sorted bool Whether to apply topological sorting for dependency resolution. When True (default), automatically orders substitutions so that dependent variables are substituted in correct order (e.g., if y depends on x, x is substituted first). Defaults to True. True

Returns

Name Type Description
Basic SymPy expression with substitutions applied, or None if input is None.

Examples

from keecas import symbols, u, pc, show_eqn

# Basic parameter substitution
F, A_load = symbols(r"F, A_{load}")

_p = {
    F: 100*u.kN,
    A_load: 20*u.cm**2,
}

sigma = symbols(r"\sigma")
_e = {
    sigma: "F / A_load" | pc.parse_expr,
}

# Substitute parameters into expression
result = _e[sigma] | pc.subs(_p)
# Multi-step workflow with merged dicts
_v = {
    k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] A_{load} & = 20{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 50.0{\,}\text{MPa} \end{align}\]

# Dependency resolution with sorted=True
x, y, z = symbols(r"x, y, z")

# y depends on x, z depends on y
_e = {
    z: "x + y" | pc.parse_expr,
    y: "2 * x" | pc.parse_expr,
    x: 5,
}

# Automatic ordering: x first, then y, then z
result = z | pc.subs(_e)  # sorted=True by default

Notes

  • Automatically filters out None values and non-Basic keys from substitution dict
  • Topological sorting handles complex dependency chains automatically
  • Works seamlessly with Pint quantities through SymPy integration
  • Common pattern: _p | _e merges parameters and expressions for substitution

N

N(expression, precision=15)

Numerically evaluate symbolic expressions to floating-point values.

Converts symbolic expressions containing irrational numbers, constants, or unevaluated operations into numeric approximations. Commonly used as final step in calculation workflows before display with show_eqn().

Parameters

Name Type Description Default
expression Basic SymPy expression to evaluate numerically. Can contain symbolic math operations, constants (pi, e, etc.), or quantities with units. required
precision int Number of decimal digits for evaluation. Controls internal calculation precision, not display formatting (use float_format in show_eqn for display). Defaults to 15. 15

Returns

Name Type Description
Basic Numerically evaluated SymPy expression as floating-point approximation.

Examples

from keecas import symbols, u, pc, show_eqn
from sympy import pi

# Basic numeric evaluation
r = symbols(r"r")
A_circle = symbols(r"A_{circle}")

_p = {
    r: 5*u.cm,
}

_e = {
    A_circle: "pi * r**2" | pc.parse_expr,
}

# Evaluate symbolic pi to numeric value
_v = {
    k: v | pc.subs(_p | _e) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} r & = 5{\,}\text{cm} & \\[8pt] A_{circle} & = \pi{\,}r^{2} & = 78.5398163397448{\,}\text{cm}^{2} \end{align}\]

# Control precision for high-accuracy calculations
import sympy as sp

expr = sp.sqrt(2)

# Default precision (15 digits)
result_default = expr | pc.N

# High precision (50 digits)
result_high = expr | pc.N(precision=50)
# Typical workflow: subs -> convert_to -> N
F, A_load, sigma_Sd = symbols(r"F, A_{load}, \sigma_{Sd}")

_p = {
    F: 850*u.kN,
    A_load: 120*u.cm**2,
}

_e = {
    sigma_Sd: "F / A_load" | pc.parse_expr,
}

_v = {
    k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F & = 850{\,}\text{kN} & \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & \\[8pt] \sigma_{Sd} & = \dfrac{F}{A_{load}} & = 70.8333333333333{\,}\text{MPa} \end{align}\]

Notes

  • Precision parameter controls internal calculation accuracy, not display
  • For display formatting, use float_format parameter in show_eqn()
  • Works with Pint quantities, preserving units in output
  • Commonly chained after subs() and convert_to() in evaluation workflows

convert_to

convert_to(expression, units=1)

Convert quantities to different units while preserving values.

Converts SymPy expressions with units to target units, handling both prefixed units (kN, daN, cm) and compound units (MPa, kN/m). Commonly used in engineering workflows to standardize units before display or comparison. Integrates seamlessly with Pint unit definitions.

Parameters

Name Type Description Default
expression Basic SymPy expression with units to convert. Must contain dimensional quantities (e.g., force, pressure, length). required
units Any Target units for conversion. Can be: - Single unit (e.g., u.MPa) - List of units (e.g., [u.kN, u.mm]) - Compound units (e.g., u.kN/u.m) Defaults to 1 (dimensionless). 1

Returns

Name Type Description
Basic Expression converted to target units with same magnitude in new units.

Examples

from keecas import symbols, u, pc, show_eqn

# Basic unit conversion
F, A_load = symbols(r"F, A_{load}")

_p = {
    F: 5000*u.N,  # Newtons
    A_load: 120*u.cm**2,
}

# Convert to kilonewtons
_v = {
    F: _p[F] | pc.convert_to(u.kN),
    A_load: _p[A_load] | pc.convert_to(u.m),
}

show_eqn([_p, _v])

\[\begin{align} F & = 5000{\,}\text{N} & = 5{\,}\text{kN} \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & = \dfrac{3}{250}{\,}\text{m}^{2} \end{align}\]

# Compound unit conversion
sigma = symbols(r"\sigma")

_p = {
    F: 850*u.kN,
    A_load: 120*u.cm**2,
}

_e = {
    sigma: "F / A_load" | pc.parse_expr,
}

# Convert pressure to MPa
_v = {
    k: v | pc.subs(_p | _e) | pc.convert_to(u.MPa) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F & = 850{\,}\text{kN} & \\[8pt] A_{load} & = 120{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 70.8333333333333{\,}\text{MPa} \end{align}\]

# List of target units for flexibility
L, delta = symbols(r"L, \delta")

_p = {
    L: 8*u.m,
}

_e = {
    delta: "L / 400" | pc.parse_expr,
}

# Try converting to mm, fallback to other units if needed
_v = {
    k: v | pc.subs(_p | _e) | pc.convert_to([u.mm]) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} L & = 8{\,}\text{m} & \\[8pt] \delta & = \dfrac{L}{400} & = 20.0{\,}\text{mm} \end{align}\]

Notes

  • Prefixed units (kN, cm, MPa) handled automatically via SymPy prefix system
  • Non-prefixed units (kgf, lbf) use scale factors from Pint definitions
  • All Pint units convert correctly through SymPy integration
  • Commonly chained between subs() and N() in evaluation workflows
  • List of units allows flexible conversion with fallback options

doit

doit(expression)

Evaluate unevaluated operations in symbolic expressions.

Forces evaluation of operations that SymPy keeps in symbolic form, such as derivatives, integrals, summations, or limits. Useful when symbolic operations need numeric results or simplified forms.

Parameters

Name Type Description Default
expression Basic SymPy expression containing unevaluated operations (derivatives, integrals, summations, limits, etc.) that should be evaluated. required

Returns

Name Type Description
Basic Expression with all unevaluated operations evaluated to their results.

Examples

from keecas import symbols, pc
import sympy as sp

# Evaluate derivative
x = symbols(r"x")
expr = sp.Derivative(x**2, x)

# Without doit: shows Derivative(x**2, x)
print(expr)

# With doit: evaluates to 2*x
result = expr | pc.doit
print(result)
Derivative(x**2, x)
2*x
# Evaluate integral
integral_expr = sp.Integral(sp.sin(x), x)

# Evaluates to -cos(x)
result = integral_expr | pc.doit
# Use in calculation workflow
from keecas import u, show_eqn

F, x_coord = symbols(r"F, x")

_p = {
    F: 100*u.kN,
}

# Expression with derivative
_e = {
    symbols(r"dF/dx"): sp.Derivative(F * x_coord**2, x_coord),
}

# Evaluate derivative then substitute
_v = {
    k: v | pc.doit | pc.subs(_p) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] dF/dx & = \dfrac{\partial}{\partial x} F{\,}x^{2} & = 200.0{\,}x{\,}\text{kN} \end{align}\]

Notes

  • Works with derivatives, integrals, limits, summations, and products
  • May be needed before subs() to properly substitute into evaluated forms
  • Not all operations can be evaluated symbolically (may return unchanged)
  • Combines well with other pipe commands in calculation workflows

parse_expr

parse_expr(expression, local_dict=None, evaluate=False, **kwargs)

Parse mathematical expression strings into SymPy symbolic objects.

Converts string representations of mathematical expressions into SymPy expressions that can be manipulated symbolically. Most commonly used with pipe operator to define expressions in _e dicts using readable string notation instead of verbose SymPy syntax.

NOTE: Automatically captures local variables from caller’s scope when local_dict is None, enabling clean string-based expression definitions.

Parameters

Name Type Description Default
expression str String representation of mathematical expression using standard notation (e.g., “F / A”, “pi * r**2”, “sqrt(x2 + y2)”). Supports operators: +, -, *, /, **, parentheses, and common functions. required
local_dict dict[str, Any] | None Dictionary of local variables for parsing context (symbol definitions, parameters, functions). If None, automatically uses caller’s local variables from enclosing scope. Defaults to None. None
evaluate bool Whether to evaluate the expression during parsing (e.g., simplify numeric operations). When False, preserves structure as written. Defaults to False. False
**kwargs Any Additional arguments passed to SymPy’s parse_expr: - transformations: List of parsing transformations (defaults to T[:11]) - global_dict: Global symbol dictionary - rational: Whether to convert floats to rationals {}

Returns

Name Type Description
Basic Parsed SymPy expression object ready for symbolic manipulation.

Examples

from keecas import symbols, u, pc, show_eqn

# Most common pattern: define expressions as strings
F, A_load, sigma = symbols(r"F, A_{load}, \sigma")

_p = {
    F: 100*u.kN,
    A_load: 20*u.cm**2,
}

# Use parse_expr to convert string to SymPy expression
_e = {
    sigma: "F / A_load" | pc.parse_expr,
}

_v = {
    k: v | pc.subs(_p | _e) | pc.convert_to([u.MPa]) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F & = 100{\,}\text{kN} & \\[8pt] A_{load} & = 20{\,}\text{cm}^{2} & \\[8pt] \sigma & = \dfrac{F}{A_{load}} & = 50.0{\,}\text{MPa} \end{align}\]

# Complex expressions with functions
from sympy import pi

r, A_circle, V_sphere = symbols(r"r, A_{circle}, V_{sphere}")

_p = {
    r: 5*u.cm,
}

_e = {
    A_circle: "pi * r**2" | pc.parse_expr,
    V_sphere: "(4/3) * pi * r**3" | pc.parse_expr,
}

_v = {
    k: v | pc.subs(_p | _e) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} r & = 5{\,}\text{cm} & \\[8pt] A_{circle} & = \pi{\,}r^{2} & = 78.5398163397448{\,}\text{cm}^{2} \\[8pt] V_{sphere} & = \dfrac{4{\,}\pi{\,}r^{3}}{3} & = 523.598775598299{\,}\text{cm}^{3} \end{align}\]

# Custom local_dict for additional functions
from sympy import sqrt

custom_locals = {
    'special_func': lambda x: sqrt(x**2 + 1),
}

expr = "special_func(5)" | pc.parse_expr(local_dict=custom_locals)
# Multiple dependent expressions
x, y, z, result = symbols(r"x, y, z, result")

_p = {
    x: 3,
    y: 4,
}

# Expressions can reference each other
_e = {
    z: "sqrt(x**2 + y**2)" | pc.parse_expr,
    result: "z * 2" | pc.parse_expr,
}

# tip: automatic dependency resolution with pc.subs
_v = {
    k: v | pc.subs(_p | _e) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} x & = 3 & \\[8pt] y & = 4 & \\[8pt] z & = \sqrt{x^{2} + y^{2}} & = 5.0 \\[8pt] result & = z{\,}2 & = 10.0 \end{align}\]

Notes

  • Uses transformations T[:11] by default for standard mathematical parsing
  • Automatically captures caller’s local scope for symbol resolution
  • Common functions supported: sin, cos, sqrt, log, exp, abs, etc.
  • Operators: +, -, *, /, ** (power), parentheses for grouping
  • Cleaner than verbose SymPy syntax: “F/A” vs sp.Div(F, A)
  • Idiomatic pattern: define symbols, then use string expressions in _e dict

quantity_simplify

quantity_simplify(
    expression,
    across_dimensions=True,
    unit_system='SI',
    **kwargs,
)

Simplify expressions with units by combining and reducing quantities.

Applies SymPy’s quantity simplification to combine terms with compatible units and reduce complex unit expressions. Useful for cleaning up expressions with multiple unit terms or dimensional analysis.

Parameters

Name Type Description Default
expression Basic SymPy expression to simplify, typically containing multiple terms with units that can be combined or reduced. required
across_dimensions bool Whether to simplify across different dimensions (e.g., combine force and length into energy). When True, allows broader simplifications. Defaults to True. True
unit_system str Unit system for simplification, determines which base units to use. Options include “SI”, “CGS”, “imperial”. Defaults to “SI”. 'SI'
**kwargs Any Additional arguments passed to SymPy’s quantity_simplify: - across_dimensions: Override the across_dimensions parameter - unit_system: Override the unit_system parameter {}

Returns

Name Type Description
Basic Simplified SymPy expression with combined and reduced unit terms.

Examples

from keecas import symbols, u, pc, show_eqn

# Simplify expression with multiple force terms
F_1, F_2, F_total = symbols(r"F_1, F_2, F_{total}")

_p = {
    F_1: 100*u.kN,
    F_2: 50000*u.N,
}

_e = {
    F_total: "F_1 + F_2" | pc.parse_expr,
}

# Simplify combines terms with compatible units
_v = {
    k: v | pc.subs(_p | _e) | pc.quantity_simplify | pc.convert_to([u.kN]) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F_{1} & = 100{\,}\text{kN} & \\[8pt] F_{2} & = 50000{\,}\text{N} & \\[8pt] F_{total} & = F_{1} + F_{2} & = 150.0{\,}\text{kN} \end{align}\]

# Dimensional analysis with unit simplification
F, d, E = symbols(r"F, d, E")

_p = {
    F: 500*u.N,
    d: 2*u.m,
}

# Work (energy) from force and distance
_e = {
    E: "F * d" | pc.parse_expr,
}

# Simplify to base energy units
_v = {
    k: v | pc.subs(_p | _e) | pc.quantity_simplify | pc.convert_to([u.J]) | pc.N
    for k, v in _e.items()
}

show_eqn([_p | _e, _v])

\[\begin{align} F & = 500{\,}\text{N} & \\[8pt] d & = 2{\,}\text{m} & \\[8pt] E & = F{\,}d & = 1000.0{\,}\text{J} \end{align}\]

# Different unit systems
from sympy import sympify
from sympy.physics.units import newton, kilonewton

# Create expression with different unit prefixes
expr = 100*kilonewton + 5000*newton

# Simplify combines compatible units
result = expr | pc.quantity_simplify(unit_system="SI")
print(result)  # Combines to single unit
105000*newton

Notes

  • Combines terms with compatible units (e.g., kN + N -> kN)
  • Simplifies compound units to base units when appropriate
  • across_dimensions=True enables dimensional analysis simplifications
  • Works with both SI and other unit systems
  • May need convert_to() afterward to get desired output units

as_two_terms

as_two_terms(expression, as_mul=False)

Split expression into magnitude and units components.

Separates multiplicative expressions or matrices into two terms, typically magnitude and units for cleaner display.

Parameters

Name Type Description Default
expression Basic SymPy expression to split required
as_mul bool If True, return as unevaluated multiplication False

Returns

Name Type Description
Basic | tuple[Basic, Basic] Two-term tuple or unevaluated multiplication, depending on as_mul.
Basic | tuple[Basic, Basic] Returns original expression if splitting is not applicable.

Notes

For matrices, splits only if all elements share the same units.

as_Mul

as_Mul(expression)

Create unevaluated multiplication from tuple of expressions.

Multiplies two expressions while keeping them visually separated, ideal for displaying magnitude and units distinctly.

Parameters

Name Type Description Default
expression tuple[Basic, Basic] Tuple containing two SymPy expressions to multiply required

Returns

Name Type Description
Basic Unevaluated multiplication expression for clean display