Skip to content

Symbolic Computation ​

This document provides specifications for TeXpr's symbolic computation capabilities, including exact differentiation, simplification rules, variable assumptions, and domain handling.

Scope and Limitations ​

IMPORTANT

TeXpr is not a full Computer Algebra System (CAS). Understanding these boundaries is critical:

CapabilityTeXprFull CAS (SymPy, Mathematica)
Symbolic differentiation✅ Exact✅ Exact
Symbolic integration❌ Numerical only✅ Symbolic
SimplificationPattern-basedCanonical forms
Equation solvingLinear/Quadratic onlyGeneral
Polynomial factoringBasic patternsFull algorithms
Domain assumptionsBasicComprehensive

Differentiation ​

Exact vs. Numeric ​

TeXpr performs exact symbolic differentiation. Derivatives are computed by applying calculus rules to the AST, not by numerical approximation.

dart
final expr = texpr.parse('x^3');
final deriv = texpr.differentiate(expr, 'x');
// Result: AST representing 3x²

// This is EXACT, not (f(x+h) - f(x))/h

Differentiation Rules ​

The following rules are applied recursively:

RuleFormulaExample
Constantd/dx(c) = 0d/dx(5) = 0
Variabled/dx(x) = 1d/dx(x) = 1
Other variabled/dx(y) = 0d/dx(y) = 0
Powerd/dx(x^n) = n·x^(n-1)d/dx(x³) = 3x²
Sumd/dx(f+g) = f' + g'd/dx(x+1) = 1
Productd/dx(fg) = f'g + fg'd/dx(x·sin(x)) = sin(x) + x·cos(x)
Quotientd/dx(f/g) = (f'g - fg')/g²Standard quotient rule
Chaind/dx(f(g)) = f'(g)·g'd/dx(sin(x²)) = 2x·cos(x²)
Exponentiald/dx(e^f) = f'·e^fd/dx(e^x²) = 2x·e^x²
Logarithmd/dx(ln(f)) = f'/fd/dx(ln(x)) = 1/x

Function Derivatives ​

FunctionDerivative
sin(x)cos(x)
cos(x)-sin(x)
tan(x)sec²(x)
sec(x)sec(x)·tan(x)
csc(x)-csc(x)·cot(x)
cot(x)-csc²(x)
arcsin(x)1/√(1-x²)
arccos(x)-1/√(1-x²)
arctan(x)1/(1+x²)
sinh(x)cosh(x)
cosh(x)sinh(x)
tanh(x)sech²(x)

Higher-Order Derivatives ​

dart
texpr.differentiate(expr, 'x', order: 2);  // Second derivative
texpr.differentiate(expr, 'x', order: 3);  // Third derivative

Limitation: Very high-order derivatives (> 50) may hit recursion limits or produce very large ASTs.


Integration ​

Symbolic vs. Numerical ​

WARNING

Integration is numerical only. TeXpr does not produce symbolic antiderivatives.

dart
// This produces a numeric result, not an AST
texpr.evaluate(r'\int_{0}^{1} x^2 dx');  // 0.3333...

For symbolic integration, export to SymPy:

dart
final sympy = texpr.parse(r'\int x^2 dx').toSymPy();
// "integrate(x**2, x)"  — run in Python for symbolic result

Numerical Method ​

  • Algorithm: Simpson's Rule
  • Intervals: 10,000 (fixed)
  • Accuracy: ~10 decimal places for smooth functions

Simplification Rules ​

Pattern-Based, Not Canonical ​

TeXpr applies local pattern matching. It does not produce canonical polynomial forms.

dart
// These succeed
engine.simplify(parse('0 + x'));      // → x
engine.simplify(parse('x * 1'));      // → x
engine.simplify(parse('x + x'));      // → 2x

// This does NOT simplify
engine.simplify(parse('2x + 3x'));    // → 2x + 3x (not 5x)

Applied Rules ​

PatternResultCondition
x + 0xAlways
0 + xxAlways
x - 0xAlways
x * 1xAlways
1 * xxAlways
x * 00Always
0 * x0Always
x / 1xAlways
x ^ 01x ≠ 0
x ^ 1xAlways
0 ^ x0x > 0
1 ^ x1Always
x - x0Same subexpression
x / x1x ≠ 0
--xxAlways
x + x2xSame subexpression
x * xx²Same subexpression

Trigonometric Identities ​

IdentityApplied
sin²(x) + cos²(x) = 1Yes
sin(0) = 0Yes
cos(0) = 1Yes
tan(0) = 0Yes
sin(-x) = -sin(x)Yes
cos(-x) = cos(x)Yes
sin(2x) = 2·sin(x)·cos(x)Via expandTrig()
cos(2x) = cos²(x) - sin²(x)Via expandTrig()

Logarithm Laws ​

LawApplied
log(1) = 0Yes
log(e) = 1 (for ln)Yes
log(x^n) = n·log(x)Yes
log(ab) = log(a) + log(b)Via specific method
log(a/b) = log(a) - log(b)Via specific method

Variable Assumptions ​

Default Behavior ​

Without assumptions, TeXpr assumes variables can be any complex number:

dart
engine.simplify(parse('sqrt(x^2)'));  // → |x| (absolute value)
engine.simplify(parse('ln(x^2)'));    // → ln(|x|^2) or similar safe form

Setting Assumptions ​

dart
engine.assume('x', Assumption.nonNegative);
engine.simplify(parse('sqrt(x^2)'));  // → x (not |x|)

Available Assumptions ​

AssumptionMeaningEnables
Assumption.realx ∈ ℝReal-valued operations
Assumption.complexx ∈ ℂDefault, no restrictions
Assumption.integerx ∈ ℤInteger optimizations
Assumption.positivex > 0sqrt(x²) = x, ln(x) valid
Assumption.nonNegativex ≥ 0sqrt(x²) = x
Assumption.negativex < 0sqrt(x²) = -x
Assumption.nonPositivex ≤ 0Domain restrictions

Clearing Assumptions ​

dart
engine.clearAssumption('x');
// Or create a new engine instance

Domain Restrictions ​

Implicit Domains ​

Functions have implicit domain restrictions:

FunctionDomainBehavior Outside
sqrt(x)x ≥ 0 (real)Returns complex
ln(x)x > 0 (real)Returns complex or throws
arcsin(x)-1 ≤ x ≤ 1Returns complex
arccos(x)-1 ≤ x ≤ 1Returns complex
1/xx ≠ 0Returns ±∞

Complex Number Handling ​

When domain restrictions are violated, TeXpr returns complex numbers:

dart
texpr.evaluate('sqrt(-1)');   // ComplexResult(0, 1) = i
texpr.evaluate('ln(-1)');     // ComplexResult(0, π) = πi
texpr.evaluate('arcsin(2)');  // Complex result

Check result type:

dart
final result = texpr.evaluate('sqrt(-1)');
if (result.isComplex) {
  final c = result.asComplex();
  print('${c.real} + ${c.imaginary}i');
}

SymbolicEngine API ​

Overview ​

dart
import 'package:texpr/texpr.dart';

final engine = SymbolicEngine();
final texpr = Texpr();

final expr = texpr.parse('0 + x');
final simplified = engine.simplify(expr);

Methods ​

MethodPurposeExample
simplify(expr)Apply simplification rules0 + x → x
expand(expr)Expand powers and products(x+1)² → x² + 2x + 1
factor(expr)Factor polynomialsx² - 4 → (x-2)(x+2)
expandTrig(expr)Expand trig identitiessin(2x) → 2·sin(x)·cos(x)
solveLinear(eq, var)Solve linear equations2x + 4 = 0 → -2
solveQuadratic(eq, var)Solve quadratic equationsx² - 4 = 0 → [2, -2]
assume(var, assumption)Set domain assumptionassume('x', Assumption.positive)
areEquivalent(e1, e2)Test equivalencex + 1 ≡ 1 + x

Expansion ​

dart
engine.expand(texpr.parse('(x + 1)^2'));
// Result: x² + 2x + 1

Supports (a + b)^n for integer n ≤ 10.

Factorization ​

dart
engine.factor(texpr.parse('x^2 - 4'));
// Result: (x - 2)(x + 2)

Limited to recognizable patterns (difference of squares, perfect squares).

Equation Solving ​

dart
// Linear: ax + b = 0
engine.solveLinear(equation, 'x');

// Quadratic: ax² + bx + c = 0
engine.solveQuadratic(equation, 'x');

WARNING

General polynomial solving (degree > 2) is not supported.


Equivalence Testing ​

dart
final e1 = texpr.parse('x + 1');
final e2 = texpr.parse('1 + x');
engine.areEquivalent(e1, e2);  // true

This works by:

  1. Simplifying both expressions
  2. Comparing the canonical AST structures

Limitations: May return false for equivalent expressions that require advanced algebraic manipulation to prove equal.


What TeXpr Does NOT Do ​

For clarity, here's what you cannot do with TeXpr's symbolic engine:

OperationStatusAlternative
Symbolic integration❌Export to SymPy
General equation solving❌External CAS
System of equations❌External CAS
Polynomial long division❌Manual or CAS
Gröbner basis❌Specialized library
Limit evaluation (symbolic)❌Numerical only
Series expansion❌External CAS
Laplace/Fourier transforms❌External CAS

Performance Considerations ​

Simplification Complexity ​

Simplification is O(n) for a single pass but may iterate up to 100 times for convergence:

dart
// Worst case: 100 iterations × O(n) per iteration
engine.simplify(veryComplexExpression);

AST Growth in Expansion ​

Expansion can produce exponentially larger ASTs:

dart
(x + 1)^10  // Produces 11 terms
(x + y + z)^10  // Produces 66 terms

Caching Derivatives ​

For repeated differentiation, cache the parsed expression:

dart
final expr = texpr.parse('sin(x^2)');
final d1 = texpr.differentiate(expr, 'x');
final d2 = texpr.differentiate(d1, 'x');
// More efficient than re-parsing

Made with ❤️ by TeXpr, Docs Inspired by ElysiaJS