source: CIVL/examples/loop_invariants/loop_assigns_gen/lcp2.cvl

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/*
2 * Verify that the abstraction of function 'lcp2' is sound.
3 *
4 * Note: requires Why3 with TIMEOUT > 10 seconds!
5 *
6 * Command: civl verify -collectSymbolicConstants lcp2.cvl
7 */
8#include <stdlib.h>
9#include <string.h>
10#include <civlc.cvh>
11#include <assert.h>
12
13#pragma CIVL ACSL
14
15$input int N;
16$assume(N > 0);
17$input int X1[N];
18
19/* string 'x' is not greater than string 'y' with the specific length */
20/*@
21 @ predicate ngt_len(int * X1, int N, int x, int y, int l) =
22 @ 0 <= l && l <= N && x + l <= N && y + l <= N
23 @ && (x + l == N || (y + l < N ==> X1[y+l] > X1[x+l]))
24 @ && (\forall int k1; 0 <= k1 && k1 < l ==> X1[(x)+k1] == X1[(y)+k1]);
25 */
26
27/* string 'x' is NOT greater than string 'y' */
28/*@
29 @ predicate ngt(int * X1, int N, int x, int y) =
30 @ (\exists int l; ngt_len(X1, N, x, y, l) &&
31 @ !(\exists int o; ngt_len(X1, N, x, y, o) && o != l)
32 @ );
33 @*/
34
35int lcp(int *arr, int n, int x, int y) {
36 int l = 0;
37
38 /*@ loop invariant 0 <= l && l <= n;
39 @ loop invariant 0 <= x + l && x + l <= n;
40 @ loop invariant 0 <= y + l && y + l <= n;
41 @ loop invariant \forall int i; 0 <= i && i < l ==> arr[x+i]==arr[y+i];
42 @*/
43 while (x+l<n && y+l<n && arr[x+l]==arr[y+l]) {
44 l++;
45 }
46 return l;
47}
48
49/* returns:
50 * 0 if x and y points to the same suffix;
51 * poistive value if x "is greater than" y;
52 * negative or zero value if x "is NO greater than" y;
53 */
54int compare(int *a, int n, int x, int y) {
55 if (x == y) return 0;
56
57 int c = $choose_int(2);
58 int ret;
59
60 $havoc(&ret);
61 if (c == 0) {
62 $assume(ngt(X1, N, x, y) && ret <= 0);
63 return ret;
64 } else {
65 $assume(ngt(X1, N, y, x) && ret > 0);
66 return ret;
67 }
68}
69
70void sort(int *a, int n, int *data) {
71 /*@ loop invariant 1 <= i && i <= n;
72 @ loop invariant \forall int k; 1 <= k && k < i ==> ngt(a, n, data[k-1],data[k]);
73 @ loop invariant \forall int k; 0 <= k && k < n ==> 0 <= data[k] && data[k] < n; // data elements are valid
74 @ loop invariant \forall int t, k; 0 <= k && k < n && 0 <= t && t < n && k != t ==>
75 @ data[k] != data[t];
76 @ loop assigns i, data[0 .. n-1];
77 @*/
78 for(int i = 1; i < n; i++) {
79 int comp = compare(a, n, data[i - 1], data[i]);
80
81 /*@ loop invariant 0 <= j && j <= i;
82 @ loop invariant \forall int k; 0 <= k && k < n ==> 0 <= data[k] && data[k] < n; // data elements are valid
83 @ loop invariant \forall int t, k; 0 <= k && k < n && 0 <= t && t < n && k != t ==>
84 @ data[k] != data[t];
85 @ loop invariant \forall int k; j < k && k <= i ==> ngt(a, n, data[k-1],data[k]);
86 @ loop invariant \forall int k; 0 < k && k < j ==> ngt(a, n, data[k-1],data[k]);
87 @ loop invariant comp <= 0 ==> (\forall int k; 0 < k && k <= j ==> ngt(a, n, data[k-1],data[k]));
88 @ loop invariant (comp > 0 && 0 < j) ==> ngt(a, n, data[j], data[j-1]);
89 @ loop invariant (comp > 0 && 0 < j && j < i) ==> ngt(a, n, data[j-1], data[j+1]) ;
90 @ loop assigns j, comp, data[0 .. n-1];
91 @*/
92 for(int j = i; j > 0 && comp > 0;) {
93 // swap:
94 int tmp = data[j];
95
96 data[j] = data[j-1];
97 data[j-1] = tmp;
98 j--;
99 if (j > 0)
100 comp = compare(a, n, data[j - 1], data[j]);
101 }
102 }
103 $assert($forall (int i : 1 .. N-1) ngt(a, n, data[i - 1], data[i]));
104}
105
106/* An abstraction of the 'sort' function */
107void sort2(int *a, int n, int *data) {
108 int new_data[n];
109
110 memcpy(data, new_data, sizeof(int) * n);
111 $assume($forall (int i : 1 .. N-1) ngt(a, n, data[i - 1], data[i]));
112 $assume($forall (int i : 0 .. N-1) 0 <= data[i] && data[i] < n);
113 $assume($forall (int i : 0 .. N-1)
114 ($forall (int j | 0 <= j && j < N && j != i) data[i] != data[j])
115 );
116}
117
118int lcp2(int *a, int n, int index, int* suffixes) {
119 return lcp(a,n,suffixes[index], suffixes[index-1]);
120}
121
122/**
123result[0]: index
124result[1]: length
125*/
126void lrs(int* a, int n, int *result) {
127 int suffixes[n];
128
129 /*@ loop invariant 0 <= i && i <= n;
130 @ loop invariant \forall int t; 0 <= t && t < i ==> suffixes[t] == t;
131 @ loop assigns suffixes[0 .. n-1], i;
132 @*/
133 for(int i=0; i<n; i++) {
134 suffixes[i] = i;
135 }
136
137 sort2(a, n, suffixes);
138
139 int arbi_idx;
140 int len;
141
142 $havoc(&arbi_idx);
143 $assume(0 < arbi_idx && arbi_idx < n);
144 len = lcp2(a, n, arbi_idx, suffixes);
145 $assert(ngt_len(a, n, suffixes[arbi_idx-1], suffixes[arbi_idx], len));
146}
147
148int main() {
149 int result[2] = {0, 0};
150 lrs(X1, N, result);
151}
152
Note: See TracBrowser for help on using the repository browser.