# Function of ALG Language

## Table of contents

## Syntax Basics

The initiative of proposing a new programming language for algorithm implementation is based on the multi-backend design of mmCEsim. The language is specially designed so that it can be exported to C++ (with Armadillo), Python (with NumPy) and Matlab/Octave easily.

Every line of ALG language calls a function. Let’s first have a look at its basic structure before we cover its details.

```
ret1::type1 ret2 = FUNC param1 param2::type2 key1=value1 key2=value2::type3 # comments
```

It may look like an assembly language at the first glance, due to all parameters are separated by space. But it is actually much more convenient. Here are some basic rules:

- All tokens are separated by space.
- Function names are in all upper cases, like
`CALC`

,`WHILE`

. - Indentation does not matter. Blocks are ended with
`END`

. - The function line is mainly composed of three parts:
**return values**,**function name**and**parameters**, in the left to right direction. - Some functions may not have return values, and you may also omit the return values.
If there are return values, there is a
`=`

between return values and function names. - Function name is the first word on the right of
`=`

(if there are return values) or the first word of line (if there is no return value). - Like Python, parameters can be passed in by two ways:
**value in position**: Like`param1`

and`param2`

in the above example. Parameters in different positions correspond to different usages in the function. This is the only way in C++.**key and value**: Parameters can also be specified using key and its corresponding value.`value1`

and`value2`

are passed in using this method. It should be noted that there should be no space around the`=`

between key and value.

There are some special cases that parameters are viewed as a whole, for example

`COMMENT`

and`CALC`

. - If a parameter contains space or special characters, you need to use the
double quotes like
`"param with space"`

and escape special characters as in C++ and Python. - You may optionally specify the type of return value and parameters with
`::`

after the value. For example, in the above example`dtype1`

,`dtype2`

and`dtype3`

are type specifications for`ret1`

,`param2`

and`value2`

, respectively. For more information about data type, please refer to data type of ALG language. - Like Python, the backslash (
`\`

) at the end of the line can be used for continuing the function on next line. - Comments start with the hash (
`#`

) like Python.

There should be no space around the `=`

between key and value for parameters.
For example, `key=val`

is valid while `key = val`

is forbidden.

Special rules may be applied for different functions. Please refer to the specific documentation for each function.

## BRANCH

Declare start of the scope of job algorithms.

### Explanations

This is useful in `estimation`

.
Contents between `BRANCH`

and `MERGE`

will be repeated for different algorithms.
So you need to place compressed sensing estimation
`ESTIMATE`

and `RECOVER`

inside.

### Example

## BREAK

Break from a block (for `FOR`

, `FOREVER`

, `LOOP`

, `WHILE`

).

### Explanations

The same as `break`

in C++, Python and Matlab/Octave.
This function takes no parameter.

### Example

## CALC

Make arithmetic calculations.

### Explanations

There are two kinds of `CALC`

usage: **inline** and **standalone**.

**inline**: The contents to be calculated are placed in a set of dollar signs, like LaTeX syntax:`$some operations to be calculated$`

.**standalone**: This is like a normal function, with function name as`CALC`

. You may also omit the function name`CALC`

since it is the default function name if nothing is specified. Therefore,`result = CALC your expression`

is equivalent to`result = your expression`

.

For more information about the `CALC`

syntax,
please refer to CALC details.

In the current version, all spaces inside `CALC`

are eliminated,
so string operations should be avoided.

For safety, you should not use anything other than ANSI characters in `CALC`

functions.
Otherwise, there can be undefined behaviour.

If you want the calculation result to be a new variable,
you may use function `NEW`

.

### Example

C++

```
a = b + 2;
a = arma::sin(b) * c;
a = b.t() + c.i();
c = b(2, 3);
c = arma::abs(b(arma::span::all, 3)) + arma::pow(b, 2);
arma::exp2(a + c % d) / e.st() - f(arma::span::all, 3, arma::span(1, index));
```

```
a = CALC b + 2 # explicit CALC function
a = \sin(b) @ c # implicit CALC function
a = b^H + c^{-1} # conjugate transpose and inverse
c = b_{2, 3} # get element of a matrix
c = \abs{b_{:, 3}} + \pow(b_{}, 2) # use : in subscript & use {} for function
\exp2(a + c .* d) ./ e^T -f_{:,3,1:index} # element-wise operator and subscript : range
```

## CALL

Call a custom function defined by `FUNCTION`

.

## COMMENT

Place a line of comment in the exported code.

### Explanations

All contents after the function keyword `COMMENT`

are considered as comments.

In the current version, all spaces in the comment between words will be changed into one whitespace. In future releases, comment text will remain its original style.

### Example

C++

```
// Hi, this is a comment!
```

Python

```
# Hi, this is a comment!
```

Matlab/Octave

```
% Hi, this is a comment!
```

```
COMMENT Hi, this is a comment!
```

## CPP

Write standard C++ contents.

### Explanations

All contents after the `CPP`

keywords are copied to exported codes.
For backend other than C++, this function is ignored.

### Example

C++

```
std::cout << "Standard C++ Language!" << std::endl;
```

Python/Matlab/Octave

```
<--- (Nothing)
```

```
CPP std::cout << "Standard C++ Language!" << std::endl;
```

## ELIF

Alias for the continuous `ELSE`

and `IF`

.

### Explanations

The parameter is the same as `IF`

.

### Example

Example with `IF`

.

## ELSE

Used in `IF`

block.

### Explanations

This function implements as `else`

in C++, Python and Matlab/Octave.
There is no parameter for the `ELSE`

function.

### Example

Example with `IF`

.

## END

End of a block (for `ELSE`

, `ELIF`

, `FOR`

,
`FOREVER`

, `IF`

, `LOOP`

, `WHILE`

).

### Explanations

In C++, this functions as `}`

,
in Python it is the indentation goes back for one block.
In Matlab/Octave, it is the `end`

specification.

### Example

Example with `FOR`

, `FOREVER`

, `IF`

,
`LOOP`

, `WHILE`

.

## ESTIMATE

CALL standard ALG functions to estimate the sparse channel with compressed sensing (CS).

### Explanations

There are four parameters.

Position | Parameter Key | Descriptions |
---|---|---|

1 | `Q` |
The sensing matrix. |

2 | `y` |
The received signal. |

3 | `nonzero` |
The indices vector of non-zero elements. |

4 | `init` |
Whether to initialize a variable (boolean). |

### Example

Estimation for MIMO (with no RIS):

```
VNt::m = NEW `DICTIONARY.T`
VNr::m = NEW `DICTIONARY.R`
lambda_hat = INIT `GRID.*`
Q = INIT `MEASUREMENT` `GRID.*`
i::u0 = LOOP 0 `PILOT`/`BEAM.T`
F_t::m = NEW F_{:,:,i}
W_t::m = NEW W_{:,:,i}
Q_{i*`BEAM.*`:(i+1)*`BEAM.*`-1,:} = \kron(F_t^T, W_t^H) @ \kron(VNt^*, VNr) # the sensing matrix
END
BRANCH
lambda_hat = ESTIMATE Q y
RECOVER $VNr @ \reshape(lambda_hat, `GRID.R`, `GRID.T`) @ VNt^H$
MERGE
```

Example for Single RIS assisted MIMO:

```
COMMENT STEP 1: Load Dictionary
VNt::m = NEW `DICTIONARY.T`
VNr::m = NEW `DICTIONARY.R`
V_M::m = NEW `DICTIONARY[RIS]`
V_N::m = NEW \kron(VNt^*, VNr)
D::m = INIT `GRID[RIS]` `SIZE[RIS]`
LOOP 0 `SIZE[RIS]`
tmp::v = NEW \kron(V_M_{i,:}^T, V_M_{i,:}^H)
D_{:,i} = tmp_{0:`SIZE[RIS]`-1}
END
COMMENT STEP 2: Compressed Sensing Formulation
Q::m = INIT `MEASUREMENT` $`GRID.*` * `GRID[RIS]`$ # sensing matrix
K = NEW `GRID[RIS]` # number of blocks
T = NEW `PILOT`/`BEAM.T`/K # number of sounding times
k::u0 = LOOP 0 K
t::u0 = LOOP 0 T
i::u0 = NEW k * T + t
psi::v = NEW Psi_{:,i} # one reflection vector
F_t::m = NEW F_{:,:,i}
W_t::m = NEW W_{:,:,i}
Z_T::m = NEW \kron(F_t^T, W_t^H)
first_index::u0 = NEW (k * T + t) * `BEAM.*`
last_index::u0 = NEW first_index + `BEAM.*` - 1
Q_{first_index:last_index,:} = \kron((D @ psi)^T, Z_T @ V_N)
END
END
COMMENT STEP 3: Calculate Ground Truth
G_ang::m = NEW VNr^H @ G @ V_M * `GRID.R` * `GRID[RIS]` / `SIZE.R` / `SIZE[RIS]`
R_ang::m = NEW V_M^H @ R @ VNt * `GRID.T` * `GRID[RIS]` / `SIZE.T` / `SIZE[RIS]`
J::m = NEW \kron(R_ang^T, G_ang)
Lambda::m = CALL mergeToLambda J init=true
COMMENT STEP 4: Apply Compressed Sensing Algorithms
lambda_hat = INIT $`GRID.*` * `GRID[RIS]`$
BRANCH
lambda_hat = ESTIMATE Q y
Lambda_hat::m = NEW \reshape(lambda_hat, `GRID.*`, `GRID[RIS]`)
RECOVER Lambda_hat Lambda
MERGE
```

## FOR

Start a `for`

loop.

### Explanations

The parameters are similar to C++.

Position | Parameter Key | Descriptions |
---|---|---|

1 | `init` |
Initialization before entering the loop. |

2 | `cond` |
Condition to continue into the loop. |

3 | `oper` |
Operation after each iteration. |

If there is `=`

or other special characters inside your parameter or there exists space,
do remember to place them inside double quotes (`"`

).

### Example

C++

```
for (uword i = 0; i != 10; i = i + 2) {
// Do something here in the for loop.
}
```

```
FOR "i::u0 = INIT 0" "i != 10" "i=i+2" # a for loop taking three parameters
COMMENT "Do something here in the for loop."
END
```

## FOREVER

Repeat in the block until `BREAK`

.

### Example

C++

```
while (1) {
break;
}
```

```
FOREVER # takes no param
BREAK # Wow, nothing is done when I just break here [Lol]
END
```

## FUNCTION

Start a function definition.

### Explanations

The function requires an `END`

to mark the end of function.

## IF

Conditional statement.

### Explanations

This works the same as `if`

in C++, Python, Matlab/Octave.
All contents after the `IF`

keyword are part of the condition.
If you insist using the key value style, the key is `cond`

.

### Example

C++

```
if (arma::accu(arma::pow(arma::abs(A), 2)) > 0.1 * threshold) {
if (b < 0) {
b = 0;
} else if (b > 100) {
b = 100;
} else {
b = -b;
}
} else {
if (c == d) {
A = A * 0.1;
}
}
```

```
IF \accu(\pow(\abs(A), 2)) > 0.1 * threshold
IF b < 0
b = 0
ELIF b > 100
b = 100
ELSE
b = -b
END
ELSE
IF cond="c == d" # use key value style if you insist
A = A * 0.1
END
END
```

## INIT

Initialize a variable.

### Explanations

This function can initialize a **scalar**, a **vector**, a **matrix** and a **tensor**.
The initialization target can be specified in two ways:

**return value type specification**: You can specify the type of the variable to be initialized by`::`

.**parameters**: Parameter`dtype`

is used for element type, and`dim1`

,`dim2`

,`dim3`

are used for dimension specification.

Please be

consistent! The current implementation of the function is fragile and can be fooled by any inconsistent actions. While we are trying to enhance the error detection, you are advised to use the correct dimension.However, there are also a few exceptions for user’s convenience. Though row vector (

`r`

) is regarded as a matrix, you can still specify its dimension with only one parameter on`dim1`

. For a scalar initialization, the value can directly follow`=`

.

Position | Parameter Key | Descriptions |
---|---|---|

1 | `dim1` |
Size of the first dimension (for vector). |

2 | `dim2` |
Size of the second dimension (for vector and matrix). |

3 | `dim3` |
Size of the third dimension (for vector, matrix and tensor). |

4 | `fill` |
Element filling mode. `randn` for standard normal distribution \(\mathcal{N}(0, 1)\), `randu` for standard uniform distribution \(\mathcal{U}(0, 1)\), `zeros` for filling as 0, `ones` for filling as 1. Default option is `zeros` . |

5 | `scale` |
Scale of the value. This works like multiplying a value after the initialization by `fill` . |

6 | `dtype` |
Element data type. This is the one character prefix like `c` , `i` . The default value is complex (`c` ). |

For initialization of a row vector (`r`

), you may just use one dimension.
For initialization of a scalar (dimension as 0), you can specify the value directly after `=`

,
but if you want to use `fill`

and `scale`

, you must specify the parameter key.

Since the development of ALG concentrates on matrix operations, the initialization also performs in a matrix-oriented way. Please refer to data type of ALG language if you are not sure how the data type works.

### Example

C++

```
cx_mat a = (4) * arma::ones<cx_mat>(4, 3);
cx_mat b = (-1 + i) * arma::zeros<cx_mat>(1, 10);
const double pi = 3.1415926;
std::complex<double> random_number = (-2) * arma::randn<std::complex<double>>();
```

```
a = INIT 4 3 fill=ones scale=4 dtype=c # a matrix
b::r = INIT 10 scale="-1+i" # row vector (viewed as a matrix)
pi::f0c = INIT 3.1415926 # a const float
random_number = INIT fill=randn scale=-2
```

## LOG

Write to log file.

### Example

Log file: `mmcesim.log`

```
[INFO] $ LOG [INFO] A user-defined message.
[INFO] * FUNCTION: LOG
[INFO] * PARAMS:
[INFO] > {}={[INFO]}::{}
[INFO] > {}={A}::{}
[INFO] > {}={user-defined}::{}
[INFO] > {}={message.}::{}
[INFO] A user-defined LOG message.
```

```
LOG [INFO] A user-defined message.
```

## LOOP

Loop with iteration counter.

### Explanations

The `LOOP`

function uses an iteration counter to control the loop.
The parameters are shown as below.

Position | Parameter Key | Descriptions |
---|---|---|

1 | `begin` |
The starting iteration counter. |

2 | `end` |
The end iteration counter (not included). |

3 | `step` |
Iteration counter step. |

4 | `from` |
The starting iteration counter. |

5 | `to` |
The last interaction counter (included if step walks into it). |

Normally, we use the `begin`

+ `end`

format.
You may also use `from`

+ `to`

format,
but the two formats cannot be used together.

The return value is the iteration counter.
If it is not specified, the default one is `i`

.
You may also use `::`

to specify the iteration counter type.

### Example

C++

```
for (auto i = 0; i < 10; ++i) {
// 0, 1, 2, ..., 9
for (auto j = 10; j >= 0; --j) {
// 10, 9, 8, ..., 0
}
for (uword k = 0; k < 10; k += 2) {
// 0, 2, 4, 6, 8
}
}
```

```
LOOP 0 10 # implicit counter name as 'i'
COMMENT 0, 1, 2, ..., 9
j = LOOP from=10 to=0 step=-1
COMMENT 10, 9, 8, ..., 0
END
k::u0 = LOOP begin=0 end=10 step=2 # specify counter type
COMMENT 0, 2, 4, 6, 8
END
END
```

Print the contents.

### Explanations

The function takes a list of parameters, and they can be matrices or scalar values. They are printed out from left to right.

### Examples

C++

```
std::cout << 1 << '\t' << H << '\n';
```

```
PRINT 1 '\t' H '\n'
```

## RECOVER

Declare the recovered channel.

### Explanations

The NMSE/BER performance is evaluated with the recovered channel specified here.

Position | Parameter Key | Descriptions |
---|---|---|

1 | `est` |
The estimated (recovered) channel. |

2 | `real` |
The real (ground-truth) channel. |

3 | `num` |
The total number of `RECOVER` statements. |

The second parameter (`real`

) is default as the cascaded channel (of size \(N_r\times N_t\)).
Therefore, it is necessary for the system with RIS to specify the real channel (which may be of other definitions).

The third parameter (`num`

) is used to specify the total number of `RECOVER`

statements.
Therefore, the NMSE result can be scaled correctly.

### Examples

See examples of `ESTIMATE`

.

Example of the `num`

key.

C++

```
NMSE0(ii, 0) += mmce::nmse(H, H_cascaded) / K;
```

```
RECOVER H_hat num=K
```

## MERGE

Declare end the scope of job algorithms.

### Explanations

This works with `BRANCH`

.
View documentation of `BRANCH`

for details.

If you do not specify `MERGE`

,
it is assumed to be end of `estimation`

by default.

It is advised to always specify `MERGE`

so that the range
between `BRANCH`

and `MERGE`

is clearer
and can be extended by other users more easily.

### Examples

## NEW

Create a new variable from CALC result.

### Explanations

The parameters are the same as CALC,
except for the return value type is **required**.

### Examples

C++

```
cx_vec y = H * x + n;
```

```
y::v = NEW H @ x + n
```

## WHILE

Repeat while the condition satisfies.

### Explanations

This is the same as C++, Python and Matlab/Octave.
The function takes only one parameter.
(If you do need a key value style, it has key `cond`

.)

Since only one parameter is needed,
all contents after the `WHILE`

keyword is viewed as the stop condition.
So there is no need to quote the condition which is required in `FOR`

.

### Example

C++

```
while (i != 100 && result == false) {
// Do something in the while loop.
}
```

```
WHILE i != 100 && result == false # no quote is needed because there will be only one param
COMMENT "Do something in the while loop."
END
```