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.