Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to prove this function, but in vain. I'm also using another function, but I proved it.
Could anyone help me?
I'm using Frama-C Sodium version with Alt-ergo 3 as prover.
Given a not-empty string x. An integer number p such that
0 < p ≤|x| is meant to be "a period of x" if
x[i] = x[i + p]
for i = 0, 1, ... , |x| − p − 1.
Note that, for each not-empty string, the length of the string
is a period of itself. In this way, every not-empty string
has got at least one period. So is well formed the concept of minimum
period of string x, denoted by per(x):
per(x) = min { p | p is period of x }.
Write a C function
unsigned per(const char x[], unsigned l)
that, given a string x of length l, returns per(x).
Here is the code and the specifications I have written so far:
/*#
requires l > 0;
requires p >= 0;
behavior zero:
assumes p == l;
ensures \result == 1;
behavior one:
assumes l != p && (l%p) == 0;
assumes \forall int i; 0 <= i < l-p-1 ==> x[i] == x[i+p];
ensures \result == 1;
behavior two:
assumes l != p && (l%p) == 0;
assumes !(\forall int i; 0 <= i < l-p-1 ==> x[i] == x[i+p]);
ensures \result == 0;
behavior three:
assumes p != l && l%p != 0;
ensures \result == 0;
complete behaviors;
disjoint behaviors;
*/
unsigned has_period(const char x[], unsigned int p, unsigned l) {
if (p == l) return 1;
if ((l % p) != 0) return 0;
/*#
loop assigns i;
loop invariant \forall int j; 0 <= j < i ==> (x[j] == x[j+p]);
loop invariant i <= l-p-1;
loop invariant i >= 0;
*/
for (int i = 0 ; i < l-p-1 ; ++i) {
if (x[i] != x[i + p])
return 0;
}
return 1;
}
/*
predicate has_period(char* x, unsigned int p, unsigned l) =
\forall int i; i < (l-p-1) ==> x[i] == x[i+p];
*/
/*#
requires l > 0;
requires \valid(x+(0..l-1));
ensures 1 <= \result <= l;
ensures \forall unsigned int i; i < (l-\result-1) ==> x[i] == x[i+\result];
ensures \forall unsigned int p; 1 <= p < \result ==> !(\forall int i; i < (l-p-1) ==> x[i] == x[i+p]);
*/
unsigned per(const char x[], unsigned l) {
int p = 1;
/*#
loop assigns p;
loop invariant 1 <= p <= l;
loop invariant \forall unsigned j; 1 <= j < p ==> !(\forall int i; i < (l-j-1) ==> x[i] == x[i+j] || (l%p) == 0);
loop invariant p >= 0;
*/
while(p < l && !has_period(x,p,l))
++p;
return p;
}
It would have helped if you had told us what your specific issue was, instead of a generic "it doesn't work", but here are some points:
Your contracts are lacking assigns clause. These are not optional when using WP, especially for functions like has_period that are called within your development. WP needs those clauses to know which locations might have changed during the call, and by taking the complement, which locations have stayed the same.
You have given a nice semi-formal definition of what a periodic string is. You should use that to define an ACSL predicate periodic (taking the same arguments as your C function has_period), and write your specifications according to this predicate. This will simplify your annotations a lot. In particular has_period does not need 4 behaviors: if periodic holds it must return 1, if periodic does not hold, it must return 0.
Using -wp-rte leads to a bunch of unproved obligations. Depending on your assignment, you might want to strengthen your specifications, especially regarding the validity of the location pointed to by x.
Related
I am trying to prove the correctness of my sorting function 'order' with Frama-C with the ACSL language. I have an additional 'swap' function to permute two values of my array 't'.
EDIT :
I updated my code.
/*#
requires \valid (t+ (0..(l-1)));
requires l > 0;
requires i<l && j<l && i>=0 && j>=0;
assigns t[i], t[j];
ensures t[j] == \old(t[i]);
ensures t[i] == \old(t[j]);
*/
void swap(int *t, int l, int i,int j){
int tmp;
tmp = t[i];
t[i] = t[j];
t[j] = tmp;
return;
}
/*#
requires \valid (t+ (0..(l-1)));
requires l > 0;
ensures \forall integer k; (0 <= k < l-1) ==> t[k] <= t[k+1];
*/
void order(int *t, int l) {
int i;
int j;
/*#
loop assigns i, t[0 .. l-1];
loop invariant 0<=i<l && i>=0;
loop invariant \forall integer k; (0 <= k<=i) ==> t[k] <= t[k+1];
loop variant l-i;
*/
for (i=0;i<l;i++) {
/*#
loop assigns j, t[0 .. l-1];
loop invariant i<=j<l && i>=0 && j>=0;
loop invariant \forall integer k; (0 <= k <= j) ==> (t[k] <= t[k+1]);
loop variant l-j;
*/
for (j=i; j<l; j++) {
if (t[i] > t[j]){
/*# assert t[i] > t[j] && i<l && j<l && i>=0 && j>=0 ; */
swap(t, l, i, j);
/*# assert t[i] < t[j] && i<l && j<l && i>=0 && j>=0 ; */
}
}
}
}
Thanks for your help!
As always when using WP, it is crucial that all functions called by the function under proof are equipped with a contract with assigns clauses. Furthemore, all loops of said function under proof must have a loop assigns clause. If this is not the case, WP will conclude that any part of the memory state might be modified by the call (resp. the loop), so that it won't be able to say anything meaningful after the corresponding instruction.
Thus, at the very minimum, you should add/replace the existing clause by:
in the contract of swap, a clause assigns t[i], t[j];
in the loop annotation of the outer loop, a clause loop assigns i, t[0 .. l-1];
in the loop annotation of the inner loop, a clause loop assigns j, t[i .. l-1];
As as side note regarding loop assigns:
they must describe all the potential modifications from the first entry into the loop up to the current step (hence t[i], t[j] is not sufficient, as there might have been other swaps occuring before the current j).
the index of the loop (here i and j) must be part of the loop assigns, although it is very easy to overlook it and wonder why WP is not happy.
Note that there might be others issues with your annotations, but these are the most obvious ones, and having appropriate assigns clauses is probably the single most important thing to have before attempting to prove deeper functional properties.
I have my test code (to study the WP loop invariants) which adds two long integers with each digit's representation in an array cell:
int main(int argc, const char * argv[]) {
char a[32], b[32];//size can be very big
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
scanf("%s %s", a, b);
unsigned int size1 = strlen(a);
unsigned int size2 = strlen(b);
//code to reverse a string. currently proved
reverse(a, size1);
reverse(b, size2);
for (unsigned int i = 0; i < size1; i++) a[i]-='0'; //move from chars to integers
for (unsigned int j = 0; j < size2; j++) b[j]-='0';
unsigned int maxsize = size1;
if (size2 > maxsize) maxsize = size2;
int over = 0;
//actual computation code
/*#
loop invariant maxsize == \max(size1, size2);
loop invariant bound: 0 <= k <= maxsize;
loop invariant ov: \forall integer i; 0 < i < k ==> \at(a[i], Here) == (\at(a[i], Pre) + b[i]+ Over((char *)a, (char *)b, i)) % 10;
loop assigns k, a[0..maxsize-1],over;
loop variant maxsize - k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
char sum=a[k] + b[k] + over;
//over=overflow is for 9+9 = 18, result=8, over=1
a[k] = sum % 10;
over = sum / 10;
}
if (over != 0) a[maxsize++] = over;
//...
return 0;
}
I want to specify only the last loop invariant. I have already tried some pieces of ACSL code with \at(a[i], LoopCurrent). I received Unknown status or Timeout. Finally, I finished with an axiomatic recursive solution without any success.
I have no ideas now what else should I try to verify this. Help?
UPDATE:
Created a function for actual calculations. Improved axioms. Still got Timeout status. Ran with Frama-C latest release from opam with default settings (timeout=10, prover Alt-Ergo).
/*#
#predicate
Unchanged{K,L}(char* a, integer first, integer last) = \forall integer i; first <= i < last ==> \at(a[i],K) == \at(a[i],L);
axiomatic ReminderAxiomatic
{
logic integer Reminder {l} (integer x, integer y);
axiom ReminderEmpty: \forall integer x, integer y; x < y ==> Reminder(x, y) == x;
axiom ReminderNext: \forall integer x, integer y; x>=y ==> Reminder(x, y) == Reminder(x-y, y)+0;
}
axiomatic DivAxiomatic
{
logic integer Div {l} (integer x, integer y);
axiom DivEmpty: \forall integer x, integer y; x < y ==> Div(x, y) == 0 ;
axiom DivNext: \forall integer x, integer y; x >= y ==> Div(x, y) == Div(x - y, y) + 1 ;
}
axiomatic OverAxiomatic
{
logic integer Over {L}(char *a, char * b, integer step) reads a[0..step-1], b[0..step-1];
axiom OverEmpty: \forall char *a, char * b, integer step; step <= 0 ==> Over(a, b, step) == 0;
axiom OverNext: \forall char *a, char * b, integer step; step > 0 && a[step-1]<10 && a[step-1]>=0 && b[step-1]<10 && b[step-1]>=0
==> Over(a, b, step) == Div((int) a[step-1]+(int)b[step-1]+(int)Over(a,b,step-1), 10);
}
*/
/*#
requires 0 <= maxsize < 10;
requires \valid (a+(0..maxsize-1));
requires \valid (b+(0..maxsize-1));
requires \valid (res+(0..maxsize));
requires \forall integer i; 0 <= i < maxsize ==> 0 <= (int)a[i] < 10;
requires \forall integer i; 0 <= i < maxsize ==> 0 <= (int)b[i] < 10;
*/
void summ(char *a, char *b, char *res, unsigned int maxsize) {
char over = 0;
/*#
loop invariant bound: 0 <= k <=maxsize;
loop invariant step: \forall integer i; 0 <= i < k ==> res[i] == (char) Reminder((int)a[i]+ (int)b[i]+ (int)Over((char *)a, (char *)b, i) , 10);
loop invariant unch: Unchanged{Here,LoopEntry}((char *)res, k, maxsize);
loop assigns k, over, res[0..maxsize-1];
loop variant maxsize-k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
char sum = a[k] + b[k] + over;
res[k] = sum % 10;
over = sum / 10;
}
//
if (over != 0) res[maxsize++] = over;
}
First of all, it would be much better if your question contained a MCVE, which in the present case include the C function you're currently working on (instead of only its body), and the ACSL annotations you've written, at their exact place in the code. The command line used to launch Frama-C wouldn't hurt either, as well as the list of annotations for which you have trouble.
Apart from that, here are a few things that might be related to your problem (again, without an exact description, it's difficult to tell for sure).
the loop assigns is wrong: you're assigning over in the loop, but it is not mentioned there.
I'm unsure whether \max is well supported by WP.
modulo and integer division are two operations automated provers tend to struggle with. You might need a few additional assertions and/or axioms to help them.
your loop invariant does not say anything about the values of a[i] for k <= i< maxsize. Since loop assigns indicates that all cells of a might have been modified, you have to add an invariant telling that the ones with higher indices have not been touched so far.
I'm not completely sure about your usage of \at(a[i],Pre): Pre indicates the beginning of the current function. Thus, if scanf and reverse are in the same function as the loop (again, a MCVE would have clarified this), this is not true. You might want to speak about \at(a[i],Loop_entry) to refer to the value of the cell in the state in which the loop is entered for the first time.
UPDATE
I'm afraid WP will not be able to completely prove your annotations, but I managed to obtain a version in which only a single lemma, that is basically an expanded version of the reads clause for the Over function is left unproved (and I believe that there is no way to prove it under WP's actual representation of C memory). Note that it implies playing with the TIP feature of WP. Code and scripts are provided below, but I'll start by commenting on your original version:
there is no need for Div and Reminder. If anything, they will confuse the prover. You can stick with xxx/10 and xxx%10. In fact, my remark on division and modulo was a bit too cautious. In the present case, everything seems to be fine at this level.
Similarly, Unchanged could be inlined, but it shouldn't hurt to keep it that way.
I have used unsigned char instead of char, as it avoids some spurious conversions due to integer promotions, and removed any cast in the logic. You normally don't have to introduce such casts in ACSL annotations, except perhaps to indicate that some computation stays within an appropriate range (as in \let x = y + z; x == (int) x; ). Such casts are translated into function calls in the proof obligation, and again it can confuse the provers.
an invariant was missing to indicate that over does indeed contain the potential carry from the previous step (again, a good hint that you're missing an invariant is that a location mentioned in loop assigns does not appear in any loop invariant).
Finally, there is a small subtlety: if you don't indicate somehow that over can only be 0 or 1, there's nothing that prevent the addition to overflow the unsigned char (making it impossible to prove that a C computation with unsigned char and its ACSL counterpart with unbounded integers give the same result). Due to the recursive nature of the Over function, this can be established by a so-called lemma function in which the mathematical induction is carried out by a simple for loop with appropriate invariants
In addition, I've added explicitely as invariant that a and b are left untouched. This is normally implied by the loop assigns, but having these explicit hypotheses makes it easier during the scripts.
To sum up, here is the final code:
/*#
axiomatic Carry {
logic integer Over {L}(unsigned char* a, unsigned char* b, integer step)
reads a[0 .. step - 1], b[0 .. step - 1];
axiom null_step: \forall unsigned char* a, *b, integer step;
step <= 0 ==> Over(a,b,step) == 0;
axiom prev_step: \forall unsigned char* a, *b, integer step;
step > 0 ==>
Over(a,b,step) ==
(a[step-1] + b[step - 1] + Over(a,b,step-1)) / 10;
lemma OverFootPrint{L1,L2}:
\forall unsigned char* a, unsigned char*b, integer step;
(\forall integer i; 0<=i<step ==> \at(a[i],L1) == \at(a[i],L2)) &&
(\forall integer i; 0<=i<step ==> \at(b[i],L1) == \at(b[i],L2)) ==>
Over{L1}(a,b,step) == Over{L2}(a,b,step);
}
*/
/*#
requires \valid(a+(0 .. step-1));
requires \valid(b+(0 .. step - 1));
requires \forall integer i; 0<=i<step ==> 0<=a[i]<10 && 0<=b[i]<10;
assigns \nothing;
ensures 0<= Over(a,b,step) <= 1;
*/
void lemma_function(unsigned char* a, unsigned char* b, unsigned int step) {
/*#
loop invariant 0<=i<=step;
loop invariant \forall integer k; 0<=k<=i ==> 0 <= Over(a, b, k) <= 1;
loop assigns i;
*/
for (int i = 0; i < step; i++);
}
/*#
requires 0 <= maxsize < 10;
requires \valid (a+(0..maxsize-1));
requires \valid (b+(0..maxsize-1));
requires \valid (res+(0..maxsize));
requires \separated (a+(0..maxsize-1),res+(0..maxsize));
requires \separated (b+(0..maxsize-1),res+(0..maxsize));
requires \forall integer i; 0 <= i < maxsize ==> 0 <= a[i] < 10;
requires \forall integer i; 0 <= i < maxsize ==> 0 <= b[i] < 10;
*/
void summ(unsigned char* a, unsigned char*b, unsigned char* res,
unsigned int maxsize) {
unsigned char over = 0;
/*#
loop invariant bound: 0 <= k <=maxsize;
loop invariant step: \forall integer i; 0 <= i < k ==> res[i] == (a[i]+ b[i]+ Over(a,b,i)) % 10;
loop invariant over: over == Over(a,b,k);
loop invariant a_unchanged: \forall integer i; 0 <= i < maxsize ==>
\at(a[i],LoopEntry) == a[i];
loop invariant b_unchanged: \forall integer i; 0 <= i < maxsize ==>
\at(b[i],LoopEntry) == b[i];
loop invariant unch: \forall integer i; k<=i<=maxsize ==> \at(res[i],LoopEntry) == res[i];
loop assigns k, over, res[0..maxsize-1];
loop variant maxsize-k;
*/
for (unsigned int k = 0; k < maxsize; k++)
{
unsigned char sum = a[k] + b[k] + over;
res[k] = sum % 10;
over = sum / 10;
lemma_function(a,b,k);
}
//
if (over != 0) res[maxsize++] = over;
}
The two TIP scripts are available here. To use them, put them in a directory scripts/typed next to the code (say file.c) and use this command line:
frama-c[-gui] -wp -wp-prover alt-ergo,script -wp-session scripts file.c
You can change the name of the scripts directory if you wish (it must match the argument of -wp-session), but typed and the filenames of the scripts must be as given since WP will use them to detect which proof obligation they are supposed to prove. In GUI mode, you can have a look at the script, but it is probably difficult to understand and explaining each step will not fit in a SO's answer.
Every time I find a pretty good solution to a problem at my work, always start coding in C to ruin that feeling... :D
So here I am, noobing with some easy C code and wonder why it's not working o.O
I want to represent a matrix with a 2D array (array of arrays) and fill it from a text file. The code is bad, the code ugly... I'm interested any tip/trick what I can fetch from you, Mr. senior :)
What wrong with my logic? What is under the hood? Am I using the [] operator not as expected? Am I just simply don't know how to iterate through a 2D array? I complie this source on windows with cl, using declaration in for() and god know what else what is not strictly C-like.
Input is a text file containing the size of the matrix and the elements of it separated by white space(s). The syntax of this: file := {n, A | n :-N, A := N^(n*n)}
For example:
3
1 3 2
4 5 2
7 0 1
So here it is... take cover!
#include <stdio.h>
int main(int argc, char **argv) {
Opening the file, no error checking for the minimal code :)
FILE *fp = fopen("mat_mul.test", "r");
Now, allocating the arrays based on the first integer in the file... Is this correct? Are there any better approach for allocating array of arrays?
int n = fgetc(fp) - '0';
int **A = (int**) malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++)
A[i] = (int*) malloc(sizeof(int) * n);
Aaand, here is the magic, the spell what has turned against its master :D
char act;
int i = 0, j = 0;
while (EOF != (act = fgetc(fp)))
if ('0' <= act && '9' >= act)
A[j == n - 1 ? i++ : i][j == n - 1 ? j = 0 : j++] = act - '0';
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("A[%i][%i]=%i\n", i, j, A[i][j]);
}
}
Cleaning without exhaustive!
if (fclose(fp)) {
return 0;
}
You invoke undefined behaviour when you try to do the row and column assignment and advancement at once here:
A[j == n - 1 ? i++ : i][j == n - 1 ? j = 0 : j++] = act - '0';
You assign to j in the second pair of brackets and also access its value in the first pair. (My compiler warns me that the "operation on 'j' may be undefined".) There is a sequence point between the parts of the ternary operatoy, but not between the two index operators [].
Besides the undefined behaviour, the expression is also needlessly complicated in my opinion. Separate assignmemt and advancing the row and columns counter:
if ('0' <= act && '9' >= act) {
A[i][j] = act - '0';
j++;
if (j == n) {
j = 0;
i++;
if (i == n) break; // end outer while
}
}
You should also include <stdlib.h> for the declaration of malloc. (That's also something my compiler tells me when warnings are enabled.)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
There are n balls each with a particular weight and cost. The balls have to be removed such that the cost of the balls removed is maximum. An additional condition is that the sum of weights of the last k balls should be <= the weight of the the remaining balls multiplied by another constant Q (k is a constant: given). The balls can only be removed from the ends. How can the cost be maximised. I can solve this question using a recursive algorithm. But I would like to know how to reduce the complexity O(n) using queues.
#include<stdio.h>
long int Q, val[100000], wt[100000],k,n;
long int steal(long int l,long int r,long int cut)
{
long int i,sum,steal1, steal2 ,X, Y = 0;
for(i = r; i > r - k; i--)
Y = Y + wt[i];
sum = 0;
for(i = l; i <= r; i++)
sum = sum + wt[i];
X = sum - Y;
if(X * Q < Y)
return 0;
else
{
steal1 = steal(l, r-1, r);
steal2 = steal(l+1, r, l);
if(steal1 == 0 && steal2 != 0)
return steal2 ;
else if(steal1 != 0 && steal2 == 0)
return steal1 ;
else if(steal1 == 0 && steal2 == 0)
{
if(r-l+1 == n)
return 0;
else
return val[cut];
}
else
{
if(steal1+val[r] > steal2+val[l])
return steal1+val[r];
else
return steal2+val[l];
}
}
}
int main()
{
long int i;
scanf("%ld %ld %ld", &n, &k, &Q);
for(i = 0; i < n; i++)
scanf("%ld", &wt[i]);
for(i = 0; i < n; i++)
scanf("%ld", &val[i]);
printf("%ld\n", steal(0, n - 1,n));
return 0;
}
Test Case :
5 2 1 (n, k and q respectively)
5 4 6 3 2 (weights of the n balls)
3 2 4 2 2 (Value of each ball)
Answer : 5
Things to be fixed:
You have some arrays declared with 100000 elements, regardless of the actual value of n, which should be their size instead. If 100000 < n, then the arrays are too small and you will have problems due to index out of bounds. If n < 100000, then you waste a lot of memory. Instead of initializing arrays with 100000 element, initialize them with n elements. Read this for further info.
You could use insertion sort while reading the input, to sort the elements by weight, value, or some formula, so you will be able to differentiate balls by weight, or value, or some formula which suits your needs better.
With recursion you are using the stack. You could use a custom stack for that purpose.
If you want to queue the balls, then the queue can be the one created at 2.
If you want the very best solution, then you will need to implement Divide et Impera for your purpose.
EDIT: Originally I had transcribed i++ not i--
The code now is as it was, and the code in the code block compiles and works.
Why, if unsigned int i; is used instead of int i; in the code snippet below, does using the function result in a segfault?
void insertion_sort_int_array(int * const Ints, unsigned int const len) {
unsigned int pos;
int key;
int i;
for (pos = 1; pos < len; ++pos) {
key = Ints[pos];
for (i = (pos - 1); (i >= 0) && Ints[i] > key; i--) {
Ints[i + 1] = Ints[i];
}
Ints[i + 1] = key;
}
}
THe posted code will fail in either case (possibly with a segfault, possibly only corrupting memory).
The inner loop starts at pos-1 and scans upwards in memory until some random condition is met - it does not check if it has passed the end of the array, so will run merrily on until it crashes or the end condition happens to be met by the (undefined) contents of the memory it is corrupting.
You probably meant to scan downwards in memory (using i-- in the loop), in which case it would fail because the loop will reach 0. Subtracting 1 from 0 gives you a very large positive number in an unsigned, so the loop will never end (i>=0 is always true) and it will access some memory somewhere in the region of Pluto.
insertionSort(array A)
begin
for x := 1 to length[A]-1 do
begin
value := A[x];
i := x - 1;
while i >= 0 and A[i] > value do
begin
A[i + 1] := A[i];
i := i - 1;
end;
A[i + 1] := value;
end;
end;
The only difference between the standard insertion sort algorithm and your code is that you're incrementing i instead of decrementing. That's your problem. I bet that in the code you're actually compiling and running, you have i-- instead of i++ in the inner loop. That's why the unsigned i makes a difference - it cannot be negative, so the inner loop will never end. Did you copy the code wrong when you posted?
EDIT:
Well, now that you changed the posted code, it all makes sense, right? An unsigned i will simply underflow to INT_MAX when you decrement it past 0, which will cause you to access memory outside of the array bounds.
What keeps i+1 within the bounds of your array 'ints'? It looks like badly formed data in your array will cause you to index into areas of memory which you shouldn't be in.
Why, if unsigned int i; is used
instead of int i; in the code snippet
below, does using the function result
in a segfault?
Because for unsigned int i, i >= 0 is always true, so your for loop is unlikely to terminate when you want.
You should always be extremely careful when looping backwards (from high to low) if your counter is unsigned.
i will [wraparound] causing access beyond the array limits.
Importing limits and comparing to UINT_MAX instead of the previous (i >= 0) fixes the issue:
#include <limits.h>
void insertion_sort_int_array(int * const Integers, unsigned int const N)
{
unsigned int o;
int target;
unsigned int i;
for (o = 1; o < N; o++) {
target = Integers[o];
for (i = (o - 1); (i != UINT_MAX) && (Ints[i] > target); i--) {
Integers[i + 1] = Integers[i];
}
Integers[i + 1] = key;
}
}