# Description of the Optal Language

## Short Tutorial

### Describing Optimization Goals

The minimal thing needed to describe a problem is a goal.
`minimize 3 + 4`
This describes an expression to be minimized. It is also possible to ask for maximization.
`maximize 3 + 4`
This is a particularily uninteresting problem since the objective is a constant, hence there is nothing to optimize. To define the search space, we need variables.
```dvar float x
maximize x```
This tells that there is a variable x which has a value in the real set. This won't also provide any insightfull result since there is no maximal value for reals. To limit the search space we can add constraints.
```dvar float x
maximize x
constraints {
x <= 3
}```
By constraining x to be lower than 3, the problem has an optimal solution, that appens to be for x = 3. We now have seen the 3 main parts of an optal script: the names declarations, the goal and the constraints. They must appear in that order.

### Simple production problem

Giapetto wants to know how many numbers of wooden trains and soldiers he should build each week to maximize its profit.
```// Giapetto build and sell wooden trains and soldiers
dvar int soldier
dvar int train

/* He wants to maximize its profit.
A soldier costs 3¤ and a train 2¤. */
maximize 3 * soldier + 2 * train

constraints {
// He builds a positive number of soldiers and trains
soldier >= 0;
train >= 0;

/* He has a finite amount of time: he works 5 days per week
and works 7 hours per day.
A train takes 1 hour to build and soldiers, a bit more */
1.85 * soldier + train <= 5 * 7 ;

/* A soldier and a train takes 1 unit of wood to build and
giapetto buys 30 each week */
soldier + train <= 30;
}```

### Using iterators

It is possible to use forall and sum keywords to simplify big scripts. forall allows to define a set of constraints, sum simplifies writing big constraints. More details on those syntax is explained later.
```dvar int soldier
dvar int train

alias Products = < soldier, train >
// an array containing the variables soldier and train
alias Times = < 1.85, 1 >
alias Wood = < 1, 1 >
alias Profit = < 3, 2 >
alias index = indexOf(Products)
// the array <0, 1>, used to iterates on other arrays

maximize sum(i in index) Profit[i] * Products[i]
// Profit[0] * Product[0] + Profit[1] * Product[1]

constraints {
forall(prod in Products) prod >= 0;
// Products[0] >= 0 && Products[1] >= 0
sum(i in index) Times[i] * Products[i] <= 5 * 7;
sum(i in index) Wood[i] * Products[i] <= 30;
}```

## The Optal Language : a Reference

OPTAL has C style comments with /* */ and //.
`/* a comment /* some imbricated comment */ end of the comment */`
`maximize 1 // the end of the line is a comment`

### Basic types

The basics types of OPTAL are: bool, int, floats, linear expression and linear constraints.

#### Integers

Integers expressions are integer constants and operator between integers.
`6 * (1 + 3) - 5`
Division is not allowed between integers.

#### Floats

Floats expressions are float constants and operators between floats.
`6. * (1.3 + 3.) - 5.2 / 12.2`
operators between integers and floats are authorised and behave as operation on floats.

#### Bool

The basics boolean expressions are the constants true and false, and combinations using not && and ||
`true || false && not false`
Arithmetic expressions on booleans are authorized and converted to integers, false is converted to 0 and true to 1. Boolean expressions are also the results of comparison between integers, floats and booleans. Those are true expressions
```1 <= 2
2 == 2
4 >= 3
3 != 2
3 < 3.1
true > false```

#### Linear expressions

Basic linear expressions are constant integers or floats, or variables declared by
```dvar float some_float_var
dvar int some_int_var
dvar bool some_bool_var```
arithmetic expressions between linear expression and float or ints are linear expressions.
```3 * some_float_var
2. + some_int_var```
Sum and difference between linear expressions are linear expressions.
`3 * some_float_var + 2 * some_int_var - some_bool_var`
Notice that product of linear expressions are forbidden.

#### Linear constraints

Linear constraints are the results of comparison between linear expression.
```3 * some_float_var <= 2 * some_int_var
3 * some_float_var == 3
3 * some_float_var >= 3```
Comparisons using != > and < are not authorised. Linear constraints can be combined using &&
```3 * some_float_var <= 2 * some_int_var &&
3 * some_float_var >= 3```

#### symbols

Symbols are names declared by the syntax
``symbol`

### Structured types

OPTAL has 2 types of structured types, arrays and maps.

#### Arrays

Arrays are dense integer indexed data. Arrays can be built using the syntax:
`< 1, 2, 3 >`
`< 1, 2, 3 >[1]`
This returns 2, the first index is 0.

#### Maps

Maps are sparse data indexed by any value, but are accessible using symbols. Maps indexed by symbols can be declared using the syntax:
`{ name1 : 3, name2 : 4 }`
`{ name1 : 3, name2 : 4 }.name1`
Maps indexed by other types than symbols can be accessed through the [] syntax.
`{ name1 : 3, name2 : 4 }[`name1]`
For instance if `map` is indexed by arrays of size 2, it can be accessed using.
`map[<1,2>]`

### Patter operators

#### Sum

Sum allows to evaluate an expression for each elements of an array or and object and do the sum of the results.
`sum(x in <1,2,3>) (x * 3)`
or
`sum(x in {a:1,b:2,c:3}) (x * 3)`
are equivalent to
`(1 * 3) + (2 * 3) + (3 * 3)`
The parameter of sum is a set of patterns binding variables names to values.
`sum(x in <1,2>, y in <3,4>) (x + y)`
wich is equivalent to
`sum(x in <1,2>) sum(y in <3,4>) (x + y)`
or
`sum(x, y in <1,2>) (x + y)`
is equivalent to
`sum(x in <1,2>) sum(y in <1,2>) (x + y)`
A single pattern can bind multiple variables:
`sum(<x,y> in <<1,3>, <2,4>>) (x + y)`
is
`sum(x in <1,2>) sum(y in <3,4>) (x + y)`
Patterns can be constrained. The expression is evaluated only when the constraint is satisfied.
`sum(x in <1,2,3>: x != 2) x * 3`
is equivalent to
`(1 * 3) + (3 * 3)`
It is possible to use implicit equality constraints
`sum(x in <1,2>, x <2,3>) (x * 3)`
is equivalent to
`sum(x in <1,2>, y <2,3>: x == y) (x * 3)`

#### Forall

Forall is like sum but the union operator is && instead of +.
`forall(x in <1,2>) (x >= 2)`
is
`(1 >= 2) && (2 >= 2)`

### Other functions

#### range

The range binary operator takes two integers (a,b) and returns the array of integers between a and b.
`1 .. 3`
is the array
` <1, 2, 3> `

#### indexOf

The indexOf function takes an array or a map and returns the array of the index. If arr is an array or a map.
`sum(x in indexOf(arr)) arr[x]`
is equivalent to
`sum(x in arr) x`

#### Max

Max returns the biggest value of an integer collection.
`Max(<1,2,3>)`
is 3

#### Last

Returns the last index of an array, i.e. the length - 1
`Last(<0,0,0>)`
is 2

### Alias

It is possible to declare some alias for expressions
`alias x = 3 * 4`
`alias y = x + 2`
It is not possible to redeclare already declared variables.

### Variables

Linear variables can be declared by the dvar keyword with a type associated.
`dvar float some_float_var`
A set of variables can be declared by the syntax
`dvar float var_set[set]`
If set is a collection containing integers var_set is an array indexed by the elements of set, otherwise it will be a map. For arrays, index must be consecutive and starting with 0.