-
Notifications
You must be signed in to change notification settings - Fork 38
Open
Description
Hi!
The example below fails to verify in Silicon, but verifies in Carbon (using the most recent release of the viper vscode plugin).
The places that seem relevant are commented with // FIXME:.
If I switch the order of the last two invariants in the inner loop, then the code gets verified in Silicon as well.
Seems like a potential bug in handling loop invariant?
domain Matrix {
function select(m: Matrix, i: Int, j: Int) : Int
function store(m:Matrix, i: Int, j:Int, value: Int) : Matrix
function size(m:Matrix) : Int // only one size function needed for a square matrix (number of rows and number of columns)
axiom select_store_same {
forall m: Matrix, i: Int, j:Int, v:Int :: {select(store(m,i,j,v),i,j)} inRange(m,i,j) ==> select(store(m,i,j,v),i,j) == v
}
axiom store_preserve_size {
forall m: Matrix, i: Int, j: Int, v: Int :: {store(m,i,j,v)} inRange(m,i,j) ==> size(store(m,i,j,v)) == size(m)
}
axiom select_store_diff {
forall m: Matrix, i1: Int, j1:Int, i2: Int, j2:Int, v : Int :: {select(store(m,i1,j1,v),i2,j2)} {select(m,i2,j2),store(m,i1,j1,v)}
inRange(m,i1,j1) && inRange(m,i2,j2) && (i1 != i2 || j1 != j2) ==> select(store(m,i1,j1,v),i2,j2) == select(m,i2,j2)
}
}
define inRange(m,i,j) 0 <= i && 0 <= j && i < size(m) && j < size(m)
method add(m1: Matrix, m2: Matrix) returns (m3: Matrix)
requires size(m1) == size(m2)
ensures forall x:Int, y:Int :: {select(m3,x,y)} inRange(m1,x,y) ==> select(m3,x,y) == select(m1,x,y) + select(m2,x,y)
{
assume size(m3) == size(m1) // "initialise" m3 to *some* matrix of the right size
var i : Int := 0
var j : Int
while(i < size(m1))
invariant i >= 0
invariant size(m3) == size(m1)
// FIXME: fails to be reestablished (with Silicon)
invariant forall x: Int, y: Int :: {select(m3,x,y)} 0 <= x < i && 0 <= y < size(m1) ==> select(m3,x,y) == select(m1,x,y) + select(m2,x,y)
{
j := 0
while(j < size(m1))
invariant i >= 0
invariant j >= 0
invariant size(m3) == size(m1)
// FIXME: if we switch the order of the two invariants below, the program verifies in both Silicon and Carbon
invariant forall y: Int :: {select(m3,i,y)} 0 <= y < j ==> select(m3,i,y) == select(m1,i,y) + select(m2, i, y)
invariant forall x: Int, y: Int :: {select(m3,x,y)} 0 <= x < i && 0 <= y < size(m3) ==> select(m3,x,y) == select(m1,x,y) + select(m2, x, y)
{
m3 := store(m3,i,j,(select(m1,i,j) + select(m2,i,j)))
// assert select(m3,i,j) == select(m1,i,j) + select(m2,i,j)
j := j + 1
}
i := i + 1
}
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels