-1

I am trying to verify the addition of two 2d arrays but I constantly take a timeout error regardless of the solver that I use.

The code that I am trying to verify is the following:

typedef struct{
  float mem[3];
}BaseMatrix3x1;


/*@ requires \valid(b1) && \valid(b2);
  @ ensures A: \forall integer i; 0 <= i < 3 ==>
                b1->mem[i] == \old(b1)->mem[i] + b2->mem[i];
  @ assigns b1->mem[0..2];
@*/
void baseMatrixAssignAdd3x1(BaseMatrix3x1 *b1, BaseMatrix3x1 *b2){
    /*@ loop invariant 0 <= i <= 3;
      loop invariant \forall integer k; 
      0 <= k < i ==>
        \at(b1->mem[k], LoopCurrent) ==
            \at(b1->mem[k], LoopEntry) + \at(b2->mem[k], LoopEntry);
      loop assigns i, b1->mem[0..2];*/ 
    for(unsigned int i=0; i<3; i++){
        b1->mem[i] += b2->mem[i];
  }
}

The second loop invariant is the one that causes all the solvers to timeout.

Do you have any suggestions?

Edit: I fixed the assign error (which was not the problem though).

I don't call this function somewhere yet, I am just trying to prove the loop invariants. From my understanding, in order to verify a function, we do not care about the way that this function will be called. We care only about the Pre and Post conditions that we have.

byako
  • 3,372
  • 2
  • 21
  • 36
Eldrad
  • 97
  • 4
  • 1
    How are you initializing b1 and b2, and how do you call the function? (edit your post showing these please) – ryyker May 05 '16 at 20:14
  • 2
    The text in the comments does not agree with what the code does. Specifically, the comments state that mem[0] through mem[3] are assigned new values, but the code sets mem[0] through mem[2] only. – FredK May 05 '16 at 20:18
  • @EugeneSh - I removed my _comment_ below because I agree that the question is about something other than what OP has posted. There is no content about _static-analysis_, except the tag. (Unless the function show is representing something other than a summing loop.) – ryyker May 05 '16 at 20:25
  • 1
    @ryvker: this question is very much on-topic in the *static-analysis* tag. Not all static analyzers need the entire program to wok. Here, the author is attempting to prove his function at the unit level, using deductive verification. – byako May 06 '16 at 15:15
  • There is no 2D array in your code! – too honest for this site May 12 '16 at 15:07
  • @Olaf I'm puzzled as to why this function should be closed. The MCVE is fine, and the problem is clearly stated: the SMT solvers the OP used are timing out, meaning that the proof fails. – byako May 12 '16 at 22:52
  • @byako: Any specific reason you ask **me**? The CV has more than one closer. Just that: Check times, see the history! If Feel free to OV. – too honest for this site May 13 '16 at 09:06
  • Sorry if my comment was inappropriate, but I can notify only one person and you were the only one with an activity on this question. And unfortunately, I do not have enough reputation to see the CV history – byako May 13 '16 at 11:23

1 Answers1

4

First, what is incorrect/missing in your code:

  • you never mention that b1 and b2 are pointers to different matrices. Your loop assigns are incorrect without this information, because b2->mem[0..2] also gets assigned. You need to add a requires \separated(b1, b2); assumption
  • you postcondition is incorrect, because \old only applies to the pointer b1 (which remains unchanged in the function anyway), while it should apply to b1->mem. You should have written \old(b1->mem[i]) instead.
  • you're missing an important loop invariant, namely that b1->mem[i..2] has not been modified (yet). Since your loop assigns mentions that all of b1->mem may be assigned at every iteration, you need to add an invariant on the unchanged parts.

Next, one apparent limitation of the WP plugin that prevents a full proof:

  • the support for the label LoopCurrent seems insufficient. But, in your loop invariants, LoopCurrent is the default label. So you can always replace \at(P, LoopCurrent) by P.

Here is a fully annotated version of your code that the WP plugin is able to prove, using Alt-Ergo as prover.

/*@
  requires \valid(b1) && \valid(b2);
  requires \separated(b1, b2);
  ensures A: \forall integer i; 0 <= i < 3 ==>
                b1->mem[i] == \old(b1->mem[i]) + b2->mem[i];
  assigns b1->mem[0..2];
@*/
void baseMatrixAssignAdd3x1(BaseMatrix3x1 *b1, BaseMatrix3x1 *b2){
  /*@ loop invariant 0 <= i <= 3;
      loop invariant \forall integer k; 
        k >= i ==> b1->mem[k] == \at(b1->mem[k], Pre);
      loop invariant \forall integer k; 
        0 <= k < i ==> b1->mem[k] == \at(b1->mem[k], LoopEntry) + b2->mem[k];
      loop assigns i, b1->mem[0..2];*/ 
  for(unsigned int i=0; i<3; i++){
    b1->mem[i] += b2->mem[i];
  }
}
byako
  • 3,372
  • 2
  • 21
  • 36