I am trying to prove quantified assertions for arrays and encountered some problems. Consider the following small program:
int a[4] = {1,2,3,4};
/*# requires p == a;
assigns \nothing;
*/
void test(int *p)
{
p++;
//# assert \forall int i; 0 <= i < 3 ==> p[i] < 10;
//# assert \exists int i; p[i] == 3;
}
I am using the 'Typed' memory model:
frama-c-gui -wp -wp-qed -wp-byreference -wp-model 'Typed' -main test Test.c
For some reason the "requires" does not hold and thus all assertions can be proved, even 1==2. In order to overcome this I directly assign the global variable in the function body:
int a[4] = {1,2,3,4};
/*# assigns \nothing;
*/
void test(int *p)
{
p = a;
p++;
//# assert \forall int i; 0 <= i < 3 ==> p[i] < 10;
//# assert \exists int i; p[i] == 3;
}
Here the forall holds but the exists does not. The exists only holds when I add the assertion "p[1] == 3" before it. What is missing to prove such existential array properties? I need this to express a loop invariant for a search loop over array entries.
Thanks, Harald
The "requires" is transformed into false by an incorrect simplification. It will be corrected in the next release. Thank you for spotting the error.
With the fix, the last assertion is still not proved by Alt-ergo because it is not able to find the witness for i using its usual heuristics. When you add the assertion "p[1] == 3" you give the witness, that's why it's easier to prove. Some other provers (Z3, CVC4) will be able to prove this particular assertion directly. Stay tuned for the next release.
Related
Today when I am solving Fibonacci arrays, I meet with a very strange thing. Recursion only takes 16ms, but iteration takes 80ms. I have tried to optimize my iteration (such as I use a vector container to fulfill my stack) but iteration is still much slower than recursion. It doesn't make sense because recursion still builds a stack at OS level, which is more time-consuming than iteration.
Here is my iteration code:
class Solution {
public:
int fib(int n) {
std::stack<int, std::vector<int>> st;
st.push(n);
int result = 0;
int temp = 0;
while(!st.empty()) {
temp = st.top(); st.pop();
if(temp == 1) result++;
else if(temp == 0) continue;
else {
st.push(temp - 1);
st.push(temp - 2);
}
}
return result;
}
};
Here is my recursion code
class Solution {
public:
int fib(int n) {
if(n == 0) return 0;
if(n == 1) return 1;
else return fib(n - 1) + fib(n - 2);
}
};
Well, I have searched for the reason. According to Is recursion ever faster than looping?, recursion is more time-consuming than iteration in an imperative language. But C++ is one of the imperative languages, it is not convincing.
I think I find the reason. You can help me check if there is any incorrect in my analysis?
The reason why recursion is faster than iteration is that if you use an STL container as a stack, it would be allocated in heap space.
When the PC pointer wants to access the stack, cache missing might happen, which is greatly expensive as for a small scale problem.
However, as for the Fibonacci solution, the code length is not very long. So the PC pointer can easily jump to the function's beginning. If you use a static int array, the result is satisfying.
Here is the code:
class Solution {
public:
int fib(int n) {
int arr[1000];
arr[0] = n;
int s = 1;
int result = 0;
int temp;
while (s) {
temp = arr[s-1];
s--;
switch (temp) {
case 1:
result++;
break;
case 0:
continue;
break;
default:
arr[s++] = temp - 1;
arr[s++] = temp - 2;
}
}
return result;
}
};
I was trying to implement pwd command in xv6 system. But i am getting a error in sysfile.c execution. The function is as follows showing the error:-
int sys_getcwd(void) {
char *p;
int n;
if(argint(1, &n) < 0 || argptr(0, &p, n) < 0)
return -1;
return name_for_inode(p, n, proc->cwd);
}
I get error as follows:
error: ‘proc’ undeclared (first use in this function)
return name_for_inode(p, n, proc->cwd);
But I also included proc.h in this file.
proc is not defined, and warning, it's a struct name.
You have to query the current process, you can do it with myproc() function
int sys_getcwd(void) {
char *p;
int n;
struct proc *curproc = myproc();
if(argint(1, &n) < 0 || argptr(0, &p, n) < 0)
return -1;
return name_for_inode(p, n, curproc->cwd);
}
Yes proc is not global variable so initialize it with current process on which cpu is working.
struct proc *proc = myproc();
return name_for_inode(p, n, proc->cwd);
I can't think of any idea to get foo's assigns clause to be proved. I tried assigns var; since foo() indirectly modifies the global var variable, but it doesn't work. Is there a way to get an assigns clause for the local p variable or the location return from a()? Here is the code:
int var;
//# assigns \nothing;
int *a(){
return &var;
}
//# assigns *p;
void b(int* p){
*p = 1;
}
//# assigns \nothing;
void foo(){
int *p = a();
b(p);
}
//# assigns var;
void main(){
var = 0;
foo();
return;
}
frama-c command:
frama-c -wp test.c
[kernel] Parsing test.c (with preprocessing)
[wp] Warning: Missing RTE guards
[wp] 10 goals scheduled
[wp] [Alt-Ergo] Goal typed_foo_assign_normal_part3 : Unknown (103ms)
[wp] [Alt-Ergo] Goal typed_foo_assign_exit_part3 : Unknown (Qed:4ms) (102ms)
[wp] Proved goals: 8 / 10
Qed: 8
Alt-Ergo: 0 (unknown: 2)
As you guessed, foo does assign something, and assigns \nothing is an invalid clause for this function. The proper clause is indeed assigns var. Within an assigns clause, you must list all global variables that are modified, plus all the variables that are local to a caller and that can be reference through a formal.
Now, why does the proof of the variants with assigns var not go through? Well, as written, in foo, WP cannot guess where p points to, as it has no way of knowing that it is actually equal to &a. You must add this information to the specification of function a. With this modification, the proof is immediate.
Full code:
int var;
/*# assigns \nothing;
ensures \result == &var; */
int *a(){
return &var;
}
//# assigns *p;
void b(int* p){
*p = 1;
}
//# assigns var;
void foo(){
int *p = a();
b(p);
}
//# assigns var;
void main(){
var = 0;
foo();
return;
}
Is there a way to use Frama-C's slicing plugin to compute slices for a specific C assert statement?
For example, given the following code:
int main() {
double a=3;
double b=4;
double c=123;
assert(b>=0);
double d=a/b;
c=a;
return 0;
}
I would like to get the following slice for assert(b>=0);:
int main() {
double b=4;
assert(b>=0);
return 0;
}
If you can rewrite your assert as an ACSL assertion, you can use option -slice-assert main.
int main() {
double a=3;
double b=4;
double c=123;
//# assert(b>=0);
double d=a/b;
c=a;
return 0;
}
(In this case, the division will also be removed, as it does not influence the assertion.)
void main(void)
{
double b;
b = (double)4;
/*# assert b ≥ 0; */ ;
return;
}
Alternatively, you can also slice on the calls to the assert function, using -slice-calls assert.
void main(void)
{
double b;
b = (double)4;
assert(b >= (double)0);
return;
}
If you want to slice on a particular assertion (if there are more than one in the function), you will have to use a slicing pragma, or the programmatic API (not recommended).
I have written a simple program that does autocorrelation as follows...I've used pgi accelerator directives to move the computation to GPUs.
//autocorrelation
void autocorr(float *restrict A, float *restrict C, int N)
{
int i, j;
float sum;
#pragma acc region
{
for (i = 0; i < N; i++) {
sum = 0.0;
for (j = 0; j < N; j++) {
if ((i+j) < N)
sum += A[j] * A[i+j];
else
continue;
}
C[i] = sum;
}
}
}
I wrote a similar program in OpenCL, but I am not getting correct results. The program is as follows...I am new to GPU programming, so apart from hints that could fix my error, any other advices are welcome.
__kernel void autocorrel1D(__global double *Vol_IN, __global double *Vol_AUTOCORR, int size)
{
int j, gid = get_global_id(0);
double sum = 0.0;
for (j = 0; j < size; j++) {
if ((gid+j) < size)
{
sum += Vol_IN[j] * Vol_IN[gid+j];
}
else
continue;
}
barrier(CLK_GLOBAL_MEM_FENCE);
Vol_AUTOCORR[gid] = sum;
}
Since I have passed the dimension to be 1, so I am considering my get_global_size(0) call would give me the id of the current block, which is used to access the input 1d array.
Thanks,
Sayan
The code is correct. As far as I know, that should run fine and give corret results.
barrier(CLK_GLOBAL_MEM_FENCE); is not needed. You'll get more speed without that sentence.
Your problem should be outside the kernel, check that you a re passing correctly the input, and you are taking out of GPU the correct data.
BTW, I supose you are using a double precision suported GPU as you are doing double calcs.
Check that you are passing also double values. Remember you CAN't point a float pointer to a double value, and viceversa. That will give you wrong results.