Commit 10ba6776 by Jean-Christophe Filliâtre

### N-queens: proof in progress

parent bb11c2df
 ... ... @@ -20,7 +20,7 @@ theory BitwiseArithmetic end theory Bits "the bits of an integer, as a set of integers" theory Bits "the 1-bits of an integer, as a set of integers" use export set.Fsetint ... ... @@ -66,14 +66,17 @@ theory Solution use import int.Int use export map.Map (* the number of queens *) function n : int type solution = map int int (* solutions t and u have the same prefix [0..i[ *) predicate eq_prefix (t u: solution) (i: int) = predicate eq_prefix (t u: map int 'a) (i: int) = forall k: int. 0 <= k < i -> t[k] = u[k] predicate eq_sol (t u: solution) = eq_prefix t u n (* s stores a partial solution, for the rows 0..k-1 *) predicate partial_solution (k: int) (s: solution) = forall i: int. 0 <= i < k -> ... ... @@ -104,7 +107,6 @@ module NQueens use import Bits use import module arith.Int use import module ref.Refint use import module array.Array (* warmup 1: termination of the loop *) let rec t1 (a b c : int) = ... ... @@ -140,78 +142,77 @@ module NQueens use import Solution val sol: ref solutions (* all solutions *) val s : ref int (* next slot for a solution *) val col: ref solution (* solution under construction *) val k : ref int (* current row in the current solution *) (**** /*@ requires solution(col) @ assigns s, sol[s][0..N()-1] @ ensures s==\old(s)+1 && eq_sol(sol[\old(s)], col) @*/ void store_solution(); /*@ requires @ 0 <= k && k + card(iset(a)) == N() && 0 <= s && @ pre_a:: (\forall int i; in_(i,iset(a)) <=> @ (0<=i i != col[j])) && @ pre_b:: (\forall int i; i>=0 => (in_(i,iset(b)) <=> @ (\exists int j; 0<=j=0 => (in_(i,iset(c)) <=> @ (\exists int j; 0<=j= 0 && k == \old(k) && @ sorted(sol, \old(s), s) && @ \forall int* t; ((solution(t) && eq_prefix(col,t,k)) <=> @ (\exists int i; \old(s)<=i= 0 && k == \old(k) && @ partial_solution(k, col) && @ sorted(sol, \at(s,L), s) && @ \forall int *t; @ (solution(t) && @ \exists int di; in_(di, diff(\at(iset(e),L), iset(e))) && @ eq_prefix(col,t,k) && t[k]==di) <=> @ (\exists int i; \at(s,L)<=i (\exists int i; 0<=i<\result && eq_sol(t,sol[i])) @*/ int queens(int n) { return t3(~(~0< (0<=i< n /\ forall j: int. 0 <= j < !k -> i <> !col[j])) /\ "pre_b" (forall i: int. i>=0 -> mem i (bits b) <-> (exists j: int. 0 <= j < !k /\ !col[j] = i + j - !k)) /\ "pre_c" (forall i: int. i>=0 -> mem i (bits c) <-> (exists j: int. 0 <= j < !k /\ !col[j] = i + !k - j)) /\ partial_solution !k !col } if a <> 0 then begin let e = ref (a & ~b & ~c) in 'L:let f = ref 0 in while !e <> 0 do invariant { !f = !s - at !s 'L >= 0 /\ !k = at !k 'L /\ subset (bits !e) (at (bits !e) 'L) /\ partial_solution !k !col /\ sorted !sol (at !s 'L) !s /\ (forall t: solution. (solution t /\ exists di: int. mem di (diff (at (bits !e) 'L) (bits !e)) /\ eq_prefix !col t !k /\ t[!k] = di) <-> (exists i: int. (at !s 'L) <= i < !s /\ eq_sol t !sol[i])) /\ (* assigns *) eq_prefix (at !col 'L) !col (at !k 'L) /\ eq_prefix (at !sol 'L) !sol (at !s 'L) } let d = !e & (- !e) in (* assert \exists int x; iset(d) == singleton(x) && in_(x,iset(a)) *) assert { bits d = singleton (min_elt (bits !e)) }; assert { bits (a-d) = remove (min_elt (bits !e)) (bits a) }; (* ghost *) col := !col[!k <- min_elt d]; (* ghost *) incr k; f += t3 (a - d) ((b+d) * 2) ((c+d)/2); (* ghost *) decr k; e -= d done; !f end else begin (* ghost *) store_solution (); 1 end { result = !s - old !s >= 0 /\ !k = old !k /\ sorted !sol (old !s) !s /\ (forall t: solution. ((solution t /\ eq_prefix !col t !k) <-> (exists i: int. old !s <= i < !s /\ eq_sol t !sol[i]))) /\ (* assigns *) eq_prefix (old !col) !col !k /\ eq_prefix (old !sol) !sol (old !s) } let queens3 (q: int) = { 0 <= q = n /\ !s = 0 /\ !k = 0 } t3 (~(~0 << q)) 0 0 { result = !s /\ sorted !sol 0 !s /\ forall t: solution. solution t <-> (exists i: int. 0 <= i < result /\ eq_sol t !sol[i]) } end ... ...
 ... ... @@ -130,6 +130,10 @@ Parameter below: Z -> (set Z). Axiom below_def : forall (x:Z) (n:Z), (mem x (below n)) <-> ((0%Z <= x)%Z /\ (x < n)%Z). Axiom cardinal_below : forall (n:Z), ((0%Z <= n)%Z -> ((cardinal (below n)) = n)) /\ ((~ (0%Z <= n)%Z) -> ((cardinal (below n)) = 0%Z)). Parameter bits: Z -> (set Z). ... ...