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<N() && \forall int j; 0<=j<k => i != col[j])) &&
@ pre_b:: (\forall int i; i>=0 => (in_(i,iset(b)) <=>
@ (\exists int j; 0<=j<k && col[j] == i+j-k))) &&
@ pre_c:: (\forall int i; i>=0 => (in_(i,iset(c)) <=>
@ (\exists int j; 0<=j<k && col[j] == i+k-j))) &&
@ partial_solution(k, col)
@ assigns
@ col[k..], s, k, sol[s..][..]
@ ensures
@ \result == s - \old(s) && \result >= 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<s && eq_sol(t, sol[i])))
@*/
int t3(int a, int b, int c){
int d, e=a&~b&~c, f=1;
//@ label L
if (a)
/*@ invariant
@ included(iset(e),\at(iset(e),L)) &&
@ f == s - \at(s,L) && f >= 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<s && eq_sol(t, sol[i]))
@ loop_assigns
@ col[k..], s, k, sol[s..][..]
@*/
for (f=0; d=e&-e; e-=d) {
//@ assert \exists int x; iset(d) == singleton(x) && in_(x,iset(a))
//@ ghost col[k] = min_elt(d); // ghost code
//@ ghost k++; // ghost code
f += t3(a-d, (b+d)*2, (c+d)/2);
//@ ghost k--; // ghost code
}
//@ ghost else
//@ ghost store_solution(); // ghost code
return f;
}
/*@ requires
@ n == N() && s == 0 && k == 0
@ ensures
@ \result == s &&
@ sorted(sol, 0, s) &&
@ \forall int* t;
@ solution(t) <=> (\exists int i; 0<=i<\result && eq_sol(t,sol[i]))
@*/
int queens(int n) {
return t3(~(~0<<n),0,0);
}
*****)
val sol: ref solutions (* all solutions *)
val s : ref int (* next slot for a solution = number of solutions *)
let store_solution () =
{ solution !col }
sol := !sol[!s <- !col];
incr s
{ !s = old !s + 1 /\
eq_prefix (old !sol) !sol (old !s) /\
!sol[old !s] = !col }
let rec t3 (a b c : int) =
{ 0 <= !k /\ !k + cardinal (bits a) = n /\ 0 <= !s /\
"pre_a" (forall i: int. mem i (bits a) <->
(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).
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -122,6 +122,9 @@ theory Fsetint
axiom below_def: forall x n: int. mem x (below n) <-> 0 <= x < n
lemma cardinal_below:
forall n: int. cardinal (below n) = if n >= 0 then n else 0
end
theory FsetExt
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment