Expressions

Mathematical expressions in Myokit are represented as trees of Expression objects. For example the expression 5 + 2 is represented as a Plus expression with two operands of the type Number. All expressions extend the Expression base class described below.

Creating expression trees manually is a labour-intesive process. In most cases, expressions will be created by the parser.

class myokit.Expression(operands=None)

Abstract class

Myokit’s most generic interface for expressions. All expressions extend this class.

Expressions are immutable objects.

Expression objects have an _rbp property determining their right binding power (myokit uses a top-down operator precedence parsing scheme) and an optional _token property that may contain the text token this expression object was originally parsed from.

bracket(op=None)

Returns True if this operator requires brackets. For example, 5 + 3 should return True, since 2 * 5 + 3 != 2 * (5 + 3) while sin(3) should return False.

clone(subst=None, expand=False, retain=None)

Clones this expression.

The optional argument subst can be used to pass a dictionary mapping expressions to a substitute. Any expression that finds itself listed as a key in the dictionary will return this replacement value instead.

The argument expand can be set to True to expand all variables other than states. For example, if x = 5 + 3 * y and y = z + sqrt(2) and dot(z) = ..., cloning x while expanding will yield x = 5 + 3 * (z + sqrt(2)). When expanding, all constants are converted to numerical values. To maintain some of the constants, pass in a list of variables or variable names as retain.

Substitution takes precedence over expansion: A call such as e.clone(subst={x:y}, expand=True) will replace ``x by y but not expand any names appearing in y.

code(component=None)

Returns this expression formatted in mmt syntax.

When LhsExpressions are encountered, their full qname is rendered, except in two cases: (1) if the variable’s component matches the argument component or (2) if the variable is nested. Aliases are used in place of qnames if found in the given component.

contains_type(kind)

Returns True if this expression tree contains an expression of the given type.

depends_on(lhs)

Returns True if this Expression depends on the given LhsExpresion.

eval(subst=None, precision=64, ignore_errors=False)

Evaluates this expression and returns the result. This operation will fail if the expression contains any Names that do not resolve to numerical values.

The optional argument subst can be used to pass a dictionary mapping expressions to their results. Calling eval on an expression listed as a key in the dictionary will return the stored result.

For debugging purposes, the argument precision can be set to myokit.SINGLE_PRECISION to perform the evaluation with 32 bit floating point numbers.

By default, evaluations are performed using error checking: a myokit.NumericalError is raised on divide-by-zeros, invalid operations (like 0/0) and overflows (but not underflows). To run an evaluation without error checking, set ignore_errors=True.

eval_unit(mode=1)

Evaluates the unit this expression should have, based on the units of its variables and literals.

Incompatible units may result in a EvalUnitError being raised. The method for dealing with unspecified units can be set using the mode argument.

Using myokit.UNIT_STRICT any unspecified unit will be treated as dimensionless. For example adding None + [kg] will be treated as [1] + [kg] which will raise an error. Similarly, None * [m] will be taken to mean [1] * [m] which is valid, and None * None will return [1]. In strict mode, functions such as exp(), which expect dimensionless input will raise an error if given a non-dimensionless operator.

Using myokit.UNIT_TOLERANT unspecified units will try to be ignored where possible. For example, the expression None + [kg] will be treated as [kg] + [kg], while None * [m] will be read as [1] * [m] and None * None will return None. Functions such as exp() will not raise an error, but simply return a dimensionless value.

The method is intended to be used to check the units in a model, so every branch of an expression is evaluated, even if it won’t affect the final result.

is_conditional()

Returns True if and only if this expression’s tree contains a conditional statement.

is_constant()

Returns true if this expression contains no references or only references to variables with a constant value.

is_literal()

Returns True if this expression doesn’t contain any references.

is_state_value()

Returns True if this expression is a Name pointing to the current value of a state variable.

operator_rep()

Returns a representation of this expression’s type. (For example ‘+’ or ‘*’)

pyfunc(use_numpy=True)

Converts this expression to python and returns the new function’s handle.

By default, when converting mathematical functions such as log, the version from numpy (i.e. numpy.log) is used. To use the built-in math module instead, set use_numpy=False.

pystr(use_numpy=False)

Returns a string representing this expression in python syntax.

By default, built-in functions such as ‘exp’ are converted to the python version ‘math.exp’. To use the numpy versions, set numpy=True.

references()

Returns a set containing all references to variables made in this expression.

tree_str()

Returns a string representing the parse tree corresponding to this expression.

validate()

Validates operands, checks cycles without following references. Will raise exceptions if errors are found.

walk(allowed_types=None)

Returns an iterator over this expression tree (depth-first). This is a slow operation. Do _not_ use in performance sensitive code!

Example:

5 + (2 * sqrt(x))

1) Plus
2) Number(5)
3) Multiply
4) Number(2)
5) Sqrt
6) Name(x)

To return only expressions of certain types, pass in a sequence allowed_typess, containing all types desired in the output.

Names and numbers

The simplest types of expression are atomic expressions, which have either a definite, numerical value (Number) or point to a variable (Name).

For equations a distinction is made between what may appear on the left-hand side (lhs) and right-hand side (rhs). To indicate this difference in code, all left-hand side equations must extend the class LhsExpression.

class myokit.Number(value, unit=None)

Extends: Expression

Represents a number with an optional unit for use in Myokit expressions. All numbers used in Myokit expressions are floating point.

>>> import myokit
>>> x = myokit.Number(10)
>>> print(x)
10
>>> x = myokit.Number(5.00, myokit.units.V)
>>> print(x)
5 [V]

Arguments:

value
A numerical value (something that can be converted to a float). Number objects are immutable so no clone constructor is provided.
unit
A unit to associate with this number. If no unit is specified the number’s unit will be left undefined.
convert(unit)

Returns a copy of this number in a different unit. If the two units are not compatible a myokit.IncompatibleUnitError is raised.

unit()

Returns the unit associated with this number/quantity or None if no unit was specified.

class myokit.LhsExpression(operands=None)

Abstract class, extends: Expression

An expression referring to the left-hand side of an equation.

Running eval() on an LhsExpression returns the evaluation of the associated right-hand side. This may result in errors if no right-hand side is defined. In other words, this will only work if the expression is embedded in a variable’s defining equation.

rhs()

Returns the rhs expression equal to this lhs expression.

var()

Returns the variable referenced by this LhsExpression. For Name objects this will be equal to the left hand side of their defining equation, for derivatives this will be the variable they represent the the derivative of.

class myokit.Name(value)

Extends: LhsExpression

Represents a reference to a variable.

class myokit.Derivative(op)

Extends: LhsExpression

Represents a reference to the time-derivative of a variable.

Operators

class myokit.PrefixExpression(op)

Abstract class, extends: Expression

Base class for prefix expressions: expressions with a single operand.

class myokit.InfixExpression(left, right)

Abstract class, extends: Expression

Base class for for infix expressions: <left> operator <right>.

The order of the operands may matter, so that <left> operator <right> is not always equal to <right> operator <left>.

Functions

class myokit.Function(*ops)

Abstract class, extends: Expression

Base class for built-in functions.

Functions have a name, which must be set to a human readable function name (usually just the function’s .mmt equivalent) and a list of integers called _nargs. Each entry in _nargs specifies a number of arguments for which the function is implemented. For example Sin has _nargs=[1] while Log has _nargs=[1,2], showing that Log can be called with either 1 or 2 arguments.

If errors occur when creating a function, an IntegrityError may be thrown.

Conditions

class myokit.Condition

Abstract class

Interface for conditional expressions that can be evaluated to True or False. Doesn’t add any methods but simply indicates that this is a condition.

class myokit.PrefixCondition(op)

Abstract class, extends: Condition, PrefixExpression

Interface for prefix conditions.

class myokit.InfixCondition(left, right)

Abstract class, extends: Condition, InfixExpression

Base class for infix expressions.

Unary plus and minus

class myokit.PrefixPlus(op)

Extends: PrefixExpression

Prefixed plus. Indicates a positive number +op.

>>> from myokit import *
>>> x = PrefixPlus(Number(10))
>>> print(x.eval())
10.0
class myokit.PrefixMinus(op)

Extends: PrefixExpression

Prefixed minus. Indicates a negative number -op.

>>> from myokit import *
>>> x = PrefixMinus(Number(10))
>>> print(x.eval())
-10.0

Addition and multiplication

class myokit.Plus(left, right)

Extends: InfixExpression

Represents the addition of two operands: left + right.

>>> from myokit import *
>>> x = parse_expression('5 + 2')
>>> print(x.eval())
7.0
class myokit.Minus(left, right)

Extends: InfixExpression

Represents subtraction: left - right.

>>> from myokit import *
>>> x = parse_expression('5 - 2')
>>> print(x.eval())
3.0
class myokit.Multiply(left, right)

Extends: InfixExpression

Represents multiplication: left * right.

>>> from myokit import *
>>> x = parse_expression('5 * 2')
>>> print(x.eval())
10.0
class myokit.Divide(left, right)

Extends: InfixExpression

Represents division: left / right.

>>> from myokit import *
>>> x = parse_expression('5 / 2')
>>> print(x.eval())
2.5

Powers and roots

class myokit.Power(left, right)

Extends: InfixExpression

Represents exponentiation: left ^ right.

>>> import myokit
>>> x = myokit.parse_expression('5 ^ 2')
>>> print(x.eval())
25.0
class myokit.Sqrt(*ops)

Extends: Function

Represents the square root sqrt(x).

>>> import myokit
>>> x = myokit.parse_expression('sqrt(25)')
>>> print(x.eval())
5.0

Logarithms and e

class myokit.Exp(*ops)

Extends: UnaryDimensionlessFunction

Represents a power of e. Written exp(x) in .mmt syntax.

>>> from myokit import *
>>> x = Exp(Number(1))
>>> print(round(x.eval(), 4))
2.7183
class myokit.Log(*ops)

Extends: Function

With one argument log(x) represents the natural logarithm. With two arguments log(x, k) is taken to be the base k logarithm of x.

>>> from myokit import *
>>> x = Log(Number(10))
>>> print(round(x.eval(), 4))
2.3026
>>> x = Log(Exp(Number(10)))
>>> print(round(x.eval(), 1))
10.0
>>> x = Log(Number(256), Number(2))
>>> print(round(x.eval(), 1))
8.0
class myokit.Log10(*ops)

Extends: UnaryDimensionlessFunction

Represents the base-10 logarithm log10(x).

>>> from myokit import *
>>> x = Log10(Number(100))
>>> print(round(x.eval(), 1))
2.0

Trigonometric functions

All trigonometric functions use angles in radians.

class myokit.Sin(*ops)

Extends: UnaryDimensionlessFunction

Represents the sine function sin(x).

>>> from myokit import *
>>> x = parse_expression('sin(0)')
>>> print(round(x.eval(), 1))
0.0
>>> x = Sin(Number(3.1415 / 2.0))
>>> print(round(x.eval(), 1))
1.0
class myokit.Cos(*ops)

Extends: UnaryDimensionlessFunction

Represents the cosine function cos(x).

>>> from myokit import *
>>> x = Cos(Number(0))
>>> print(round(x.eval(), 1))
1.0
>>> x = Cos(Number(3.1415 / 2.0))
>>> print(round(x.eval(), 1))
0.0
class myokit.Tan(*ops)

Extends: UnaryDimensionlessFunction

Represents the tangent function tan(x).

>>> from myokit import *
>>> x = Tan(Number(3.1415 / 4.0))
>>> print(round(x.eval(), 1))
1.0
class myokit.ASin(*ops)

Extends: UnaryDimensionlessFunction

Represents the inverse sine function asin(x).

>>> from myokit import *
>>> x = ASin(Sin(Number(1)))
>>> print(round(x.eval(), 1))
1.0
class myokit.ACos(*ops)

Extends: UnaryDimensionlessFunction

Represents the inverse cosine acos(x).

>>> from myokit import *
>>> x = ACos(Cos(Number(3)))
>>> print(round(x.eval(), 1))
3.0
class myokit.ATan(*ops)

Extends: UnaryDimensionlessFunction

Represents the inverse tangent function atan(x).

>>> from myokit import *
>>> x = ATan(Tan(Number(1)))
>>> print(round(x.eval(), 1))
1.0

If two arguments are given they are interpreted as the coordinates of a point (x, y) and the function returns this point’s angle with the (positive) x-axis. In this case, the returned value will be in the range (-pi, pi].

Conditional operators

class myokit.If(i, t, e)

Extends: Function

Allows conditional functions to be defined using an if-then-else structure.

The first argument to an If function must be a condition, followed directly by an expression to use to calculate the function’s return value if this condition is True. The third and final argument specifies the expression’s value if the condition is False.

A simple example in .mmt syntax:

x = if(V < 10, 5 * V + 100, 6 * V)
condition()

Returns this if-function’s condition.

piecewise()

Returns an equivalent Piecewise object.

value(which)

Returns the expression used when this if’s condition is True when called with which=True. Otherwise return the expression used when this if’s condition is False.

class myokit.Piecewise(*ops)

Extends: Function

Allows piecewise functions to be defined.

The first argument to a Piecewise function must be a condition, followed directly by an expression to use to calculate the function’s return value if this condition is true.

Any number of condition-expression pairs can be added. If multiple conditions evaluate as true, only the first one will be used to set the return value.

The final argument should be a default expression to use if none of the conditions evaluate to True. This means the piecewise() function can have any odd number of arguments greater than 2.

A simple example in mmt syntax:

x = piecewise(
    V < 10, 5 * V + 100
    V < 20, 6 * V,
    7 * V)

This will return 5 * V + 100 for any value smaller than 10, 6 * V for any value greater or equal to 10 but smaller than 20, and 7 * V for any values greather than or equal to 20.

conditions()

Returns an iterator over the conditions used by this Piecewise.

pieces()

Returns an iterator over the pieces in this Piecewise.

class myokit.OrderedPiecewise(*ops)

Extends: Function

An ordered piecewise function is defined as:

y = opiecewise(x,
    f[0](x), z[0],
    f[1](x), z[1],
    ...,
    f[n-1](x), z[n-1]
    f[n](x)
    )

Here x is a variable whose domain is split into segments by the strictly increasing collection of points z[i]. When x < z[i] for i = 0, 1, ..., n-1 the returned value is calculated from f[i]. When x >= z[n-1] the returned value is obtained from f[n].

The points z[i] split the range of x into a continuous series of segments. This structure allows for efficient evaluation using bisection trees. The Piecewise class implements a more general piecewise function, that poses no restrictions on the type of condition used to select an evaluation function.

count_pieces()

Returns the number of pieces in this piecewise function.

if_tree()

Returns this expression as a tree of If objects.

piecewise()

Returns this expression as a Piecewise object.

var()

Returns this object’s conditional variable.

class myokit.Not(op)

Extends: PrefixCondition

Negates a condition. Written as not x.

>>> from myokit import *
>>> x = parse_expression('1 == 1')
>>> print(x.eval())
True
>>> y = Not(x)
>>> print(y.eval())
False
>>> x = parse_expression('(2 == 2) and not (1 > 2)')
>>> print(x.eval())
True
class myokit.Equal(left, right)

Extends: InfixCondition

Represents an equality check x == y.

>>> from myokit import *
>>> print(parse_expression('1 == 0').eval())
False
>>> print(parse_expression('1 == 1').eval())
True
class myokit.NotEqual(left, right)

Extends: InfixCondition

Represents an inequality check x != y.

>>> from myokit import *
>>> print(parse_expression('1 != 0').eval())
True
>>> print(parse_expression('1 != 1').eval())
False
class myokit.More(left, right)

Extends: InfixCondition

Represents an is-more-than check x > y.

>>> from myokit import *
>>> print(parse_expression('5 > 2').eval())
True
class myokit.Less(left, right)

Extends: InfixCondition

Represents an is-less-than check x < y.

>>> from myokit import *
>>> print(parse_expression('5 < 2').eval())
False
class myokit.MoreEqual(left, right)

Extends: InfixCondition

Represents an is-more-than-or-equal check x > y.

>>> from myokit import *
>>> print(parse_expression('2 >= 2').eval())
True
class myokit.LessEqual(left, right)

Extends: InfixCondition

Represents an is-less-than-or-equal check x <= y.

>>> from myokit import *
>>> print(parse_expression('2 <= 2').eval())
True
class myokit.And(left, right)

Extends: InfixCondition

True if two conditions are true: x and y.

>>> from myokit import *
>>> print(parse_expression('1 == 1 and 2 == 4').eval())
False
>>> print(parse_expression('1 == 1 and 4 == 4').eval())
True
class myokit.Or(left, right)

Extends: InfixCondition

True if at least one of two conditions is true: x or y.

>>> from myokit import *
>>> print(parse_expression('1 == 1 or 2 == 4').eval())
True

Miscellaneous

class myokit.Abs(*ops)

Extends: Function

Returns the absolute value of a number abs(x).

>>> from myokit import *
>>> x = parse_expression('abs(5)')
>>> print(x.eval())
5.0
>>> x = parse_expression('abs(-5)')
>>> print(x.eval())
5.0
class myokit.Floor(*ops)

Extends: Function

Represents a rounding towards minus infinity floor(x).

>>> from myokit import *
>>> x = Floor(Number(5.2))
>>> print(x.eval())
5.0
>>> x = Floor(Number(-5.2))
>>> print(x.eval())
-6.0
class myokit.Ceil(*ops)

Extends: Function

Represents a rounding towards positve infinity ceil(x).

>>> from myokit import *
>>> x = Ceil(Number(5.2))
>>> print(x.eval())
6.0
>>> x = Ceil(Number(-5.2))
>>> print(x.eval())
-5.0
class myokit.Quotient(left, right)

Extends: InfixExpression

Represents the quotient of a division left // right.

>>> from myokit import *
>>> x = parse_expression('7 // 3')
>>> print(x.eval())
2.0
class myokit.Remainder(left, right)

Extends: InfixExpression

Represents the remainder of a division (the “modulo”), expressed in mmt syntax as left % right.

>>> import myokit
>>> x = myokit.parse_expression('7 % 3')
>>> print(x.eval())
1.0
class myokit.Polynomial(*ops)

Extends: Function

Polynomials in myokit can be defined as:

p = myokit.Polynomial(x, c0, c1, c2, ...)

where c0, c1, c2, ... is a sequence of constant coefficients and x is an LhsExpression. The function’s value is calculated as:

p(x) = c[0] + x * (c[1] + x * (c[2] + x * (...)))

Or, equivalently:

p(x) = c[0] + c[1] * x + c[2] * x^2 + c[3] * x^3 + ...
coefficients()

Returns an iterator over this polynomial’s coefficients.

degree()

Returns this polynomial’s degree.

tree(horner=True)

Returns this expression as a tree of Number, Plus and Multiply objects.

The extra argument horner can be used to switch between horner form (default) and the more standard (but slower) form:

a + b*x + c*x**2 + ...
var()

Returns this polynomial’s variable.

class myokit.Spline(*ops)

Extends: Function

Splines in myokit are defined as a special case of the OrderedPiecewise function, where each piece is defined by a Polynomial of a fixed degree.

Splines / polynomials are defined as univariate. All polynomials in a spline must have the same variable as used in the spline’s conditional statements.

degree()

Returns the degree of this spline’s pieces.

class myokit.UnsupportedFunction(name, ops)

Unsupported functions in other formats than myokit can be imported as an UnsupportedFunction. This preserves the meaning of the original document. UnsupportedFunction objects should never occur in valid models.

class myokit.UserFunction(name, arguments, template)

Defines a user function. User functions are not Expression objects, but template expressions that are converted upon parsing. They allow common functions (for example a boltzman function) to be used in string expressions.

Arguments:

name
The user function’s name
arguments
A list of function argument names
template
The Expression evaluating this function.
arguments()

Returns an iterator over this user function’s arguments.

convert(arguments)

Returns an Expression object.