Version: dev

simplify

Stable function · Expressions

Tier: stable · Kind: function · Topic: Expressions

JuliaTypeScriptPythonRustGo
simplifysimplifysimplifysimplifySimplify

Julia

simplify(expr::NumExpr)
simplify(expr::IntExpr)
simplify(expr::VarExpr)
simplify(expr::OpExpr)
simplify(expr::ASTExpr)::ASTExpr

Perform constant folding and algebraic simplification on an expression. Returns a new simplified ASTExpr object (non-mutating).

Simplification Rules

  • Constant folding: 2 + 3 → 5
  • Additive identity: x + 0 → x, 0 + x → x
  • Multiplicative identity: x * 1 → x, 1 * x → x
  • Multiplicative zero: x * 0 → 0, 0 * x → 0
  • Exponentiation: x^0 → 1, x^1 → x

Examples

# Constant folding
expr = OpExpr("+", [NumExpr(2.0), NumExpr(3.0)])
result = simplify(expr)  # NumExpr(5.0)

# Identity elimination
expr = OpExpr("*", [VarExpr("x"), NumExpr(1.0)])
result = simplify(expr)  # VarExpr("x")

Source

Example (expressions)

# Parse from text, or build the tree directly.
expr = parse_expression("k * x + y")
built = OpExpr("+", [OpExpr("*", [VarExpr("k"), VarExpr("x")]), VarExpr("y")])
@assert to_ascii(expr) == to_ascii(built) == "k * x + y"

@assert free_variables(expr) == Set(["k", "x", "y"])

# `substitute` takes a Dict{String,ASTExpr}: give the value type explicitly.
replaced = substitute(expr, Dict{String,ASTExpr}("y" => parse_expression("2 * x")))
@assert to_ascii(replaced) == "k * x + 2 * x"
@assert free_variables(replaced) == Set(["k", "x"])

# Constant subexpressions fold away.
@assert to_ascii(simplify(parse_expression("x * (1 + 1)"))) == "x * 2"

# An equation parses the same way, with D(x, t) for a time derivative.
eq = parse_equation("D(x, t) = -k * x")
@assert eq isa Equation
@assert to_unicode(eq) == "∂x/∂t = −k·x"

From docs/api/examples/julia/expressions.jl

TypeScript

function simplify(expr: Expr): Expr

Simplify an expression using basic algebraic rules

Parameters

  • expr — Expression to simplify

Returns

Simplified expression

Source

Example (expressions)

// Expressions are plain JSON trees; build one directly ...
const built: Expr = { op: '*', args: ['k', { op: '-', args: ['T_wall', 'T_air'] }] }

// ... or parse the text form, which is the inverse of `toAscii`.
const parsed = parseExpression('k * (T_wall - T_air)')
assert.deepEqual(parsed, built)
assert.deepEqual([...freeVariables(parsed)].sort(), ['T_air', 'T_wall', 'k'])
assert.equal(contains(parsed, 'T_wall'), true)

// Substitution is single-pass and returns a new tree.
const bound = substitute(parsed, { T_wall: 300, k: 0.05 })
assert.equal(toAscii(bound), '0.05 * (300 - T_air)')
assert.deepEqual([...freeVariables(bound)], ['T_air'])
assert.equal(toAscii(simplify(substitute(parsed, { T_wall: 300, T_air: 300 }))), '0')

const eq = parseEquation('D(T_air) = k * (T_wall - T_air)')
assert.deepEqual(eq.rhs, built)

assert.throws(() => parseExpression('k * (T_wall'), ExpressionParseError)

From docs/api/examples/typescript/expressions.ts

Python

simplify(expr: Expr) -> Expr

Simplify an expression by performing constant folding and basic algebraic simplifications.

Parameters

  • expr (Expr) — Expression to simplify

Returns

  • Expr — Simplified expression

Source

Example (simplify)

messy = ExprNode(op="+", args=[ExprNode(op="*", args=["x", 1]), 0])
assert earthsci_ast.simplify(messy) == "x"

folded = earthsci_ast.simplify(ExprNode(op="*", args=[2, 3, "x"]))
assert earthsci_ast.to_ascii(folded) == "x * 6"

From docs/api/examples/python/expressions.py

Rust

pub fn simplify(expr: &Expr) -> Expr

Simplify an expression (basic symbolic simplification).

Applies constant folding and the identity/absorbing-element rules for binary +, *, and ^. Children are simplified first — including sidecar expressions (aggregate bodies, filter, integral bounds, makearray values, table_lookup axes) — and operator nodes are rebuilt with crate::types::ExpressionNode::map_children, so all node metadata is preserved.

Source · Rust docs

Example (evaluate)

let expr = parse_expression("k * A - x")?;
let bindings = HashMap::from([
    ("k".to_string(), 2.0),
    ("A".to_string(), 3.0),
    ("x".to_string(), 1.0),
]);
assert_eq!(evaluate(&expr, &bindings), Ok(5.0));

// A missing binding is reported by name, not guessed.
let partial = HashMap::from([("k".to_string(), 2.0)]);
let mut unbound = evaluate(&expr, &partial).unwrap_err();
unbound.sort();
assert_eq!(unbound, ["A", "x"]);

assert!(contains(&expr, "A") && !contains(&expr, "B"));
assert_eq!(to_ascii(&simplify(&parse_expression("x * 1 + 0")?)), "x");

From docs/api/examples/rust/expressions.rs

Go

func Simplify(expr Expression) Expression

Simplify performs constant folding and basic algebraic simplification.

A typed-nil *ExprNode is returned unchanged rather than dereferenced (audit no audit ID; found while fixing G3), matching Substitute/asExprNode.

Source · Go docs