This example reads grades from an input array. The number of each grade level is counted. If there are more than 10 "F"s, the output variable excessiveFailure is set to 1.
In the implementation, there is an error in that the excessiveFailure variable is set based on the number of "D"s rather than the number of "F"s. This example exhibits the value of TASS's loop co-invariant functionality. Using traditional model checking techniques, a depth first search of the state space occurs. This search is exponential in the number of students (N_BOUND). With TASS's loop co-invariants, the bug is quickly discovered.
#pragma TASS input {N_BOUND > 0}
int N_BOUND;
#pragma TASS input {N > 0 && N < N_BOUND}
int N;
#pragma TASS input
double scores[N];
#pragma TASS output
int excessiveFailure;
int failureFlag = 0;
int numGrade[5];
void main() {
int i = 0;
for(; i < 5; i++)
numGrade[i] = 0;
i=0;
l:
while(i < N) {
if(scores[i] >= 90.0)
numGrade[0]++;
else if(scores[i] >= 80.0)
numGrade[1]++;
else if(scores[i] >= 70.0)
numGrade[2]++;
else if(scores[i] >= 60.0)
numGrade[3]++;
else
numGrade[4]++;
if(numGrade[4] > 10)
failureFlag = 1;
i++;
}
excessiveFailure = failureFlag;
}
#pragma TASS input {N_BOUND > 0}
int N_BOUND;
#pragma TASS input {N > 0 && N < N_BOUND}
int N;
#pragma TASS input
double scores[N];
#pragma TASS output
int excessiveFailure;
int failureFlag = 0;
int numGrade[5];
void main() {
int i = 0;
for(; i < 5; i++)
numGrade[i] = 0;
i=0;
l:
#pragma TASS jointinvariant @main {numGrade[0] == spec.numGrade[0] && numGrade[1]
== spec.numGrade[1] && numGrade[2] == spec.numGrade[2] && numGrade[3] ==
spec.numGrade[3] && numGrade[4] == spec.numGrade[4] && failureFlag == spec.failureFlag
&& i >= 0 && i == spec.i}
while(i < N) {
if(scores[i] >= 90.0)
numGrade[0]++;
else if(scores[i] >= 80.0)
numGrade[1]++;
else if(scores[i] >= 70.0)
numGrade[2]++;
else if(scores[i] >= 60.0)
numGrade[3]++;
else
numGrade[4]++;
if(numGrade[3] > 10)
failureFlag = 1;
i++;
}
excessiveFailure = failureFlag;
}
$ ./tass compare -loop examples/gradeCount/gradeCountSpec.c
examples/gradeCount/gradeCountImpl.c
+----------------------------------------------------------------------+
| TASS: Toolkit for Accurate Scientific Software |
| version 1.0_r1777 (2010-07-12) http://vsl.cis.udel.edu/tass |
+----------------------------------------------------------------------+
specification : gradeCountSpec (numProcs = 1)
specSourceFile : examples/gradeCount/gradeCountSpec.c
implementation : gradeCountImpl (numProcs = 1)
implSourceFile : examples/gradeCount/gradeCountImpl.c
mode : COMPARE
prover : CVC3
deadlock : ABSOLUTE
reduction : URGENT
simplify : true
simplifyProver : false
bufferBound : 10
verbose : false
loop method : true
repository : ./TASSREP
frontend : MINIMP
errorBound : 1
Comparing gradeCountSpec and gradeCountImpl...
************ ERROR DETECTED ************
Execution error (kind: FUNCTIONAL_COMPATIBILITY, certainty: MAYBE)
Corresponpdence of joint invariants could not be established.
with:
Process 0 at location 4: gradeCountSpec.c 19.1--19.13: "while(i < N)"
Process 1 at location 4: gradeCountImpl.c 21.1--21.13: "while(i < N)"
Writing trace to gradeCountSpec_gradeCountImpl.trace...Invalid query pc => co-invariants
in corresponding loops.
{gradeCountSpec_numGrade_l_0[4]=90, gradeCountImpl_numGrade_l_0[1]=0,
gradeCountSpec_numGrade_l_0[1]=0, gradeCountSpec_numGrade_l_0[3]=0, gradeCountSpec_i_l_0=0,
gradeCountImpl_numGrade_l_0[2]=0, gradeCountSpec_numGrade_l_0=(ARRAY (arr_var: INT): IF
(arr_var = 0) THEN 0 ELSE IF (arr_var = 1) THEN 0 ELSE IF (arr_var = 2) THEN 0 ELSE IF
(arr_var = 3) THEN 0 ELSE 90 ENDIF ENDIF ENDIF ENDIF), gradeCountSpec_failureFlag_l_0=0,
gradeCountSpec_numGrade_l_0[2]=0, gradeCountImpl_numGrade_l_0=(ARRAY (arr_var: INT): IF
(arr_var = 0) THEN 0 ELSE IF (arr_var = 1) THEN 0 ELSE IF (arr_var = 2) THEN 0 ELSE IF
(arr_var = 3) THEN 0 ELSE 90 ENDIF ENDIF ENDIF ENDIF), gradeCountImpl_numGrade_l_0[4]=90,
X1=1, X0=2, gradeCountImpl_numGrade_l_0[0]=0, gradeCountImpl_numGrade_l_0[3]=0, X2=(ARRAY
(arr_var: INT): 90), gradeCountImpl_failureFlag_l_0=0, gradeCountSpec_numGrade_l_0[0]=0,
gradeCountImpl_i_l_0=0, X2[0]=90}
done.
Writing model gradeCountSpec.model...done.
Writing model gradeCountImpl.model...done.
STATS:
statesSeen : 53
statesMatched : 1
statesSaved : 53
transitions : 53
numValues : 154
numQueries : 23
numMessages : 0
numValidCalls : 0
numSimplifyCalls : 0
time : 1.113s.
RESULT: gradeCountSpec and gradeCountImpl MAY NOT be functionally equivalent. Counterexample found.