Skip to content

Operators

Riccardo De Benedictis edited this page Sep 13, 2022 · 1 revision

Once introduced to variables and constants, we can begin to operate with them by using operators. We use operators to impose constraints on declared variables. The complete list of operators is described in the following.

Assignment operator (=) The assignment operator assigns a value to a variable. For example

x = 5;
y = [0, 20];

assigns the value 5 to the variable x and the domain [0, 20] to the variable y. The assignment operation always takes place from right to left, and never the other way around. For example

x = y;

assigns the value y to variable x. The value of x, at the moment this statement is executed, is lost and replaced by y.

It is worth noticing that we are assigning y to x therefore, if y changes at a later moment, it will reflect on the value taken by x and the other way around. Variables x and y will represent exactly the same object after this assignment statement is executed.

The assignment operator can be used, also, during variable declaration for assigning to variables an initial domain through the syntax <type> <id> = <expr>.

Arithmetic operators ( +, -, *, / ) Operations of addition, subtraction, multiplication and division correspond literally to their respective mathematical operators. The semantic, however, is taken by interval arithmetic. Specifically, arithmetic operations are defined as:

  • -[x0, x1] = [ - x1, - x0]
  • [x0, x1] + [y0, y1] = [x0 + y0, x1 + y1]
  • [x0, x1] - [y0, y1] = [x0 - y0, x1 - y1]
  • [x0, x1] * [y0, y1] = [min(x0 * y0, x0 * y1, x1 * y0, x1 * y1), max(x0 * y0, x0 * y1, x1 * y0, x1 * y1)]
  • [x0, x1] / [y0, y1] = [min(x0 / y0, x0 / y1, x1 / y0, x1 / y1), max(x0 / y0, x0 / y1, x1 / y0, x1 / y1)]

For example:

x = 5 + y;

assigns to the variable x the expression 5 + y. Suppose the domain of variable y is [10, 20], the domain of variable x will be [15, 25] after the execution of the statement.

It is worth noticing that, similar to what happens for the simple assignment case, we are assigning the expression 5 + y to x therefore, if y changes at a later moment, it will reflect on the value taken by x and the other way around. Specifically, the variable x and the expression 5 + y will represent exactly the same object after this assignment statement is executed. As a consequence, if the domain of y becomes, for example, [15, 20], the domain of x will become [20, 25]. The value of x, at the moment this statement is executed, is lost and replaced by the expression 5 + y.

Relational and comparison operators ( ==, !=, <, >, <=, <=) Two expressions can be compared using relational and equality operators to know, for example, if two values are equal or if one is greater than the other. The result of such an operation is a boolean variable representing the validity of the relation.

Be careful! The assignment operator (operator =, with one equal sign) is not the same as the equality comparison operator (operator ==, with two equal signs); the first one (=) assigns the expression on the right-hand to the variable on its left, while the other (==) compares whether the values on both sides of the operator are equal. Consider the following code snippet:

x = 5;       // assigns 5 to x
x = 7;       // assigns 7 to x
x == 7;      // compares x with 7 returning true
x == 5;      // compares x with 5 returning false
x == [6, 8]; // compares x with [6, 8] returning {true, false}

The first statement assigns value 5 to variable x. The second statement assigns value 7 to variable x. The third statement compares the variable x with the value 7 returning a boolean constant true. The fourth statement compares the variable x with the value 5 returning a boolean constant false. Finally, the fifth statement compares the variable x with the domain [6, 8] returning a boolean variable with domain {true, false}.

Logical operators ( !, &, |, ^ ) Logical operators return boolean variables representing the validity of the operator. To begin, the operator ! is the domain description language operator for the Boolean operation NOT. It has only one operand, to its right, and inverts it, producing false if its operand is true, and true if its operand is false. Basically, it returns the opposite Boolean value of evaluating its operand. The logical operators &, | and ^ are used when evaluating two (or more) expressions to obtain a single relational result. Specifically, the operator & corresponds to the Boolean logical operation AND, which yields true if both (all of) its operands are true, and false otherwise. The operator | corresponds to the Boolean logical operation OR, which yields true if any of its operands is true, thus being false only when both (all of) its operands are false. Finally, the operator ^ corresponds to the Boolean logical operation EXACT-ONE, which yields true if exactly one of its operands is true, thus being false all of its operands are false ore more than one is true.

Assertions An assertion is a statement that a boolean expression must be true. To assert a boolean expression it is enough to specify the boolean expression as a statement. Notice that enforcing a boolean expression to be true (or, more generally, to false), can result in the updating of the values of the involved variables through constraint propagation. Suppose, for example, we execute the following snippet:

int x = [0, 10];
int y = [10, 20];
bool x_eq_y = x == y;

// Assertion: x_eq_y must be equal to true
x_eq_y;

In the above example we are creating an integer variable x having domain [0, 10], an integer variable y having domain [10, 20], and a boolean variable x_eq_y having domain {true, false}. With the execution of the assertion represented by the fourth statement, however, the value of the variable x_eq_y is constrained to be equal to true. This, in turn, results in forcing the constraint x == y to be equal to true which, in turn, results in assigning to both variables x and y the value 10 (i.e. the only allowed value that makes the two variables equal).

What happens now if we provide an infeasible problem? Suppose, for example, we provide the following code:

int x = [0, 10];
int y = [20, 30];
x == y;

The third statement asserts that the constraint x == y must be true, however the initial domains of the variables x and y do not allow the constraint to be satisfied. When these situations occur, we say that we have an inconsistency. The solver detects the inconsistency and returns false. The domains of the variables, after an inconsistency has been detected, are no more valid.

In conclusion, it is worth to notice that the combined use of operators allows to obtain quite complex behaviors. As an example, consider the following code snippet:

// assert linear relations
x0 - x1 > x2 * 3;
x0 != x1;

// assert nonlinear relations
x0 == x2 * x3;

// assert conjunction of relations
x0 + x1 < 2 * x2 & x0 == x2 * x3 & x0 != x4;

// assert disjunction of relations
x0 < 10 | x0 > 100;

Clone this wiki locally