Fixed some minor errors and clarified some things

This commit is contained in:
David Holland 2021-06-10 11:50:12 +02:00
parent 8d17f39761
commit ea5abff33f
1 changed files with 49 additions and 19 deletions

View File

@ -159,10 +159,23 @@ public class HighSoreTable {
* 2 if new high score * 2 if new high score
* 1 if otherwise * 1 if otherwise
*/ */
//@ requires newScore >= 0; /*@ requires newScore >= 0;
//@ ensures (\forall int i; 0<=i && i<10; newScore <= \old(scores[i])) ==> (\result == 0); @ ensures (\forall int i; 0<=i && i<10;
//@ ensures (\exists int i; 0<=i && i<10; newScore > \old(scores[i])) && (\exists int i; 0<=i && i<10; newScore <= \old(scores[i])) ==> (\result == 1); @ newScore <= \old(scores[i])
//@ ensures (\forall int i; 0<=i && i<10; newScore > \old(scores[i])) ==> (\result == 2); @ )
@ ==> (\result == 0);
@ ensures (\exists int i; 0<=i && i<10;
@ newScore > \old(scores[i])
@ )
@ && (\exists int i; 0<=i && i<10;
@ newScore <= \old(scores[i])
@ )
@ ==> (\result == 1);
@ ensures (\forall int i; 0<=i && i<10;
@ newScore > \old(scores[i])
@ )
@ ==> (\result == 2);
@*/
public int addScore(int newScore) { public int addScore(int newScore) {
// [...] // [...]
} }
@ -193,7 +206,7 @@ public class HighSoreTable {
@ (\forall int i; 0<=i && i<10; @ (\forall int i; 0<=i && i<10;
@ score <= \old(scores[i]) @ score <= \old(scores[i])
@ ); @ );
*/ @*/
//@ ensures lowerThanMin(newScore) ==> (\result == 0); //@ ensures lowerThanMin(newScore) ==> (\result == 0);
// [...] // [...]
public int addScore(int newScore) { public int addScore(int newScore) {
@ -212,7 +225,7 @@ So for example
@ (\forall int i; 0<=i && i<10; @ (\forall int i; 0<=i && i<10;
@ score <= \old(scores[i]) @ score <= \old(scores[i])
@ ); @ );
*/ @*/
//@ ensures lowerThanMin(newScore) ==> (\result == 0); //@ ensures lowerThanMin(newScore) ==> (\result == 0);
\end{minted} \end{minted}
@ -235,7 +248,7 @@ In the case of a type mismatch between macro parameter usage and parameter input
@ (\forall int i; 0<=i && i<10; @ (\forall int i; 0<=i && i<10;
@ score <= \old(scores[i]) @ score <= \old(scores[i])
@ ); @ );
*/ @*/
//@ ensures lowerThanMin(newScore) ==> (\result == 0); //@ ensures lowerThanMin(newScore) ==> (\result == 0);
\end{minted} \end{minted}
@ -252,10 +265,9 @@ Another problem not solved by this approach, especially not with using a simplis
/*@ def lowerThanMin(int score) = /*@ def lowerThanMin(int score) =
@ (\forall int i; 0<=i && i<10; @ (\forall int i; 0<=i && i<10;
@ score <= \old(scores[i]) @ score <= \old(scores[i])
@ && @ && lowerThanMin(score-1)
@ lowerThanMin(score-1)
@ ); @ );
*/ @*/
//@ ensures lowerThanMin(newScore) ==> (\result == 0); //@ ensures lowerThanMin(newScore) ==> (\result == 0);
\end{minted} \end{minted}
@ -274,10 +286,9 @@ This property of a minimal score can then be reused and clearly states what it d
/*@ def minScore = /*@ def minScore =
@ (\some int score; @ (\some int score;
@ (\exists int i; 0<=i && i<10; score == scores[i]) @ (\exists int i; 0<=i && i<10; score == scores[i])
@ && @ && (\forall int i; 0<=i && i<10; score <= scores[i])
@ (\forall int i; 0<=i && i<10; score <= scores[i])
@ ); @ );
*/ @*/
//@ ensures newScore <= \old(minScore) ==> (\result ==0); //@ ensures newScore <= \old(minScore) ==> (\result ==0);
\end{minted} \end{minted}
@ -342,14 +353,13 @@ An implementation could therefore be possible using something like this pseudo c
/*@ def minScore = /*@ def minScore =
@ (\ifEx int score; @ (\ifEx int score;
@ (\exists int i; 0<=i && i<10; score == scores[i]) @ (\exists int i; 0<=i && i<10; score == scores[i])
@ && @ && (\forall int i; 0<=i && i<10; score <= scores[i])
@ (\forall int i; 0<=i && i<10; score <= scores[i])
@ \then @ \then
@ return score @ return score
@ \else @ \else
@ return None @ return None
@ ); @ );
*/ @*/
//@ ensures newScore <= \old(minScore) ==> (\result == 0); //@ ensures newScore <= \old(minScore) ==> (\result == 0);
\end{minted} \end{minted}
@ -360,6 +370,26 @@ This could also be something some kind of ghosting variable could achieve, but I
For the time being, one could inline this whole concept and possibly have a working example, though this would not necessarily improve either readability or code reusage, but definitely increase versatility and expressiveness. For the time being, one could inline this whole concept and possibly have a working example, though this would not necessarily improve either readability or code reusage, but definitely increase versatility and expressiveness.
\begin{minted}{java}
/*@ ensures
@ (\ifEx int minScore;
@ (\exists int i; 0<=i && i<10; minScore == scores[i])
@ && (\forall int i; 0<=i && i<10; minScore <= scores[i])
@ \then
@ newScore <= minScore ==> (\result == 0)
@ \else
@ \result != 0
@ );
@*/
\end{minted}
Note however that I noticed the \texttt{\tbs{}else} branch is not really doing what it should be.
The else part doesn't handle the case of the \texttt{newScore} being higher than the minScore!
Instead it is handling the case when \emph{no} \texttt{minScore}, with the property of being an element in the \texttt{scores} array, as well as being the smallest element in this array, exists!
So in this case this would mean that our high score table is empty.
So this branch should either throw some kind of error, or rather make sure the ensures doesn't evaluate to true in that case, if this behaviour is not allowed, or if this is allowed, handle this case differently.
In case it isn't allowed to have an empty high score table, the example should be like follows
\begin{minted}{java} \begin{minted}{java}
/*@ ensures /*@ ensures
@ (\ifEx int minScore; @ (\ifEx int minScore;
@ -368,10 +398,10 @@ For the time being, one could inline this whole concept and possibly have a work
@ (\forall int i; 0<=i && i<10; minScore <= scores[i]) @ (\forall int i; 0<=i && i<10; minScore <= scores[i])
@ \then @ \then
@ newScore <= minScore ==> (\result == 0) @ newScore <= minScore ==> (\result == 0)
@ \else @ \else
@ \result != 0 @ false
@ ); @ );
*/ @*/
\end{minted} \end{minted}
The main difficulty of this approach is the handling of the bound variable, the way of returning the notion of the fulfilling value to the caller, as in the notion of a value matching the property description, as well as handling the case of no value fulfilling the formula. The main difficulty of this approach is the handling of the bound variable, the way of returning the notion of the fulfilling value to the caller, as in the notion of a value matching the property description, as well as handling the case of no value fulfilling the formula.