# compute-engine

### Functions

**evaluate**Permalink

Apply the definitions in the supplied dictionary to an expression and return the result.

Unlike `format`

this may entail performing calculations and irreversible transformations.

See also `[ComputeEngine.evaluate()](#(ComputeEngine%3Aclass).(evaluate%3Ainstance))`

.

**evaluate**(

`expr`: Expression,

`options`?: {dictionaries: Readonly<Dictionary>[]; onError: ErrorListener<ErrorCode>}): Promise<Expression| "null">

: Expression`expr`:`options`- dictionaries: Readonly<Dictionary>[];
- onError: ErrorListener<ErrorCode>;

**→**Promise<Expression| "null">

**format**Permalink

Transform an expression by applying one or more rewriting rules to it, recursively.

There are many ways to symbolically manipulate an expression, but transformations with `form`

have the following characteristics:

- they don’t require calculations or assumptions about the domain of free variables or the value of constants
- the output expression is expressed with more primitive functions, for example subtraction is replaced with addition

**format**(

`expr`: Expression,

`forms`: Form[],

`options`?: {dictionary: Dictionary; onError: ErrorListener<ErrorCode>}): Expression

: Expression`expr`: Form[]`forms`:`options`- dictionary: Dictionary;
- onError: ErrorListener<ErrorCode>;

**→**Expression

## class **ComputeEngine**Permalink

For best performance when calling repeatedly `format()`

or `evaluate()`

, create an instance of `ComputeEngine`

and call its methods. The constructor of `ComputeEngine`

will compile and optimize the dictionary so that calls of the `format()`

and `evaluate()`

methods will bypass that step. By contrast invoking the `format()`

and `evaluate()`

functions will compile the dictionary each time they are called.

### class **ComputeEngine**new **ComputeEngine**Permalink

Construct a new ComputeEngine environment.

If no `options.dictionaries`

is provided a default set of dictionaries will be used. The `ComputeEngine.getDictionaries()`

method can be called to access some subset of dictionaries, e.g. for arithmetic, calculus, etc… The order of the dictionaries matter: the definitions from the later ones override the definitions from earlier ones. The first dictionary should be the `'core'`

dictionary which include some basic definitions such as domains (‘Boolean’, ‘Number’, etc…) that are used by later dictionaries.

**ComputeEngine**(

`options`?: {dictionaries: Readonly<Dictionary>[]; onError: ErrorListener<ErrorCode>}): ComputeEngine

:`options`- dictionaries: Readonly<Dictionary>[];
- onError: ErrorListener<ErrorCode>;

**→**ComputeEngine

### class **ComputeEngine****canonical**Permalink

Format the expression to the canonical form.

In the canonical form, some operations are simplified (subtractions becomes additions of negative, division become multiplications of inverse, etc…) and terms are ordered using a deglex order. This can make subsequent operations easier.

: Expression`expr`**→**Expression

### class **ComputeEngine****domain**Permalink

Return the domain of the expression

: Expression`expr`**→**Expression

### class **ComputeEngine****evaluate**Permalink

Evaluate the expression `exp`

asynchronously.

Evaluating some expressions can take a very long time. Some can invole making network queries. Therefore to avoid blocking the main event loop, a promise is returned.

Use `result = await engine.evaluate(expr)`

to get the result without blocking.

: Expression`exp`**→**Promise<Expression>

### class **ComputeEngine****format**Permalink

Format the expression according to the specified forms.

If no form is provided, the expression is formatted with the ‘canonical’ form.

**format**(

`expr`: Expression,

`forms`?: "canonical" | "canonical-add" | "canonical-divide" | "canonical-domain" | "canonical-exp" | "canonical-list" | "canonical-multiply" | "canonical-power" | "canonical-negate" | "canonical-number" | "canonical-root" | "canonical-subtract" | "flatten" | "full" | "object-literal" | "sorted" | "stripped-metadata" | "sum-product" | Form[]): Expression

: Expression`expr`:`forms`- | "canonical"
- | "canonical-add"
- | "canonical-divide"
- | "canonical-domain"
- | "canonical-exp"
- | "canonical-list"
- | "canonical-multiply"
- | "canonical-power"
- | "canonical-negate"
- | "canonical-number"
- | "canonical-root"
- | "canonical-subtract"
- | "flatten"
- | "full"
- | "object-literal"
- | "sorted"
- | "stripped-metadata"
- | "sum-product"
- | Form[]

**→**Expression

### class **ComputeEngine****getDefinition**Permalink

: string`name`**→**FunctionDefinition

### class **ComputeEngine****getFunctionDefinition**Permalink

: string`name`**→**FunctionDefinition

### class **ComputeEngine****getSetDefinition**Permalink

: string`name`**→**SetDefinition

### class **ComputeEngine****getSymbolDefinition**Permalink

: string`name`**→**FunctionDefinition

### class **ComputeEngine****getVars**Permalink

Return the variables (free or not) in this expression

: Expression`expr`**→**Set<string>

### class **ComputeEngine****isSubsetOf**Permalink

Test if `lhs`

is a subset of `rhs`

.

`lhs`

and `rhs`

can be set expressions, i.e. `["SetMinus", "ComplexNumber", 0]`

: Expression`lhs`: Expression`rhs`**→**boolean

### class **ComputeEngine****popScope**Permalink

Remove the topmost scope from the scope stack.

**popScope**(): void

### class **ComputeEngine****pushScope**Permalink

Create a new scope and add it to the top of the scope stack

: Dictionary`dictionary`

### class **ComputeEngine****same**Permalink

Indicate if two expressions are structurally identical, using a literal symbolic identity.

Using a canonical format will result in more positive matches.

Two expressions are the same if:

- they have the same domain
- if they are numbers, if their value and domain are identical.
- if they are symbols, if their names are identical.
- if they are functions, if the head of the functions are identical, and if all the arguments are identical.

```
same(["Add", "x", 1], ["Add", 1, "x"])
// ➔ false
same(canonical(["Add", "x", 1]), canonical(["Add", 1, "x"]))`
// ➔ true
```

: Expression`lhs`: Expression`rhs`**→**boolean

### class **ComputeEngine****getDictionaries**Permalink

Return dictionaries suitable for the specified categories, or `"all"`

for all categories (`"arithmetic"`

, `"algebra"`

, etc…).

A symbol dictionary defines how the symbols and function names in a MathJSON expression should be interpreted, i.e. how to evaluate and manipulate them.

:`categories`- | DictionaryCategory[]
- | "all"

**→**Readonly<Dictionary>[]

### class **ComputeEngine**ComputeEngine.**context**Permalink

ScopeThe current scope.

A scope is a dictionary that contains the definition of local symbols.

Scopes form a stack, and definitions in more recent scopes can obscure definitions from older scopes.

### class **ComputeEngine**ComputeEngine.**onError**Permalink

ErrorListener<ErrorCode>The `onError`

function is called to signal an error

### Types

**BaseDefinition**Permalink

- domain: Domain;
- scope: Scope;
The scope this definition belongs to. This field is usually undefined, but its value is set by

`getDefinition()`

,`getFunctionDefinition()`

and`getSymbolDefinition()`

.- wikidata: string;
A short string indicating an entry in a wikibase. For example

`"Q167"`

is the wikidata entry for the Pi constant.

**CollectionDefinition**Permalink

- BaseDefinition &
- at: (
`index`: number): Expression; - countable: boolean;
If true, the size of the collection is finite.

- indexable: boolean;
If true, elements of the collection can be accessed with a numerical index with the

`at()`

function- isElementOf: (
`expr`: Expression): boolean; A predicate function that can be used to determine if an expression is a member of the collection or not (answers “True”, “False” or “Maybe”).

- iterable: boolean;
If true, the elements of the collection can be iterated over using the `iterator() function

- iterator: {done: (): boolean; next: (): Expression};
- size: (): number;
Return the number of elements in the collection.

- at: (

**CompiledDictionary**Permalink

The entries of a `CompiledDictionary`

have been validated and optimized for faster evaluation.

When a new scope is created with `pushScope()`

or when creating a new engine instance, new instances of `CompiledDictionary`

are created as needed.

**CompiledExpression**Permalink

- asyncEvaluate: (
`scope`: {}): Promise<Expression>; - evaluate: (
`scope`: {}): Expression;

**Definition**Permalink

**Dictionary**Permalink

A dictionary maps a MathJSON name to a definition.

A named entry in a dictionary can refer to a symbol, as in the expression, `"Pi"`

, to a function: “Add” in the expression `["Add", 2, 3]`

, or to a `"Set`

".

The name can be an arbitrary string of Unicode characters, however the following conventions are recommended:

- Use only letters, digits and
`-`

, and the first character should be a letter:`/^[a-zA-Z][a-zA-Z0-9-]+/`

- Built-in functions and symbols should start with an uppercase letter

As a shorthand for a numeric symbol definition, a number can be used as well. In that case the domain is determined automatically.

```
{ "x": 1.0 }
{ "x" : { "domain": "RealNumber", "value": 1.0 } }
```

- [
`name`: string]: number | Definition

**Domain**Permalink

A domain such as ‘Number’ or ‘Boolean’ represents a set of values.

Domains can be defined as a union or intersection of domains:

`["Union", "Number", "Boolean"]`

A number or a boolean.`["SetMinus", "Number", 1]`

Any number except “1”.

Domains are defined in a hierarchy (a lattice).

**Form**Permalink

A given mathematical expression can be represented in multiple equivalent ways as a MathJSON expression.

`Form`

is used to specify a representation:

: only transformations applied are those necessary to make it valid JSON (for example making sure that`'full'`

`Infinity`

and`NaN`

are represented as strings): associative functions are combined, e.g. f(f(a, b), c) -> f(a, b, c)`'flatten'`

: 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 -`'sorted'`

`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: any metadata associated with elements of the expression is removed.`'stripped-metadata'`

: each term of an expression is expressed as an object literal: no shorthand representation is used.`'object-literal'`

: `addition of 0 is simplified, associativity rules are applied, unnecessary groups are moved, single argument ‘add’ are simplified`'canonical-add'`

:`'canonical-divide'`

`divide`

is replaced with`multiply`

and `power’, division by 1 is simplified,:`'canonical-exp'`

`exp`

is replaced with`power`

: multiplication by 1 or -1 is simplified`'canonical-multiply'`

:`'canonical-power'`

`power`

with a first or second argument of 1 is simplified: real or complex number is replaced by the negative of that number. Negation of negation is simplified.`'canonical-negate'`

: complex numbers with no imaginary compnents are simplified`'canonical-number'`

:`'canonical-root'`

`root`

is replaced with`power`

:`'canonical-subtract'`

`subtract`

is replaced with`add`

and`negate`

: the following transformations are performed, in this order:`'canonical'`

- ‘canonical-number’, // ➔ simplify number
- ‘canonical-exp’, // ➔ power
- ‘canonical-root’, // ➔ power, divide
- ‘canonical-subtract’, // ➔ add, negate, multiply,
- ‘canonical-divide’, // ➔ multiply, power
- ‘canonical-power’, // simplify power
- ‘canonical-multiply’, // ➔ multiply, power
- ‘canonical-negate’, // simplify negate
- ‘canonical-add’, // simplify add
- ‘flatten’, // simplify associative, idempotent and groups
- ‘sorted’,
- ‘full’,

- | "canonical"
- | "canonical-add"
- | "canonical-divide"
- | "canonical-domain"
- | "canonical-exp"
- | "canonical-list"
- | "canonical-multiply"
- | "canonical-power"
- | "canonical-negate"
- | "canonical-number"
- | "canonical-root"
- | "canonical-subtract"
- | "flatten"
- | "full"
- | "object-literal"
- | "sorted"
- | "stripped-metadata"
- | "sum-product"

**FunctionDefinition**Permalink

- BaseDefinition &
- Partial<FunctionFeatures> &
- hold: "none" | "all" | "first" | "rest";
**‘none’**: Each of the arguments is evaluated.**‘all’**: The arguments will not be evaluated and will be passed as is.**‘first’**: The first argument is not evaluated, the others are**‘rest’**: The first argument is evaluated, the others aren’t

- sequenceHold: boolean;
If true,

`Sequence`

arguments are not automatically spliced in- signatures: FunctionSignature[];

**FunctionFeatures**Permalink

A function definition can have some flags set indicating specific properties of the function.

- additive: boolean;
If true, when the function is univariate,

`[f, ["Add", x, c]]`

where`c`

is constant, is simplified to`["Add", [f, x], c]`

.When the function is multivariate, additivity is considered only on the first argument:

`[f, ["Add", x, c], y]`

simplifies to`["Add", [f, x, y], c]`

.Default: false

- associative: boolean;
If true, [f, [f, a], b] simplifies to [f, a, b]

Default: false

- commutative: boolean;
If true, [f, a, b] simplifies to [f, b, a]

Default: false

- idempotent: boolean;
If true,

`[f, [f, x]]`

simplifies to`[f, x]`

.Default: false

- involution: boolean;
If true,

`[f, [f, x]]`

simplifies to`x`

.Default: false

- multiplicative: boolean;
If true, when the function is univariate,

`[f, ["Multiply", x, y]]`

simplifies to`["Multiply", [f, x], [f, y]]`

.When the function is multivariate, multipicativity is considered only on the first argument:

`[f, ["Multiply", x, y], z]`

simplifies to`["Multiply", [f, x, z], [f, y, z]]`

Default: false

- outtative: boolean;
If true, when the function is univariate,

`[f, ["Multiply", x, c]]`

simplifies to`["Multiply", [f, x], c]`

where`c`

is constantWhen the function is multivariate, multiplicativity is considered only on the first argument:

`[f, ["Multiply", x, y], z]`

simplifies to`["Multiply", [f, x, z], [f, y, z]]`

Default: false

- pure: boolean;
If true, invoking the function with a given set of arguments will always return the same value, i.e. ‘Sin’ is pure, ‘Random’ isn’t. This is used to cache the result of the function.

Default: true

- threadable: boolean;
If true, the function is applied element by element to lists, matrices and equations.

Default: false

**FunctionSignature**Permalink

Function signature: definition of the inputs and output of a function.

A function should have at least one signature, but can have several:

`Add(RealNumber, RealNumber): RealNumber`

`Add(ComplexNumber, ComplexNumber): ComplexNumber`

- etc…

The signature of a function that accepts any input and may output anything is: `{ rest: "Anything", result: "Anything" }`

.

- args: Domain | [
**name**: string,**domain**: Domain][]; Input arguments

- asyncEvaluate: (
`engine`: ComputeEngine, ...`args`: Expression[]): Promise<Expression>; Evaluate the function with the passed in arguments and return a corresponding result.

- compile: (
`engine`: ComputeEngine, ...`args`: CompiledExpression[]): CompiledExpression; Return a compiled (optimized) function for evaluation

- dimension: (
`engine`: ComputeEngine, ...`args`: Expression[]): Expression; Dimensional analysis

- evaluate: (
`engine`: ComputeEngine, ...`args`: Expression[]): Expression; Evaluate the function with the passed in arguments and return a corresponding result.

- rest: Domain | [
**name**: string,**domain**: Domain]; If this signature accepts unlimited additional arguments after the named arguments, they should be of this domain

- result: Domain | (
`engine`: ComputeEngine, ...`args`: Expression[]): Expression; Domain result computation

**Scope**Permalink

A scope is a set of names in a dictionary that are bound (defined) in a MathJSON expression.

Scopes are arranged in a stack structure. When an expression that defined a new scope is evaluated, the new scope is added to the scope stack. Outside of the expression, the scope is removed from the scope stack.

The scope stack is used to resolve symbols, and it is possible for a scope to ‘mask’ definitions from previous scopes.

Scopes are lexical (also called a static scope): they are defined based on where they are in an expression, they are not determined at runtime.

- dictionary: CompiledDictionary;
- parentScope: Scope;

**SetDefinition**Permalink

- CollectionDefinition &
- isSubsetOf: (
`engine`: ComputeEngine,`lhs`: Expression,`rhs`: Expression): boolean; A function that determins if a set is a subset of another. The

`rhs`

argument is either the name of the symbol, or a function with the head of the symbol.- supersets: string[];
The supersets of this set: they should be symbol with a ‘Set’ domain

- value: Expression;
If a set can be defined explicitely in relation to other sets, the

`value`

represents that relationship. For example “NaturalNumber” = [“Union”, “PrimeNumber”, “CompositeNumber”].

- isSubsetOf: (

**SymbolDefinition**Permalink

- BaseDefinition &
- SymbolFeatures &
- unit: Expression;
For dimensional analysis, e.g. “Scalar”, “Meter”, [“Divide”, “Meter”, “Second”]

- value: Expression;

**SymbolFeatures**Permalink

- constant: boolean;
If true the value of the symbol is constant.

If false, the symbol is a variable.

`grok`