source: CIVL/examples/loop_invariants/verifyThisUB/longestRepeatedSubstring/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.4 KB
RevLine 
[2fa0abd]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 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 x, int y) =
30 @ (\exists int l; ngt_len(x, y, l) &&
31 @ !(\exists int o; ngt_len(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 @ loop assigns l;
43 @*/
44 while (x+l<n && y+l<n && arr[x+l]==arr[y+l]) {
45 l++;
46 }
47 return l;
48}
49
50/* returns:
51 * 0 if x and y points to the same suffix;
52 * poistive value if x "is greater than" y;
53 * negative or zero value if x "is NO greater than" y;
54 */
55int compare(int *a, int n, int x, int y) {
56 if (x == y) return 0;
57
58 int c = $choose_int(2);
59 int ret;
60
61 $havoc(&ret);
62 if (c == 0) {
63 $assume(ngt(x, y) && ret <= 0);
64 return ret;
65 } else {
66 $assume(ngt(y, x) && ret > 0);
67 return ret;
68 }
69}
70
71void sort(int *a, int n, int *data) {
72 /*@ loop invariant 1 <= i && i <= n;
73 @ loop invariant \forall int k; 1 <= k && k < i ==> ngt(data[k-1],data[k]);
74 @ loop invariant \forall int k; 0 <= k && k < n ==> 0 <= data[k] && data[k] < n; // data elements are valid
75 @ loop invariant \forall int t, k; 0 <= k && k < n && 0 <= t && t < n && k != t ==>
76 @ data[k] != data[t];
77 @ loop assigns i, data[0 .. n-1];
78 @*/
79 for(int i = 1; i < n; i++) {
80 int comp = compare(a, n, data[i - 1], data[i]);
81
82 /*@ loop invariant 0 <= j && j <= i;
83 @ loop invariant \forall int k; 0 <= k && k < n ==> 0 <= data[k] && data[k] < n; // data elements are valid
84 @ loop invariant \forall int t, k; 0 <= k && k < n && 0 <= t && t < n && k != t ==>
85 @ data[k] != data[t];
86 @ loop invariant \forall int k; j < k && k <= i ==> ngt(data[k-1],data[k]);
87 @ loop invariant \forall int k; 0 < k && k < j ==> ngt(data[k-1],data[k]);
88 @ loop invariant comp <= 0 ==> (\forall int k; 0 < k && k <= j ==> ngt(data[k-1],data[k]));
89 @ loop invariant (comp > 0 && 0 < j) ==> ngt(data[j], data[j-1]);
90 @ loop invariant (comp > 0 && 0 < j && j < i) ==> ngt(data[j-1], data[j+1]) ;
91 @ loop assigns j, comp, data[0 .. n-1];
92 @*/
93 for(int j = i; j > 0 && comp > 0;) {
94 // swap:
95 int tmp = data[j];
96
97 data[j] = data[j-1];
98 data[j-1] = tmp;
99 j--;
100 if (j > 0)
101 comp = compare(a, n, data[j - 1], data[j]);
102 }
103 }
104 $assert($forall (int i : 1 .. N-1) ngt(data[i - 1], data[i]));
105}
106
107/* An abstraction of the 'sort' function */
108void sort2(int *a, int n, int *data) {
109 int new_data[n];
110
111 memcpy(data, new_data, sizeof(int) * n);
112 $assume($forall (int i : 1 .. N-1) ngt(data[i - 1], data[i]));
113 $assume($forall (int i : 0 .. N-1) 0 <= data[i] && data[i] < n);
114 $assume($forall (int i : 0 .. N-1)
115 ($forall (int j | 0 <= j && j < N && j != i) data[i] != data[j])
116 );
117}
118
119int lcp2(int *a, int n, int index, int* suffixes) {
120 return lcp(a,n,suffixes[index], suffixes[index-1]);
121}
122
123/**
124result[0]: index
125result[1]: length
126*/
127void lrs(int* a, int n, int *result) {
128 int suffixes[n];
129
130 /*@ loop invariant 0 <= i && i <= n;
131 @ loop invariant \forall int t; 0 <= t && t < i ==> suffixes[t] == t;
132 @ loop assigns suffixes[0 .. n-1], i;
133 @*/
134 for(int i=0; i<n; i++) {
135 suffixes[i] = i;
136 }
137
138 sort2(a, n, suffixes);
139
140 int arbi_idx;
141 int len;
142
143 $havoc(&arbi_idx);
144 $assume(0 < arbi_idx && arbi_idx < n);
145 len = lcp2(a, n, arbi_idx, suffixes);
146 $assert(ngt_len(suffixes[arbi_idx-1], suffixes[arbi_idx], len));
147}
148
149int main() {
150 int result[2] = {0, 0};
151 lrs(X1, N, result);
152}
153
Note: See TracBrowser for help on using the repository browser.