Canonical Forms

A mathematical expression has many equivalent representations.

For example, the expressions in each row below represent the same mathematical object:

\[ 215.3465 \] \[ 2.15346\mathrm{e}2 \] \[ 2.15346 \times 10^2\]
\[ 1 - x \] \[-x + 1 \] \[ 1 + (-x)\]
\[ -2x^{-1}\] \[ -\frac{2}{x} \] \[ \frac{-2}{x} \]

By applying some conventions — for example wether to write constants before or after variables in a sum, how to sort variables and functions when they are an argument in a commutative function — we define a canonical representation.

A canonical representation is somewhat arbitrary, but using it consistently can make some operations easier, for example, comparing two expressions for equality.

The canonical form used by the Compute Engine has been selected to follow common (but by no mean universal) conventions in writing mathematical expressions, as well as expressing them in a way that can optimize their computation.

To obtain the canonical representation of an expression, use the ce.canonical() function.

Applying a canonical form is applying some rewriting rules to an expression. In that sense, it is similar to simplifying an expression with ce.simplify(), but it is more conservative in which transformations it will consider, and it will not take into account any assumptions about symbols.

The default canonical representation applies a series of transformation to put sums, products, numbers, roots, etc… in canonical form. Each of these steps/format can also be applied separately for more control over the result.

The list of available formats is listed below.

Form Description
canonical Apply the following transformations, in order:
  • canonical-number
  • canonical-exp
  • canonical-root
  • canonical-subtract
  • canonical-divide
  • canonical-power
  • canonical-multiply
  • canonical-negate
  • canonical-add
  • flatten
  • canonical-list
  • canonical-set
  • canonical-domain
  • canonical-rational
  • canonical-constants
  • sorted
  • json
canonical-add Addition of 0 is simplified, associativity rules are applied, unnecessary groups are removed, single argument Add are simplified
canonical-constants Simplify some arithmetic and trigonometric constants: \( \frac{1}{2}, \frac{\pi}{4}, \ldots \)
canonical-divide Division by 1 is simplified
canonical-domain Simplify some Range and Interval expressions to corresponding constants
canonical-exp ["Power", "ExponentialE", "x"] \( \longrightarrow \) ["Exp", "x"
canonical-multiply Multiplication by \( 1 \) or \( -1 \) is simplified. Square roots are grouped. Negative constant is pulled first.
canonical-negate Negate of a number \( \longrightarrow \) the negative of the number. Negation of negation is simplified
canonical-list In List, Sequence, simplify Identity. Flattens Sequence .
canonical-number Complex numbers with no imaginary components are simplified
  • \[x^{\tilde\infty} \longrightarrow \operatorname{NaN}\]
  • \[x^0 \longrightarrow 1\]
  • \[x^1 \longrightarrow x\]
  • \[(\pm 1)^{-1} \longrightarrow -1\]
  • \[(\pm\infty)^{-1} \longrightarrow 0\]
  • \[0^{\infty} \longrightarrow \tilde\infty\]
  • \[(\pm 1)^{\pm \infty} \longrightarrow \operatorname{NaN}\]
  • \[\infty^{\infty} \longrightarrow \infty\]
  • \[\infty^{-\infty} \longrightarrow 0\]
  • \[(-\infty)^{\pm \infty} \longrightarrow \operatorname{NaN}\]
canonical-root Power \( \longrightarrow \) Root and Sqrt or simplified
canonical-set Simplify set expressions by sorting arguments
canonical-subtract Subtract \( \longrightarrow \) Add and Negate
flatten Associative functions are combined, e.g. \( f(f(a, b), c) \longrightarrow f(a, b, c) \)
json Only transformations necessary to make the expression valid JSON, for example making sure that Infinity and NaN are represented as strings
object-literal Each term of the expression is expressed as an object literal: no shorthand representation is used. For example, the number \( 4\) is represented as { num: "4" } not as 4.
sorted The arguments of commutative functions are sorted such that:
  • numbers are first, sorted numerically
  • complex numbers are next, sorted numerically by imaginary value
  • symbols are next, sorted lexicographically
  • add functions are next
  • multiply functions are next
  • power functions are next, sorted by their first argument, then by their second argument
  • other functions follow, sorted lexicographically
stripped-metadata Any metadata associated with elements of the expression is removed, for example associated wikidata, comment or latex properties

To transform an expression using the rules for a particular form, use the format() function.

import { format } from '@cortex-js/compute-engine'

console.log(format(["Add", 2, "x", 3], 'canonical');
// ➔ ["Add", 2, 3, "x"]


["BaseForm", _value_, _base_]

Format a value in a specific base, such as hexadecimal or binary.

  • value should be an integer.
  • base should be an integer from 2 to 36.
["Latex", ["BaseForm", 42, 16]]
// ➔ (\mathtt(2a))_{16}
Latex(BaseForm(42, 16))
// ➔ (\mathtt(2a))_{16}
String(BaseForm(42, 16))
// ➔ "'0x2a'"

Applying Custom Rules

You can define and apply your own custom rewriting rules using patterns, rules and the ce.replace() function.