compute-engine

Functions

evaluate

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<T>, options?: {dictionaries: Readonly<Dictionary<T>>[]}): Promise<Expression<T> | "null">
expr: Expression<T>
options:
dictionaries: Readonly<Dictionary<T>>[];
Promise<Expression<T> | "null">

format

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<T>, forms: Form[], options?: {dictionaries: Readonly<Dictionary<T>>[]}): Expression<T>
expr: Expression<T>
forms: Form[]
options:
dictionaries: Readonly<Dictionary<T>>[];
Expression<T>

class ComputeEngine

Create a CustomEngine instance to customize its behavior and the syntax and operation dictionaries it uses.

The constructor of ComputeEngine will compile and optimize the dictionary upfront.

class ComputeEnginenew ComputeEngine

Construct a new ComputeEngine environment.

If no options.dictionaries is provided a default set of dictionaries is 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.

new ComputeEngine(options?: {dictionaries: Readonly<Dictionary<T>>[]}): ComputeEngine<T>
options:
dictionaries: Readonly<Dictionary<T>>[];
ComputeEngine<T>

class ComputeEngineget/set precision

precision: number

The default precision of the compute engine: the number of significant digits when performing numeric evaluations, such as when calling ce.N().

To make calculations using machine floating point representation, set precision to "machine" (15 by default).

To make calculations using more digits, at the cost of expended memory usage and slower computations, set the precision higher.

Trigonometric operations are accurate for precision up to 1,000.

Some functions, such as ce.N() have an option to specify the precision. If no precision is specified in these functions, the default precision of the compute engine is used.

class ComputeEngineN

Return a numerical approximation of an expression.

N(exp: Expression<T>, options?: {precision: number}): Expression<T>
exp: Expression<T>
options:
precision: number;
Expression<T>

class ComputeEngineask

Return a list of all the assumptions that match a pattern.

 ce.assume(x, 'PositiveInteger');
 ce.ask(['Greater', 'x', '_val'])
 //  -> [{'val': 0}]
ask(pattern: Expression<T>): Substitution<T>[]
pattern: Expression<T>
Substitution<T>[]

class ComputeEngineassume

Add an assumption.

Return contradiction if the new assumption is incompatible with previous ones.

Return tautology if the new assumption is redundant with previous ones.

Return ok if the assumption was successfully added to the assumption set.

Note that the assumption is put into normal form before being added.

assume(symbol: Expression<T>, domain: Domain<number>): "contradiction" | "tautology" | "ok"
symbol: Expression<T>
domain: Domain<number>
"contradiction" | "tautology" | "ok"

assume(predicate: Expression<T>): "contradiction" | "tautology" | "ok"
predicate: Expression<T>
"contradiction" | "tautology" | "ok"

assume(arg1: Expression<T>, arg2?: Domain<number>): "contradiction" | "tautology" | "ok"
arg1: Expression<T>
arg2: Domain<number>
"contradiction" | "tautology" | "ok"

class ComputeEnginecanonical

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.

canonical(expr: Expression<T>): Expression<T>
expr: Expression<T>
Expression<T>

class ComputeEnginecheckContinueExecution

checkContinueExecution(): void

class ComputeEnginedomain

Return the domain of the expression

domain(expr: Expression<T>): Expression<T>
expr: Expression<T>
Expression<T>

class ComputeEngineevaluate

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.

evaluate(expr: Expression<T>, options?: {iterationLimit: number; timeLimit: number}): Promise<Expression<T>>
expr: Expression<T>
options:
iterationLimit: number;
timeLimit: number;
Promise<Expression<T>>

class ComputeEngineformat

Format the expression according to the specified forms.

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

format(expr: Expression<T>, forms?: Form | Form[]): Expression<T>
expr: Expression<T>
forms:
Expression<T>

class ComputeEnginegetCollectionDefinition

getCollectionDefinition(name: string): CollectionDefinition<T>
name: string
CollectionDefinition<T>

class ComputeEnginegetDefinition

getDefinition(name: string): Definition<T>
name: string
Definition<T>

class ComputeEnginegetFunctionDefinition

getFunctionDefinition(name: string): FunctionDefinition<number>
name: string
FunctionDefinition<number>

class ComputeEnginegetSetDefinition

getSetDefinition(name: string): SetDefinition<number>
name: string
SetDefinition<number>

class ComputeEnginegetSymbolDefinition

getSymbolDefinition(name: string): SymbolDefinition<T>
name: string
SymbolDefinition<T>

class ComputeEnginegetVars

getVars(expr: Expression<T>): Set<string>
expr: Expression<T>
Set<string>

class ComputeEngineis

Determines if the predicate is satisfied based on the known assumptions.

Return undefined if the value of the predicate cannot be determined.

ce.is(["Equal", "x", 0]);
ce.is(["Equal", 3, 4]);
is(symbol: Expression<T>, domain: Domain<number>): boolean
symbol: Expression<T>
domain: Domain<number>
boolean

is(predicate: Expression<T>): boolean
predicate: Expression<T>
boolean

is(arg1: Expression<T>, arg2?: Domain<number>): boolean
arg1: Expression<T>
arg2: Domain<number>
boolean

class ComputeEngineisEqual

isEqual(lhs: Expression<T>, rhs: Expression<T>): boolean
lhs: Expression<T>
rhs: Expression<T>
boolean

class ComputeEngineisGreater

isGreater(lhs: Expression<T>, rhs: Expression<T>): boolean
lhs: Expression<T>
rhs: Expression<T>
boolean

class ComputeEngineisGreaterEqual

isGreaterEqual(lhs: Expression<T>, rhs: Expression<T>): boolean
lhs: Expression<T>
rhs: Expression<T>
boolean

class ComputeEngineisLess

isLess(lhs: Expression<T>, rhs: Expression<T>): boolean
lhs: Expression<T>
rhs: Expression<T>
boolean

class ComputeEngineisLessEqual

isLessEqual(lhs: Expression<T>, rhs: Expression<T>): boolean
lhs: Expression<T>
rhs: Expression<T>
boolean

class ComputeEngineisSubsetOf

isSubsetOf(lhs: Domain<number>, rhs: Domain<number>): boolean
lhs: Domain<number>
rhs: Domain<number>
boolean

class ComputeEnginepopScope

Remove the topmost scope from the scope stack.

popScope(): void

class ComputeEnginepushScope

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

pushScope(dictionary: Readonly<Dictionary<T>>, scope?: Partial<Scope>): void
dictionary: Readonly<Dictionary<T>>
scope: Partial<Scope>

class ComputeEnginereplace

Apply repeatedly a set of rules to an expression.

replace(rules: RuleSet<T>, expr: Expression<T>): Expression<T>
rules: RuleSet<T>
expr: Expression<T>
Expression<T>

class ComputeEngineshouldContinueExecution

Return false if the execution should stop.

This can occur if:

  • an error has been signaled
  • the time limit or memory limit has been exceeded
shouldContinueExecution(): boolean
boolean

class ComputeEnginesignal

Call this function if an unexpected condition occurs during execution of a function in the engine.

An ErrorSignal is a problem that cannot be recovered from.

A WarningSignal indicates a minor problem that does not prevent the execution to continue.

signal(sig: WarningSignal | ErrorSignal): void
sig:

class ComputeEnginesimplify

Simplify an expression.

simplify(exp: Expression<T>, options?: {iterationLimit: number; simplifications: Simplification[]; timeLimit: number}): Expression<T>
exp: Expression<T>
options:
iterationLimit: number;
simplifications: Simplification[];
timeLimit: number;
Expression<T>

class ComputeEnginegetDictionaries

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.

getDictionaries(categories: DictionaryCategory[] | "all"): Readonly<Dictionary<any>>[]
categories:
Readonly<Dictionary<any>>[]

class ComputeEngineComputeEngine.assumptions

ExpressionMap<T, boolean>

class ComputeEngineComputeEngine.context

RuntimeScope<T>

The 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 ComputeEngineComputeEngine.deadline

number

Absolute time beyond which evaluation should not proceed

class ComputeEngineComputeEngine.iterationLimit

number

class ComputeEngineComputeEngine.numericFormat

NumericFormat

Internal format to represent numbers:

  • auto: the best format is determined based on the calculations to perform and the requested precision.
  • number: use the machine format (64-bit float, 52-bit, about 15 digits of precision).
  • decimal: arbitrary precision floating-point numbers, as provided by the “decimal.js” library
  • complex: complex numbers: two 64-bit float, as provided by the “complex.js” library

class ComputeEngineComputeEngine.recursionLimit

number

class ComputeEngineComputeEngine.timeLimit

number

Types

BaseDefinition

<T extends number> =
domain: Domain<T> | (...args: Expression<T>[]): Domain<T>;
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 representing an entry in a wikibase.

For example Q167 is the wikidata entry for the Pi constant.

CollectionDefinition

<T extends number> =
  • BaseDefinition<T> &
  • at: (index: number): Expression<T>;
    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<T>): boolean;

    A predicate function 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<T>};
    size: (): number;

    Return the number of elements in the collection.

CompiledDictionary

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.


<T extends number> = Map<string, Definition<T>>

CompiledExpression

<T extends number> =
asyncEvaluate: (scope: {}): Promise<T | Expression<T>>;
evaluate: (scope: {}): Expression<T>;

Definition

Dictionary

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 } }

<T extends number> =
[name: string]: T | Definition<T>

Domain

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).


<T extends number> = Expression<T>

Form

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

Learn more about Canonical Forms.


  • | "canonical"
  • | "canonical-add"
  • | "canonical-boolean"
  • | "canonical-constants"
  • | "canonical-divide"
  • | "canonical-domain"
  • | "canonical-exp"
  • | "canonical-list"
  • | "canonical-multiply"
  • | "canonical-power"
  • | "canonical-negate"
  • | "canonical-number"
  • | "canonical-rational"
  • | "canonical-root"
  • | "canonical-subtract"
  • | "canonical-domain"
  • | "flatten"
  • | "json"
  • | "object-literal"
  • | "sorted"
  • | "stripped-metadata"
  • | "sum-product"

FunctionDefinition

<T extends number> =
  • BaseDefinition<T> &
  • Partial<FunctionFeatures> &
  • compile: (engine: ComputeEngine, ...args: CompiledExpression<T>[]): CompiledExpression<T>;

    Return a compiled (optimized) function.

    dimension: (engine: ComputeEngine, ...args: Expression<T>[]): Expression<T>;

    Dimensional analysis

    evalComplex: (engine: ComputeEngine, ...args: number | Complex[]): Complex;

    Like evalNumber() but for Complex numbers

    evalDecimal: (engine: ComputeEngine, ...args: number | Decimal[]): Decimal;

    Live evalNumber() but for Decimal numbers (arbitrary large floating point numbers).

    evalNumber: (engine: ComputeEngine, ...args: number[]): number;

    Make a numeric evaluation of the arguments.

    The passed-in arguments have already been numerically evaluated unless the arguments have a hold property.

    If the function is numeric all the arguments are guaranteed to be numbers and the function should return a number.

    evaluate: (engine: ComputeEngine, ...args: Expression<T>[]): Expression<T>;

    Evaluate the arguments.

    This will be invoked by the ce.evaluate() function, and after the simplify() and evalNumber() definition methods have been called.

    If a function must perform any computations that may take a long time (>100ms), because they are computationally expensive, or because they require a network fetch, defer these computations to ce.evaluate() rather than ce.simplify().

    If a synchronous ce.evaluate() function is provided it will be used and ce.evaluateAsync() will not be called.

    The arguments have been simplified and numerically evaluated, except the arguments to which a hold apply.

    evaluateAsync: (engine: ComputeEngine, ...args: Promise<Expression<T>>[]): Promise<Expression<T>>;
    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
    inputDomain: Domain[];

    The number and domains of the arguments for this function.

    range: Domain<T> | (engine: ComputeEngine, ...args: Expression<T>[]): Expression<T>;

    The domain of the result.

    If range is a function, the arguments of range() are the the arguments of the function. The range() function can make use of available assumptions to determine its result.

    The range should be as precise as possible. A range of Anything is correct, but won’t be very helpful.

    A range of Number is good, a range of RealNumber is better and a range of ["Interval", 0, "+Infinity"] is even better.

    sequenceHold: boolean;

    If true, Sequence arguments are not automatically spliced in

    simplify: (engine: ComputeEngine, ...args: Expression<T>[]): Expression<T>;

    Rewrite the expression into a simplified form.

    If appropriate, make use of assumptions with ce.is().

    Do not resolve the values of variables, that is ce.simplify("x+1") is x + 1 even if x = 0. However, resolving constants is OK.

    Do not make approximate evaluations (i.e. floating point operations).

    Do not perform complex or lengthy operations: do these in ce.evaluate().

    Only make simple rewrites of the expression.

    The passed-in arguments have been simplified already, except for those to which a hold apply.

    value: T | Expression;

    The value of this function, as a lambda function. The arguments are _, _2, _3, etc…

    This property may be used to perform some simplification, or to numerically evaluate the function if no evalNumber property is provided.

FunctionFeatures

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

numeric: boolean;

If true, the input arguments and the result are expected to be number.

Default: false

outtative: boolean;

If true, when the function is univariate, [f, ["Multiply", x, c]] simplifies to ["Multiply", [f, x], c] where c is constant

When 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

Numeric

NumericFormat

  • | "auto"
  • | "machine"
  • | "decimal"
  • | "complex"

Pattern

<T extends number> = Expression<T>

Rule

<T extends number> = [lhs: Pattern<T>, rhs: Pattern<T>, condition: (ce: ComputeEngine<T>, sub: Substitution<T>): boolean]

RuleSet

<T extends number> = Iterable<Rule<T>>

RuntimeScope

<T extends number> =
  • Scope &
  • assumptions: undefined | ExpressionMap<T, boolean>;
    dictionary: CompiledDictionary<T>;
    lowWaterMark: number;

    Free memory should not go below this level for execution to proceed

    origin: {column: number; line: number; name: string};

    The location of the call site that created this scope

    parentScope: RuntimeScope<T>;
    warnings: WarningSignal[];

    Set when one or more warnings have been signaled in this scope

Scope

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.


iterationLimit: number;

Signal iteration-limit-exceeded when the iteration limit for this scope is exceeded. Default: no limits.

memoryLimit: number;

Signal out-of-memory when the memory usage for this scope is exceeded. Memory in Megabytes, default: 1Mb.

recursionLimit: number;

Signal recursion-depth-exceeded when the recursion depth for this scope is exceeded.

timeLimit: number;

Signal timeout when the execution time for this scope is exceeded. Time in seconds, default 2s.

warn: WarningSignalHandler;

This handler is invoked when exiting this scope if there are any warnings pending.

SetDefinition

<T extends number> =
  • CollectionDefinition<T> &
  • isSubsetOf: (engine: ComputeEngine, lhs: Expression<T>, rhs: Expression<T>): 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<T>;

    If a set can be defined explicitely in relation to other sets, the value represents that relationship. For example "NaturalNumber" = ["Union", "PrimeNumber", "CompositeNumber"].

Simplification

  • | "all"
  • | "arithmetic"

SymbolDefinition

<T extends number> =

SymbolFeatures

constant: boolean;

If true the value of the symbol is constant.

If false, the symbol is a variable.

hold: boolean;

If false, the value of the symbol is substituted during a ce.simplify(). If true, the symbol is unchanged during a ce.simplify()and the value is only used during ace.N()orce.evaluate()`.

True by default;

Documentation built with grok