| 1 | /*
|
|---|
| 2 | * Function 'compare' are all abstracted, too many unnecessary non-determinisms.
|
|---|
| 3 | *
|
|---|
| 4 | * Command: civl verify -collectSymbolicConstants sort_deductive.cvl
|
|---|
| 5 | */
|
|---|
| 6 | #include <stdlib.h>
|
|---|
| 7 | #include <string.h>
|
|---|
| 8 | #include <civlc.cvh>
|
|---|
| 9 | #include <assert.h>
|
|---|
| 10 |
|
|---|
| 11 | #pragma CIVL ACSL
|
|---|
| 12 |
|
|---|
| 13 | $input int N;
|
|---|
| 14 | $assume(N > 0);
|
|---|
| 15 | $input int X1[N];
|
|---|
| 16 |
|
|---|
| 17 | /* string 'x' is not greater than string 'y' with the specific length */
|
|---|
| 18 | /*@
|
|---|
| 19 | @ predicate ngt_len(int * X1, int N, int x, int y, int l) =
|
|---|
| 20 | @ 0 <= l && l <= N && x + l <= N && y + l <= N
|
|---|
| 21 | @ && (x + l == N || (y + l < N ==> X1[y+l] > X1[x+l]))
|
|---|
| 22 | @ && (\forall int k1; 0 <= k1 && k1 < l ==> X1[(x)+k1] == X1[(y)+k1]);
|
|---|
| 23 | */
|
|---|
| 24 |
|
|---|
| 25 | /* string 'x' is NOT greater than string 'y' */
|
|---|
| 26 | /*@
|
|---|
| 27 | @ predicate ngt(int * X1, int N, int x, int y) =
|
|---|
| 28 | @ (\exists int l; ngt_len(X1, N, x, y, l) &&
|
|---|
| 29 | @ !(\exists int o; ngt_len(X1, N, x, y, o) && o != l)
|
|---|
| 30 | @ );
|
|---|
| 31 | @*/
|
|---|
| 32 |
|
|---|
| 33 | int lcp(int *arr, int n, int x, int y) {
|
|---|
| 34 | int l = 0;
|
|---|
| 35 |
|
|---|
| 36 | /*@ loop invariant 0 <= l && l <= n;
|
|---|
| 37 | @ loop invariant 0 <= x + l && x + l <= n;
|
|---|
| 38 | @ loop invariant 0 <= y + l && y + l <= n;
|
|---|
| 39 | @ loop invariant \forall int i; 0 <= i && i < l ==> arr[x+i]==arr[y+i];
|
|---|
| 40 | @ loop assigns l;
|
|---|
| 41 | @*/
|
|---|
| 42 | while (x+l<n && y+l<n && arr[x+l]==arr[y+l]) {
|
|---|
| 43 | l++;
|
|---|
| 44 | }
|
|---|
| 45 | return l;
|
|---|
| 46 | }
|
|---|
| 47 |
|
|---|
| 48 | /* returns:
|
|---|
| 49 | * 0 if x and y points to the same suffix;
|
|---|
| 50 | * poistive value if x "is greater than" y;
|
|---|
| 51 | * negative or zero value if x "is NO greater than" y;
|
|---|
| 52 | */
|
|---|
| 53 | int compare(int *a, int n, int x, int y) {
|
|---|
| 54 | if (x == y) return 0;
|
|---|
| 55 |
|
|---|
| 56 | int c = $choose_int(2);
|
|---|
| 57 | int ret;
|
|---|
| 58 |
|
|---|
| 59 | $havoc(&ret);
|
|---|
| 60 | if (c == 0) {
|
|---|
| 61 | $assume(ngt(a, n, x, y) && ret <= 0);
|
|---|
| 62 | return ret;
|
|---|
| 63 | } else {
|
|---|
| 64 | $assume(ngt(a, n, y, x) && ret > 0);
|
|---|
| 65 | return ret;
|
|---|
| 66 | }
|
|---|
| 67 | }
|
|---|
| 68 |
|
|---|
| 69 | void sort(int *a, int n, int *data) {
|
|---|
| 70 | /*@ loop invariant 1 <= i && i <= n;
|
|---|
| 71 | @ loop invariant \forall int k; 1 <= k && k < i ==> ngt(a, n, data[k-1],data[k]);
|
|---|
| 72 | @ loop invariant \forall int k; 0 <= k && k < n ==> 0 <= data[k] && data[k] < n; // data elements are valid
|
|---|
| 73 | @ loop invariant \forall int t, k; 0 <= k && k < n && 0 <= t && t < n && k != t ==>
|
|---|
| 74 | @ data[k] != data[t];
|
|---|
| 75 | @ loop assigns i, data[0 .. n-1];
|
|---|
| 76 | @*/
|
|---|
| 77 | for(int i = 1; i < n; i++) {
|
|---|
| 78 | int comp = compare(a, n, data[i - 1], data[i]);
|
|---|
| 79 |
|
|---|
| 80 | /*@ loop invariant 0 <= j && j <= i;
|
|---|
| 81 | @ loop invariant \forall int k; 0 <= k && k < n ==> 0 <= data[k] && data[k] < n; // data elements are valid
|
|---|
| 82 | @ loop invariant \forall int t, k; 0 <= k && k < n && 0 <= t && t < n && k != t ==>
|
|---|
| 83 | @ data[k] != data[t];
|
|---|
| 84 | @ loop invariant \forall int k; j < k && k <= i ==> ngt(a, n, data[k-1],data[k]);
|
|---|
| 85 | @ loop invariant \forall int k; 0 < k && k < j ==> ngt(a, n, data[k-1],data[k]);
|
|---|
| 86 | @ loop invariant comp <= 0 ==> (\forall int k; 0 < k && k <= j ==> ngt(a, n, data[k-1],data[k]));
|
|---|
| 87 | @ loop invariant (comp > 0 && 0 < j) ==> ngt(a, n, data[j], data[j-1]);
|
|---|
| 88 | @ loop invariant (comp > 0 && 0 < j && j < i) ==> ngt(a, n, data[j-1], data[j+1]) ;
|
|---|
| 89 | @ loop assigns j, comp, data[0 .. n-1];
|
|---|
| 90 | @*/
|
|---|
| 91 | for(int j = i; j > 0 && comp > 0;) {
|
|---|
| 92 | // swap:
|
|---|
| 93 | int tmp = data[j];
|
|---|
| 94 |
|
|---|
| 95 | data[j] = data[j-1];
|
|---|
| 96 | data[j-1] = tmp;
|
|---|
| 97 | j--;
|
|---|
| 98 | if (j > 0)
|
|---|
| 99 | comp = compare(a, n, data[j - 1], data[j]);
|
|---|
| 100 | }
|
|---|
| 101 | }
|
|---|
| 102 | $assert($forall (int i : 1 .. N-1) ngt(a, n, data[i - 1], data[i]));
|
|---|
| 103 | }
|
|---|
| 104 |
|
|---|
| 105 | int main() {
|
|---|
| 106 | int result[2] = {0, 0};
|
|---|
| 107 | int n = N;
|
|---|
| 108 | int suffixes[n];
|
|---|
| 109 |
|
|---|
| 110 | /*@ loop invariant 0 <= i && i <= n;
|
|---|
| 111 | @ loop invariant \forall int t; 0 <= t && t < i ==> suffixes[t] == t;
|
|---|
| 112 | @ loop assigns suffixes[0 .. n-1], i;
|
|---|
| 113 | @*/
|
|---|
| 114 | for(int i=0; i<n; i++) {
|
|---|
| 115 | suffixes[i] = i;
|
|---|
| 116 | }
|
|---|
| 117 | sort(X1, n, suffixes);
|
|---|
| 118 | return 0;
|
|---|
| 119 | }
|
|---|
| 120 |
|
|---|