LocalSolver logo
is now
Hexaly logo

We're excited to share that we are moving forward. We're leaving behind the LocalSolver brand and transitioning to our new identity: Hexaly. This represents a leap forward in our mission to enable every organization to make better decisions faster when faced with operational and strategic challenges.

This page is for an old version of Hexaly Optimizer. We recommend that you update your version and read the documentation for the latest stable release.

Statements

Assignment statements

Assignments are used to assign values to variables. There are many kind of assignments in LSP depending on the type of the variable (local or global) and the operation you want to perform.

assignment_operator
    : "="
    | "<-"
    | "+="
    | "-="
    | "/="
    | "*="
    | "%="

local_assignment_operator
    : "="
    | "<-"

assignment_statement
    : `identifier` `assignment_operator` `expression` ";"
    | `identifier` `assg_compositor` `assignment_operator` `expression` ";"

local_assignment_statement
    : "local" `identifier` `local_assignment_operator` `expression` ";"
    | "local" `identifier` `assg_compositor` `local_assignment_operator` `expression` ";"

local_statement
    : "local" `identifier` ";"

assg_compositor
    : "[" `filter_iterator` "]"
    | "[" `expression` "]"
    | '.' `expression`
    | `assg_compositor` "[" `filter_iterator` ']'
    | `assg_compositor` "[" `expression` "]"
    | `assg_compositor` "." `identifier`

Simple statements

The simple statement is the classical variable = value; that assigns the given value to the specified variable, overriding the previous value. The variable can be local or global. If the variable was not previously declared as local, the variable is considered as global by default and is implicitly declared if necessary.

This statement cannot be used to add an LSExpression to the mathematical model. See Link statements for that.

Examples:

a = true;     // a = 1
b = 9;        // b = 9
c = a + b;    // c = 10
c = a * b;    // c = 9
c = (a == b); // c = 0
c = a < b;    // c = 1

Coumpound assignment statements

A coumpound assignment (also called “augmented assignment”) is the combination of an arithmetic operation and an assignment. The arithmetic operations allowed with coumpound assignment statements are:

  • + addition
  • - substraction
  • * multiplication
  • / division
  • % modulo

Thus, an assignment like a = a + b can be rewritten as a += b; with the coumpound assignment syntax.

Exemples:

a += 2;     // a = a + 2
a /= 2;     // a = a/2
a *= b + c; // a = a*(b + c)

Local assignment and local statements

Local statements local variable, local variable = value or local variable <- value introduce a new local variable with the given name and set its value to nil or to the specified value.

If a global variable with the same name was already defined, then the global variable will be masked while this local variable is visible. If a local variable with the same name was already defined an error is thrown. See Variables for the differences between local and global variables and for details on the visibility scopes of variables.

Examples:

local i;        // Declare i as local and set its value to nil.
local j = 2;    // Declare j as local and set its value to 2.

for[z in 1..10] {
    // This assignment will throw an exception since z was already implicitly
    // declared as local in the for loop.
    local z = "foo";
}

Iterated assignment statements

a[v in V] = f(v); is an iterated assignment which is strictly equivalent to for [v in V] a[v] = f(v); Similarly a[v in V] <- f(v); is an iterated assignment which is strictly equivalent to for [v in V] a[v] <- f(v); These iterated assignment features will help you will help you to make your models shorter and clearer. Similarly to the for statement introduced in the previous section, iterations can be nested and filtered:

for[i in 0..9][j in i+1..9][k in j+2..9]
    a[i][j][k] = i + j + k;
a[i in 0..9][j in i+1..9][k in j+2..9] = i + j + k; // compact

If statements

The if statement is used for conditional execution.

if_condition
    : 'if' '(' expression ')'
    ;

if_else_statement
    : if_condition statement
    | if_condition statement 'else' statement
    ;

if the if_condition is true (equals to 1), then the first statement is executed. Otherwise, the second statement after the else is executed. Note that the else branch is optional and a block of statements can be declared instead of a sole statement by using the braces {}. If the expression is not an integer equal to 0 or 1 an error will be thrown.

Note

The conditional ternary operator ? : can also be used as shortcut.

Examples:

if (0) c = "ok";
if (true) c = "ok";
if (2) c = "error"; // ERROR: invalid condition

For statements

The for statement is used to iterate over a range, the elements of a map or any other iterable value. The for statements can be nested with a compact syntax and can be filtered with an optional conditionnal statement.

for_statement
    : 'for' for_compositor statement
    ;

for_compositor
    : '[' filter_iterator ']'
    | for_compositor '[' filter_iterator ']'
    ;

filter_iterator
    : identifier 'in' expression ':' expression
    | identifier ',' identifier 'in' expression ':'  expression
    | identifier 'in' expression '..' expression ':'  expression
    | identifier 'in' expression
    | identifier ',' identifier 'in' expression
    | identifier 'in' expression '..' expression
    | expression '..' expression
    ;

Simple for-loops

for [v in A] S; is a simple for-loop where the statement S is iteratively executed with v taking all values in A, where A can be a range or an iterable value like a map. Variable v is implicitly declared as a local variable visible within this for statement and in nested blocks only.

When a range is given, it is declared with the from..to syntax where both from and to are included.

When an iterable object is given, the iteration is performed on the sub-values of the object. The iteration order is specific to the type of the value. For the maps, the order is defined as follows:

  1. Iterates on number keys (integer or floats) in ascending order.
  2. Iterates on strings in ascending order.
  3. Iterates on other types in an implementation specific way.

It is also possible to iterate on the pairs (key, value) using the syntax for [k,v in M]. In that case, k and v are both declared implicitly as local variables and contain respectively the current key and the current value of the loop.

Example:

s = { -44, 12, 14 };
for [i in 0..2] a[i] = i + 1; // a[0] = 1, a[1] = 2, a[2] = 3
for [v in s] println(v/2); // prints -22, 6 and 7.
for [k, v in s] println(k, ":", v); // prints 0:-44, 1:12 and 2:14

Filtered for-loops

for [v in V : C] is a filtered iteration loop: v takes only the values in V satisfying the condition C.

Compact for-loops

Filtered and non filtered for-loops can be nested in a compact way, as follows:

// Non compact
for[i in 0..9]
    for [j in i+1..9 : j % 2 == 0]
        for [k in j+2..9]
            a[i][j][k] = i + j + k;

// Compact
for[i in 0..9][j in i+1..9 : j % 2 == 0][k in j+2..9]
    a[i][j][k] = i + j + k;

The behavior of these 2 examples is similar except that the language considers the non-compact case as the association of 3 enclosing loops, while the compact example is solely a loop with 3 iterated indexes. This semantic difference is particularly important for break statement: a break statement stops the most inner loop, regardless of the number of iterated indexes.

For all kinds of loops, a block of statements can be declared instead of a sole statement by using the braces {}:

for[i in 0..9][j in i+1..9][k in j+2..9] {
    a[i][j][k] = i + j + k;
    b[i][j][k] = i * j * k;
}

for-loops can contain ‘break’ and ‘continue’ statement to respectively terminate the loop unconditionnaly or to go back to testing the condition of the loop whitout executing the rest of the statement suite.

While/do-while statements

while_statement
    : 'while' '(' expression ')' statement
    ;

dowhile_statement
    : 'do' statement 'while' '(' expression ')' ';'
    ;

While or do-while loops are used for repeating a section of code as long as an expression is true.

For the ‘while’ loop, the expression is tested first. If it is true, the statement is executed. The loop terminates otherwise.

For the ‘do-while’ loop, the statement is executed first, then the expression is tested. Contrary to the ‘while’ loop, the ‘do-while’ loop ensures that at least one statement suite is executed.

While or do-while loops can contain ‘break’ and ‘continue’ statement to respectively terminate the loop unconditionnaly or to go back to testing the condition of the loop whitout executing the rest of the statement.

Continue statement

continue_statement
    : 'continue' ';'
    ;

The continue statement, when encountered, goes back to testing the condition of the nearest enclosing loop, whitout executing the rest of the block code.

Continue statements can only take place in for/while/do-while loops. Use of this statement outside of these loops will throw an error.

Break statement

break_statement
    : 'break' ';'
    ;

Break statement terminates the nearest enclosing loop. Please note that for ‘for’ loops, the entire loop is stopped, regardless of the number of iterated indexes.

Break statements can only take place in for/while/do-while loops. Use of this statement outside of these loops will throw an error.

Try-catch statement

In the LSP Language, all errors, faults or exceptionnal situations are handled with an exception mechanism.

trycatch_statement
    : 'try' statement
       'catch' '(' identifier ')' statement
    ;

Throw statement

throw_statement
    : 'throw' expression ';'
    | 'throw' ';'
    ;

Contraint/minimize/maximize statements

modifier
    : 'minimize'
    | 'maximize'
    | 'constraint'
    ;

modifier_statement
    : modifier expression ';'
    ;

These statements modify expressions of the mathematical model (LSExpression) to add them to the constraints list or the objectives list. These statements can also be applied on integers or doubles.

  • constraint c; adds the LSExpression c as a constraint to the mathematical model. An error will be thrown is c is not a boolean LSExpression (introduced with a logical or relational operator) or a constant equals to 0 or 1.
  • minimize c; adds the LSExpression c as an objective to be minimized by the mathematical model.
  • maximize c; adds the LS expression c as an objective to be maximized by the mathematical model.

Note

At least one objective must be defined in the mathematical model.