2023-11-09
WARNING: THE DOCUMENTATION IS NOT UP TO DATE. WE WILL PROVIDE AN UPDATE SOON.
This document describes the Simple Math Programming Language (SMPL).
SMPL is a math-oriented programming language that can be interpreted in the browser. Its primary use is for the mathe:buddy app.
SMPL is (mostly) an imperative, typed language. Its syntax is basically a subset of JavaScript, but extends with intrinsic mathematical data types (e.g. terms, sets and matrices) and operator overloading for these types.
The language definition of SMPL is independent of concrete implementations. A reference implementation can be found here. Visit our online playground.
SMPL is heavily used by the mathe:buddy language.
Many concepts (and also parts of the source code) are taken from the Simple E-Learning Language SELL. Compared to SELL, SMPL is Turing Complete, but lacks an interactive e-learning environment.
The following example program creates two \(3 \times 3\)-matrices \(A\) and \(B\), with random (integral) entries in range [-5,5] without zero. Both matrices are numerically unequal. The product of \(A\) and \(B\) is finally assigned to variable \(C\).
% multiplication of two 3x3-matrices
let A/B = randZ<3,3>(-5,5)
let C = A * B
The example demonstrates some of the key features of SMPL:
The following Python program is similar to the two lines of SMPL code above (but not semantically equivalent, since it generates zero-elements in some cases).
import numpy
= numpy.round(numpy.random.rand(3,3)*10) - 5
A while True:
= numpy.round(numpy.random.rand(3,3)*10) - 5
B if not numpy.array_equal(A,B):
break
= numpy.matmul(A, B) C
An SMPl program is a sequence of statements \(p=(s_0 ~s_1 \dots)\). Each statement ends
by a semicolon (;
). Declarations and assignments are
executed statement wise, i.e. \(s_{i+1}\) is executed after statement \(s_i\).
Example:
let x = 3
let y = sin(x)
The example programs executes lines one and two in given order. Each line is evaluated, before the next line is executed. Indeed, we also could write all statements in one line, since the semicolon separates statements.
The first line evaluates the right-hand side of the equal sign
(=
) and assigns the result, here 3
, to a new
variable with identifier x
. The type of variable
x
is INT
.
The second line first evaluates the expression
sin(x)
. Variable x
is taken as argument to the
sine function. The numeric result 0.14111..
is stored to
variable y
of data type real
. It has
double-precision (refer to IEEE 754). Take care, that real numbers \(\mathbb{R}\) are stored approximately,
unless symbolic computation is applied explicitly.
Comments provide the opportunity co write notes in natural language
that is not executed. Comments are introduced by the percentage sign
(%
) and are valid until the next line break.
Example:
% this is a comment line
let a = 5 % assign integer constant 5 to variable a
%let b = 7
The same listing can be denoted as follows without comments:
let a = 5
Declarations are initiated with keyword let
, followed by
an identifier and finally assigned expression by =
. The
expression in the right-hand side is mandatory to derive the data type.
Data types are described in detail in the next section.
Example:
let x = 5, z = 9.1011
let y = 7
let u = rand(5)
let v = zeros<2,3>()
let a:b = randZ<3,3>(-2, 2)
let c/d/e = rand<3,3>(-2, 2)
x
and u
are integral. The value
for u
is randomly chosen from set {0,1,2,3,4,5}.z
is a real valued.x
and z
are declared together
(without any semantical relation). The notation is equivalent to
let y=7; let y=9.1011;
v
, a
, b
,
c
and d
are matrices. v
is a zero
matrix with two rows and three columns.a
and b
consist of randomly
chosen, integral elements in range [-2,2] without zero.:
evaluates the right-hand side as
many times, as there are left-hand side variables. The example is equal
to:
let a = randZ<3,3>(-2, 2); let b = randZ<3,3>(-2, 2);
./
guarantees that no pair of matrices
c
, d
and e
is equal: Matrix, a
\(3 \times 3\) matrix is generated and
assigned to variable c
. Then a random \(3 \times 3\) matrix is generated that is
numerically unequal to matrix a
. Finally, a random \(3 \times 3\) matrix for c
is
generated with \(c \neq a\) and \(c \neq b\).An assignment has the form X = Y;
. First, the right-hand
side Y
is evaluated and then assigned to the variable
X
on the left-hand side.
Variables are named by identifiers, consisting of one ore more
characters. The first character must be a lowercase or uppercase letter
or underscore, i.e. a..z
or A..Z
or
_
. Starting from the second character, also numbers
0..9
are allowed additionally. Keywords and function names
of the standard function library (see appendix) are not allowed.
Examples: x
, y0
, A
,
mat_0
.
The right-hand side of an assignment consists of a unary constant
(e.g. 1337
or 3.14
or -42
) or a
function call (e.g. sin(x)
) or a variable
(e.g. x
) or an expression (e.g. a + 4
).
An expression is denoted in infix notation: The operator is denoted between two operands in case of a binary operation or the operator is denoted before the operand in case of a unary operation.
The following list of operators is implemented in SMPL. The list is ordered by increasing precedence. Explicit parentheses can break the default precedence (e.g. \(a * (b+c)\)).
Operator | Description |
---|---|
|| |
Logical Or (binary) |
&& |
Logical And (binary) |
== ,!= |
Equal, Unequal (binary) |
< ,
<= ,> ,>= |
Less than, Less or equal, Greater than, Greater or equal (binary) |
+ , - |
Addition, Subtraction (binary) |
* , / |
Multiplication, Division (binary) |
^ |
Potency (binary) |
++ , -- |
Postfix Incrementation, Decrementation (unary) |
! |
logical not (unary) |
Not all operators can be applied to each data type. For example,
a && b
is only valid, if operands a
and b
are boolean.
Base data types are evaluated at compile-time. The compiler reports an error, if types do not match for a operator.
Dimensions are evaluated at runtime. For example, a
RuntimeError
is thrown if two matrices with a different
number of rows are added.
Comparing non-integer numbers with ==
and
!=
applies the following numerical compare:
a == b
is implemented as \(|a-b|\leq\epsilon\) and a != b
is implemented as \(|a-b|>\epsilon\). (Note: \(\epsilon\) is statically set to \(10^{-9}\). It will be configurable in
future SMPL revisions.)
Some examples for expressions (the examples assumes, that variables
y
, u
, w
, A
,
B
, C
have been declared before usage):
let x = 1.23 * sin(y) + exp(u + 2*w)
let C = A * transpose(B)
let d = det(C)
The set of implemented functions is listed in the appendix.
SMPL supports the following data types:
boolean (BOOL
)
A boolean variable is either true
or
false
.
Example:
let x = true
let y = false
let w = true
let u = (x && y) || !w
let v = 3 < 5
\(u := (x \land y) \lor \lnot w\)
integer (INT
)
An integer variable stores integral values in range \(-2^{53}\) to \(2^{53}-1\).
Note:
JavaScript
stores integer values as double precision floating point numbers.
Example:
let x = 5
let y = -23
let z = x * y
let w = round(x / y)
Note that the division outputs RATIONAL
data type,
despite concrete values. Use round
or floor
or
ceil
to get an integer value.
rational (RATIONAL
)
A rational number variable stores values of the form x/y
with \(x,y \in \mathbb{Z}\).
Example:
let x = 1 / 7
let y = real(1 / 7)
Variable x
is of type RATIONAL
and stores
1/7
. Variable y
is of type REAL
and stores 0.142857...
in IEEE 754 double
precision.
real (REAL
)
Real number variables store approximations of real values with IEEE 754 double precision.
Example:
let x = PI
let y = sin(0.1)
complex (COMPLEX
).
Complex variables store complex number in normal form
x+yi
with \(x,y \in
\mathbb{R}\). Complex numbers can be initialized by function
complex(x,y)
or writing x+yi
.
For y=1
, one must write 1i
instead of just
i
. The identifier i
is an ordinary variable
name.
Example:
let x = 3 - 4i
let y = complex(3, -4)
let phi = arg(x)
let r = abs(x)
let z = r * exp(phi)
set (SET
)
A set variable stores a set of elements. We use curly brackets to declare sets.
Examples:
let y = {} % an empty set
let x = {3, 4, 5}
add(x, {4,6}) % x := {3,4,5,6}
remove(x, 3) % x := {4,5,6}
let y = iselement(x, 4) % true
Note: set of non-integers will be supported later.
term (TERM
)
A term is an symbolic expression.
Example
let f(x) = x^2
let y = f(3)
let g(x,y) = 2 * exp(-x) * sin(y)
let h(x,y) = diff(g, x)
let int = integrate(f, 0, 3)
The example calculates \(f(x)=x^2\), \(y=9\), \(g(x)=2\cdot\exp(x)\cdot\sin(y)\), \(h(x,y)=-2 \cdot \exp(x) \cdot \sin(y)\), \(int=21.3333...\).
vector (VECTOR
)
let v = [1, 2, 3]
let w = [4, 5, 6]
let x = zeros<3>()
let n = len(v)
let d = dot(v, w)
matrix (MATRIX
)
zero<m,n>()
function, which creates a zero matrix
with m
rows and n
columns.[a00, a01, ..., a0n-1; a10, a11, ..., a1n-1; ...; am-10 am-11 ... am-1n-1]
.
Rows are delimited by ;
and columns are delimited by
,
.[i,j]
with row
i
and column j
. Indices start at zero,
i.e. the first index is 0 and the last index is \(m-1\) for a row and \(n-1\) for a column.The appendix lists all functions with matrix operands.
let A = zeros<2,3>()
let B = [1, 2, 3; 4, 5, 6]
let C = ones<3,3>()
B[2,3] = 5
let x = B[0,0]
let d = det(C)
let r = rows(A);
let c = cols(A);
Note: matrices with complex elements will be supported later.
Conditional code is executed only, if a conditional is true. The
if
-statement has the form
if C { S0 } elif C1 { S1 } ... else { Sn }
, with a
sequences of statements S0
, S1
etc. Sequence
S0
is executed, if the boolean condition S0
is
true. Sequence S1
is executed, if the boolean condition
S0
is false and the boolean condition S1
is
true. In case that all conditions Ci
are false, then
sequence Sn
is executed.
The elif
parts and else
part are
optional.
Example
let s = 0
let x = rand(-5,5)
if x > 0 {
s = 1
}
elif x < 0 {
s = -1
}
else {
x = 0
}
Example:
while x > 0 {
% body
}
Example:
do {
% body
} while x > 0
Example:
let f = 1
for k from 1 to 4 {
f = f * k
}
The following list describes all built-in constants. We use the
notation :T
after each variable to indicate its data
type.
PI : REAL
(\(3.141592653589793\))The following list describes all built-in functions. We use the
notation :T1|T2|...
to list valid data types for each
parameter and the return value. For example
abs(x:INT|REAL|COMPLEX):REAL
denotes function
abs
with one parameter named x
that can be an
integer a real value or complex value. The function returns a real
value.
Some function also require dimensions. These are embedded into
<...>
.
Notation: We write data type VOID
for functions that do
not return any value.
abs ( x : INT|REAL|COMPLEX ) : REAL
Returns the absolute values of x
.
Example: abs(-4)
is evaluated to
4
.
Example: abs(3+4i)
is evaluated to
5
.
acos ( x : REAL ) : REAL
Calculates \(\cos^{-1}(x)\).
Example: acos(0)
returns \(1.57079...\).
add ( x : SET, y : SET ) : VOID
Adds all elements of set y
to set x
.
Example: let x={1,2,3}; add(x,{4,7})
changes x
to {1,2,3,4,7}
.
asin ( x : REAL ) : REAL
Calculates \(\sin^{-1}(x)\).
Example: asin(0)
returns \(0\).
atan ( x : REAL ) : REAL
Calculates \(\tan^{-1}(x)\).
Example: atan(0)
returns \(0\).
binomial ( n : INT , k : INT ) : INT
Calculates the binomial coefficient \(\binom{n}{k} = \frac{n!}{k!(n-k)!}\).
Example: binomial(4,2)
returns
6
.
ceil ( x : INT|REAL ) : INT
Returns the ceiling of x
.
Example: ceil(3.14159)
returns
4
.
ceil ( x : MATRIX ) : MATRIX
Returns a matrix, where each element is the ceiling value of the input matrix.
Example: ceil([[1.1,2.2],[4.4,5.5]])
returns
[2,3;5,6]
.
complex ( x : INT|REAL , y : INT|REAL ) : COMPLEX
Creates a complex number from real part x
and imaginary
part y
, i.e. \(z=x+yi\).
Example: complex(2,3)
returns
2+3i
.
column ( x : MATRIX, c : INT ): VECTOR
Returns the c
-th column of matrix x
as
vector. The first vector has index 0.
Example: column([[1,2],[3,4]], 1)
returns
[2,4]
.
conj ( z : COMPLEX ) : COMPLEX
Calculates \(\bar z\), i.e. the
complex conjugate of z
.
Example: conj(3+4i)
returns
3-4i
.
cos ( x : REAL ) : REAL
Calculates \(\cos(x)\).
Example: cos(PI/2)
returns \(0\).
cross ( x : VECTOR, y : VECTOR ) : VECTOR
Calculated the cross product of two vectors \(x\) and \(y\), i.e. \(x \times y\), or throws an exception, if one of the vectors has not exactly three elements.
Example: cross([1,2,3],[4,5,6])
returns
[-3,6,-3]
.;
det ( x : MATRIX ) : REAL
Returns \det(x)
or throws an error, if \(x\) is not square.
TODO: example(s).
diff ( f : TERM , x : ID ) : TERM
Calculates \(\frac{\partial f}{\partial x}\).
Example: f(x,y)=x^2+y; diff(f, x)
returns
2*x
.
dot ( u : VECTOR , v : VECTOR ) : REAL
Calculates the doc product of two vectors \(u\) and \(v\).
Example: dot([1,2,3],[4,5,6])
returns
32
.
eigenvalues_sym ( x : MATRIX ) : SET_REAL
Calculate the set of eigenvalues of a symmetric matrix
x
. If x
is not symmetric, an error is
thrown.
Example: eigenvalues_sym([[3,0],[0,4]])
returns
{3,4}
.
exp ( x : REAL|COMPLEX ) : REAL|COMPLEX
Calculates \(\exp(x)\).
Examples: exp(0)
returns \(1\). exp(1i)
returns
0.54... + 0.84...i
.
eye ( n : INT ): MATRIX
Returns an \(n \times n\) identity matrix.
Example: eye(3)
returns
[[1,0,0],[0,1,0],[0,0,1]]
fac ( x : INTEGER) : INTEGER
Calculates \(x!\), i.e. the faculty of \(x\).
Example: fac(3)
returns 6.
figure2d() : FIGURE_2D
Creates a new 2D-figure instance.
figure_x_range( fig : FIGURE_2D, min : REAL , max : REAL ) : VOID
Defines the range of the \(x\)-axis
for figure fig
.
figure_y_range( fig : FIGURE_2D, min : REAL , max : REAL ) : VOID
Defines the range of the \(y\)-axis
for figure fig
.
figure_x_label( fig : FIGURE_2D, label : STRING ) : VOID
Sets the label of the \(x\)-axis for
figure fig
.
figure_y_label( fig : FIGURE_2D, label : STRING ) : VOID
Sets the label of the \(y\)-axis for
figure fig
.
figure_color( fig : FIGURE_2D, key : INT ) : VOID
Sets the color for figure fig
.
figure_plot( fig : FIGURE_2D, x : VECTOR|TERM ) : VOID
Plots a 2D-point or a function term into figure
fig
.
floor ( x : INT|REAL ) : INT
Returns the floor of x
.
Example: floor(2.71)
returns
2
.
floor ( x : MATRIX ) : MATRIX
Returns a matrix, where each element is the ceiling value of the input matrix.
Example: floor([[1.1,2.2],[4.4,5.5]])
returns
[[1,2],[4,5]]
.
imag ( x : COMPLEX ) : REAL
Returns the imaginary part of a complex number.
Example: imag(3+4i)
returns 4.
is_invertible ( x : MATRIX ) : BOOL
Returns true, if \(x\) is invertible, otherwise false. Throws an exception, if \(x\) is not a square matrix.
TODO: epsilon + give example(s)
is_symmetric ( x : MATRIX ) : BOOL
Returns true, if \(x\) is symmetric, otherwise false. Throws an exception, if \(x\) is not a square matrix.
TODO: epsilon + give example(s)
is_zero ( x : VECTOR|MATRIX ) : BOOL
Returns true, if all elements \(|x| < \epsilon\).
len ( x : VECTOR|SET ) : INT
Returns the length of a vector or the cardinality (number of elements) of a set.
Examples: len([1,0,0,1])
returns 4.
len(set(1,3,3,7))
returns 3.
linsolve ( A : MATRIX , x : VECTOR ) : VECTOR
TODO: no, one, inf solutions.
max ( s : SET_INT ) : INT
Returns the maximum value from an integer set. If the set is empty, then \(-\infty\) is returned.
Example: max(set(1,-2,3))
returns
3
.
max ( s : SET_REAL ) : REAL
Returns the maximum value from a set consisting of real valued elements. If the set is empty, then \(-\infty\) is returned.
Example: max(set(1.1,-2.1,3.1))
returns
3.1
.
min ( s : SET_INT ) : INT
Returns the minimum value from an integer set. If the set is empty, then \(\infty\) is returned.
Example: min(set(1,-2,3))
returns
-2
.
min ( s : SET_REAL ) : REAL
Returns the minimum value from a set consisting of real valued elements. If the set is empty, then \(\infty\) is returned.
Example: min(set(1.1,-2.1,3.1))
returns
-2.1
.
norm2 ( u : VECTOR ) : REAL
Calculates the euclidean norm of a vector \(u\), i.e. \(\sqrt{u_0^2 + u_1^2 + \dots}\).
Example: norm2([3,4])
returns
5
.
ode < lhs : TERM , rhs : TERM > : TERM
Returns an ordinary differential equation (ODE).
Example:
let y(x) = ode( diff(y,x), - 2 * x^2/y );
ones < m : INT , n : INT > () : MATRIX
Returns a one-matrix with m
rows and n
columns.
Example: ones<2,3>()
returns a \(2\times 3\) matrix with all elements
1.
rand ( a : INT , b : INT ) : INT
Returns a random integer in range [a,b]
.
rand < n : INT > ( a : INT , b : INT ) : VECTOR
Returns a vector of length \(n\),
where each element is a randomly chosen integer value in range
[a,b]
.
rand < m : INT , n : INT > ( a : INT , b : INT ) : MATRIX
Returns a \(m \times n\) matrix,
where each element is a randomly chosen integer value in range
[a,b]
.
rand ( s : SET_INT ) : INT
Randomly returns one of the elements of integer set
s
.
Example: rand(set(11,12,13))
returns 11
or 12
or 13
.
randZ ( a : INT , b : INT ) : INT
Returns a random integer in range [a,b]
, except value
0.
randZ < n : INT > ( a : INT , b : INT ) : VECTOR
Returns a vector of length \(n\),
where each element is a randomly chosen integer value in range
[a,b]
, except value 0.
randZ < m : INT , n : INT > ( a : INT , b : INT ) : MATRIX
Returns a \(m \times n\) vector,
where each element is a randomly chosen integer value in range
[a,b]
, except value 0.
rank ( x : MATRIX ) : INT
Calculates the rank of matrix \(x\).
real ( x : INT ) : REAL
Type casts an integer value to a real value.
Example: real(3)
returns
3.0
.
real ( x : COMPLEX ) : REAL
Returns the real part of a complex number.
Example: real(3+4i)
returns 3.
remove ( x : SET, y : SET ) : VOID
Removes all elements of set y
from set
x
.
Example: let x={1,2,3}; remove(x,{2,3})
changes
x to {1}
.
row ( x : MATRIX, r : INT ): VECTOR
Returns the c
-th row of matrix x
as vector.
The first row has index 0.
Example: row([[1,2],[3,4]], 1)
returns
[3,4]
.
round ( x : INT|REAL ) : INT
Returns the rounded value of x
.
Example: round(3.14159)
returns
3
.
round ( x : MATRIX ) : MATRIX
Returns a matrix, where each element of the input matrix is rounded.
Example: round([[1.1,2.2],[4.4,5.5]])
returns
[[1,2],[4,6]]
.
set ( x0 : INT , x1 : INT, ... ) : SET_INT
Creates and returns a set of integer values.
Example: set(4, 2, 5, 2)
returns a set \(\{2,4,5\}\).
set ( x0 : REAL , x1 : REAL, ... ) : SET_REAL
Creates and returns a set of real values.
Example: set(0.1, -3.4)
returns a set \(\{-3.4,0.1\}\).
set ( x0 : COMPLEX , x1 : COMPLEX, ... ) : SET_COMPLEX
Creates and returns a set of complex values.
Example: set(4+2i, 2, 5i, 2)
returns a set \(\{4+2i,2,5i\}\).
sin ( x : REAL ) : REAL
Calculates \(\sin(x)\).
Example: sin(0)
returns \(0\).
shuffle ( x : VECTOR ) : VECTOR
Randomly reorders the elements of x
.
Example: shuffle([3,1,4])
returns
[1,3,4]
or [4,3,1]
or …
sqrt ( x : INT|REAL ) : REAL
Calculates \(\sqrt{x}\) for \(x \geq 0\). If \(x<0\), a runtime error is thrown.
For negative or complex x
, use function
sqrtC
.
Example: sqrt(4)
returns
2
.
sqrtC ( x : INT|REAL|COMPLEX ) : COMPLEX
Calculates \(\sqrt{x}\) and returns the result as complex number. The result is technically a complex number, even if the imaginary part is zero.
Examples: sqrt(-4)
returns 2i
.
sqrt(4)
returns 2+0i
.
tan ( x : REAL ) : REAL
Calculates \(\tan(x)\).
Example: tan(0)
returns \(0\).
triu ( x : MATRIX ) : MATRIX
Returns the upper triangular part of \(x\).
TODO: example(s)
zeros < n : INT > () : VECTOR
Returns a zero-vector with n
elements.
Example: zero<3>()
returns a vector with all
three elements 0.
zeros < m : INT , n : INT > () : MATRIX
Returns a zero-matrix with m
rows and n
columns.
Example: zero<2,3>()
returns a \(2\times 3\) matrix with all elements
0.
The following formal grammar (denoted in EBNF) is currently implemented.
<GRAMMAR>
program =
{ (statement | "\n") };
statement =
declareOrAssign
| ifCond
| whileLoop
| forLoop
| figure;
declareOrAssign =
[ "let" ] # "let" -> declaration
ID ["[" TERM "]"] # variable ID, optional: vector-index
( {":" ID} | {"/" ID} ) # additional variable ID(s), '/' := distinct
["(" ID { "," ID } ")"] # function parameters
"=" TERM # assign right-hand side
[">>>" ID ">>>" TERM [">>>" TERM]] # TESTS: expected: type, value,
(";"|"\n"); # stringified
ifCond =
"if" TERM block { "elif" TERM block } [ "else" block ];
whileLoop =
"while" TERM block;
forLoop =
"for" ID "from" TERM "to" TERM block;
block =
"{" { statement } "}";
figure =
"figure" "{" { figureStatement } "}";
figureStatement =
("x_axis"|"y_axis") "(" num "," num "," STR ")"
| "function" "(" ID ")"
| "circle" "(" num "," num "," num ")";
num =
["-"] INT
| ["-"] REAL;
</GRAMMAR>
Author: Andreas Schwenk, TH Köln