Constraint guards are predicate expressions that function as guards against the creation of constraints, and not as logical relations to be satisfied by the solver. These predicate expressions &&,|| and ! are evaluated before the constraints are solved. This enables users to write constraints that avoid errors due to nonexistent object handles or array indices out of bounds.
There are 4 states when a sub expression is evlauated.
0 FALSE Subexpression evaluates to FALSE.
1 TRUE Subexpression evaluates to TRUE.
E ERROR Subexpression causes an evaluation error like null pointer.
R RANDOM Expression includes random variables and cannot be evaluated.
If any of subexpression results ERROR,then randomization fails.
EXAMPLE:1 class SList_97;
randint n;
rand Slist_97 next;
constraint sort { n < next.n; }
endclass
In the Example 1, while sorting the elements of array in ascending order, if next is null i.e for last element randomization fails.
EXAMPLE:2 class SList_98;
randint n;
rand Slist_98 next;
constraint sort { if( next != null ) n < next.n; }
endclass
In Example 2, Even if next is null, constraint wont be generated so randomization will never fail.
EXAMPLE:3 class D;
int x;
endclass class C;
randint x, y;
D a, b;
constraint c1 { (x < y || a.x > b.x || a.x == 5 ) -> x+y == 10; }
endclass
In Example 3, the predicate subexpressions are (x < y), (a.x > b.x), and (a.x == 5), which are all
connected by disjunction. Some possible cases are as follows:
Case 1: a is non-null, b is null, a.x is 5.
Because (a.x==5) is true, the fact that b.x generates an error does not result in an error.
The unconditional constraint (x+y == 10) is generated.
Case 2: a is null.
This always results in error, irrespective of the other conditions.
Case 3: a is non-null, b is non-null, a.x is 10, b.x is 20.
All the guard subexpressions evaluate to FALSE.
The conditional constraint (x<y) -> (x+y == 10) is generated.
EXAMPLE:4 class D;
int x;
endclass class C;
randint x, y;
D a, b;
constraint c1 { (x < y && a.x > b.x && a.x == 5 ) -> x+y == 10; }
endclass
In Example 4, the predicate subexpressions are (x < y), (a.x > b.x), and (a.x == 5), which are all
connected by conjunction. Some possible cases are as follows:
Case 1: a is non-null, b is null, a.x is 6.
Because (a.x==5) is false, the fact that b.x generates an error does not result in an error.
The constraint is eliminated.
Case 2: a is null
This always results in error, irrespective of the other conditions.
Case 3: a is non-null, b is non-null, a.x is 5, b.x is 2.
All the guard subexpressions evaluate to TRUE, producing constraint (x<y) -> (x+y == 10).
EXAMPLE:5 class D;
int x;
endclass class C;
randint x, y;
D a, b;
constraint c1 { (x < y && (a.x > b.x || a.x ==5)) -> x+y == 10; }
endclass
In Example 5, the predicate subexpressions are (x < y) and (a.x > b.x || a.x == 5), which are connected
by disjunction. Some possible cases are as follows:
Case 1: a is non-null, b is null, a.x is 5.
The guard expression evaluates to (ERROR || a.x==5), which evaluat es to (ERROR || TRUE)
The guard subexpression evaluates to TRUE.
The conditional constraint (x<y) -> (x+y == 10) is generated.
Case 2: a is non-null, b is null, a.x is 8.
The guard expression evaluates to (ERROR || FALSE) and generates an error.
Case 3: a is null
This always results in error, irrespective of the other conditions.
Case 4: a is non-null, b is non-null, a.x is 5, b.x is 2.
All the guard subexpressions evaluate to TRUE.
The conditional constraint (x<y) -> (x+y == 10) is generated.
EXAMPLE:6
class A_108;
randinteger arr[];
constraint c { foreach( arr[i]) arr[i] == arr[i+1] ;}
endclass
In Example 6, generates an error when i is the last element in the array.