Program Correctness: Jorge A. Pérez
Program Correctness: Jorge A. Pérez
Block 5
Jorge A. Pérez
(based on slides by Arnold Meijster)
Linear Search
2 / 30
Linear Search
var k : N;
fP : M = Min fi 2 N j prop (i )g 1g
<
L
fQ : k = M g
3 / 30
Linear Search: Invariant
Notice:
P M = Min fi 2 N j prop (i )g 1 <
M 2 N ^ prop (M ) ^ 8i 2 N(prop (i ) ) M i )
0 We will iterate on k to inspect prop (k ), so we need a while.
1 Choose an invariant J and a guard B such that J ^ :B ) Q.
J :0k M
B : :prop (k )
4 / 30
Linear Search: Invariant
Notice:
P M = Min fi 2 N j prop (i )g 1 <
M 2 N ^ prop (M ) ^ 8i 2 N(prop (i ) ) M i )
0 We will iterate on k to inspect prop (k ), so we need a while.
1 Choose an invariant J and a guard B such that J ^ :B ) Q.
J :0k M
B : :prop (k )
J ^ :B 0 k M ^ prop (k )
fprop (k ) ^ P g
) 0k M ^M k
) Q : k =M
4 / 30
Linear Search: Initialization & Variant
P :M = Min fi 2 N j prop (i )g 1g
<
J :0k M
B : :prop (k )
Q :k = M
fJ ^ B ^ vf = Vg
fJ ^ vf < Vg
6 / 30
Linear Search: Body of the Loop
fJ ^ B ^ vf = Vg
(* definitions J , B and vf *)
f0 k M ^ :prop (k ) ^ M k = Vg
fJ ^ vf < Vg
6 / 30
Linear Search: Body of the Loop
fJ ^ B ^ vf = Vg
(* definitions J , B and vf *)
f0 k M ^ :prop (k ) ^ M k = V g
(* P ) prop (M ); 0 k M ^ prop (M ) ^ :prop (k ) ) k 6= M *)
f0 k < M ^ M k = V g
fJ ^ vf < Vg
6 / 30
Linear Search: Body of the Loop
fJ ^ B ^ vf = Vg
(* definitions J , B and vf *)
f0 k M ^ :prop (k ) ^ M k = V g
(* P ) prop (M ); 0 k M ^ prop (M ) ^ :prop (k ) ) k 6= M *)
f0 k < M ^ M k = V g
(* prepare k := k + 1 *)
f0 k + 1 M ^ M (k + 1) < V g
fJ ^ vf < Vg
6 / 30
Linear Search: Body of the Loop
fJ ^ B ^ vf = Vg
(* definitions J , B and vf *)
f0 k M ^ :prop (k ) ^ M k = V g
(* P ) prop (M ); 0 k M ^ prop (M ) ^ :prop (k ) ) k 6= M *)
f0 k < M ^ M k = V g
(* prepare k := k + 1 *)
f0 k + 1 M ^ M (k + 1) < V g
k := k + 1;
fJ ^ vf < Vg
6 / 30
Linear Search: Body of the Loop
fJ ^ B ^ vf = Vg
(* definitions J , B and vf *)
f0 k M ^ :prop (k ) ^ M k = V g
(* P ) prop (M ); 0 k M ^ prop (M ) ^ :prop (k ) ) k 6= M *)
f0 k < M ^ M k = V g
(* prepare k := k + 1 *)
f0 k + 1 M ^ M (k + 1) < V g
k := k + 1;
f0 k M ^ M k < V g
fJ ^ vf < Vg
6 / 30
Linear Search: Body of the Loop
fJ ^ B ^ vf = Vg
(* definitions J , B and vf *)
f0 k M ^ :prop (k ) ^ M k = V g
(* P ) prop (M ); 0 k M ^ prop (M ) ^ :prop (k ) ) k 6= M *)
f0 k < M ^ M k = V g
(* prepare k := k + 1 *)
f0 k + 1 M ^ M (k + 1) < V g
k := k + 1;
f0 k M ^ M k < V g
(* definitions J , and vf *)
fJ ^ vf < V g
6 / 30
Linear Search: Conclusion
var k : Z;
fP : M = Min fi 2 N j prop (i )g < 1g
k := 0;
fJ : 0 k M g
(* vf = M k *)
while :prop (k ) do
k := k + 1;
end;
fQ : k = M g
7 / 30
Application: Linear Search in an Array
8 / 30
Application: Linear Search in an Array
8 / 30
Application: Linear Search in an Array
var k : Z;
fP : M = Min fi 2 N j n i _ a [i ] = w gg
k := 0;
fJ : 0 k M g
(* vf = M k *)
while k < n ^ a [k ] 6= w do (* short circuit evaluation *)
k := k + 1;
end;
fQ : k = M g
9 / 30
Outline
Linear Search
10 / 30
Up to Here...
We have seen:
I The roadmap for designing repetitions
I Linear search (Ch 8.1)
Coming next:
I Binary search (Ch 8.2)
I The Dutch National Flag problem (Ch 8.4)
I Chapters 10 and 9
11 / 30
Up to Here...
We have seen:
I The roadmap for designing repetitions
I Linear search (Ch 8.1)
Coming next:
I Binary search (Ch 8.2)
I The Dutch National Flag problem (Ch 8.4)
I Chapters 10 and 9
11 / 30
Monotonic functions
12 / 30
Monotonic functions
12 / 30
Monotonic functions
I descending ( / ): if 8i j 2 V : (i j ) f (i ) f (j ))
;
I decreasing ( / ): if 8i j 2 V : (i j ) f (i ) f (j ))
< > ; < >
12 / 30
Monotonic functions
I descending ( / ): if 8i j 2 V : (i j ) f (i ) f (j ))
;
I decreasing ( / ): if 8i j 2 V : (i j ) f (i ) f (j ))
< > ; < >
12 / 30
Binary Search
Consider now an ascending array a, with lenght n.
Given a value w , compute the smallest index k such that a [k ] = w .
If such an index does not exist, the result should be k = n.
13 / 30
Binary Search
Consider now an ascending array a, with lenght n.
Given a value w , compute the smallest index k such that a [k ] = w .
If such an index does not exist, the result should be k = n.
13 / 30
Binary Search
Consider now an ascending array a, with lenght n.
Given a value w , compute the smallest index k such that a [k ] = w .
If such an index does not exist, the result should be k = n.
13 / 30
Binary Search
Consider now an ascending array a, with lenght n.
Given a value w , compute the smallest index k such that a [k ] = w .
If such an index does not exist, the result should be k = n.
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fcalculus; logicg
0 k n ^ (k = n _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fcalculus; logicg
0 k n ^ (k = n _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fcalculus; logicg
0 k n ^ (k = n _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fdefine: a [ 1] = 1 and a [n ] = 1g
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fcalculus; logicg
0 k n ^ (k = n _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fdefine: a [ 1] = 1 and a [n ] = 1g
0 k n ^ w a [k ] ^ a [k 1] w <
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fcalculus; logicg
0 k n ^ (k = n _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fdefine: a [ 1] = 1 and a [n ] = 1g
0 k n ^ w a [k ] ^ a [k 1] w <
frewritingg
Q : 0 k n ^ a [k 1] w a [k ]
<
14 / 30
Massaging the Postcondition
Q : k = Min fi 2 N j n i _ w a [i ]g
fproperties of Min g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N((n i _ w a [i ]) ) k i )
fcontraposition: p ) q :q ) :p g
0 k ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) (i n ^ a [i ] w ))
< < <
0 k n ^ (n k _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fcalculus; logicg
0 k n ^ (k = n _ w a [k ]) ^ 8i 2 N(i k ) a [i ] w )
< <
fdefine: a [ 1] = 1 and a [n ] = 1g
0 k n ^ w a [k ] ^ a [k 1] w <
frewritingg
Q : 0 k n ^ a [k 1] w a [k ]
<
15 / 30
Binary Search: Invariant and Guard
Revising the postcondition, we obtain the following specification:
J :0j k n ^ a [j 1] < w a [k ]
B :j 6= k
Clearly, J ^ :B ) Q.
15 / 30
Binary Search: Initialization & Variant
P : a is ascending; a [ 1] = 1 ^ a [n ] = 1
J :0j k n ^ a [j 1] w a [k ]
<
B :j 6= k
2 Initialization: Because P is pre-regular, we can use true as
precondition. We find a command T0 such that ftrueg T0 fJ g.
ftrueg
(* n 2 N; calculus; use P *)
f0 0 n n ^ a [0 1] w a [n ]g
<
j :=0; k := n ;
fJ : 0 j k n ^ a [j 1] w a [k ]g
<
16 / 30
Binary Search: Body of the Loop
We will be working towards a body of the following form:
fJ ^ B ^ vf = Vg
S0 ;
fJ ^ vf = V ^ j m < kg
if a [m ] < w then
j := m + 1;
else
k := m ;
end
fJ ^ vf < V g
I Clearly, S0 should involve an assignment to m, which is a point
in the interval formed by j and k .
I Both ‘m := j ’ or ‘m := k 1’ are alternatives, but we would like
to reduce by half the search area.
I Hence, we shall consider ‘m := (j + k ) div 2’.
17 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = Vg
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] < w a [k ] ^ j =6 k ^ k j = Vg
if a [m ] < w then
j := m + 1;
else
k := m;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
if a [m ] < w then
j := m + 1;
else
k := m;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k )div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = Vg
if a [m ] < w then
j := m + 1;
else
k := m;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = Vg
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = Vg
j := m + 1;
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = Vg
k := m;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare j := m + 1 *)
f0 m + 1 k n ^ a [m + 1 1] < w a [k ] ^ k (m + 1) < V g
j := m + 1;
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = Vg
k := m;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare j := m + 1 *)
f0 m + 1 k n ^ a [m + 1 1] < w a [k ] ^ k (m + 1) < V g
j := m + 1;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
k := m;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare j := m + 1 *)
f0 m + 1 k n ^ a [m + 1 1] < w a [k ] ^ k (m + 1) < V g
j := m + 1;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare k := m *)
f0 j m n ^ a [j 1] < w a [m ] ^ m j < V g
k := m ;
end
fJ ^ vf < Vg
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j< k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare j := m + 1 *)
f0 m + 1 k n ^ a [m + 1 1] < w a [k ] ^ k (m + 1) < V g
j := m + 1;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare k := m *)
f0 j m n ^ a [j 1] < w a [m ] ^ m j < V g
k := m ;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
end
fJ ^ vf < V g
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j< k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare j := m + 1 *)
f0 m + 1 k n ^ a [m + 1 1] < w a [k ] ^ k (m + 1) < V g
j := m + 1;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare k := m *)
f0 j m n ^ a [j 1] < w a [m ] ^ m j < V g
k := m ;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
end
fJ ^ vf < V g
18 / 30
Binary Search: Body of the Loop
fJ ^ B ^ vf = V g
f0 j k n ^ a [j 1] w a [k ] ^ j 6= k ^ k j = V g
<
(* (j k ^ j< k ) (j + j j + k ^ j + k k + k ) 2 j j + k
< < 2 k *)
f0 j (j + k ) div 2 k n ^ a [j 1] w a [k ] ^ k j = V g
< <
m := (j + k ) div 2;
f0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
if a [m ] < w then
fa [m ] < w ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare j := m + 1 *)
f0 m + 1 k n ^ a [m + 1 1] < w a [k ] ^ k (m + 1) < V g
j := m + 1;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
else
fw a [m ] ^ 0 j m < k n ^ a [j 1] < w a [k ] ^ k j = V g
(* logic; calculus; prepare k := m *)
f0 j m n ^ a [j 1] < w a [m ] ^ m j < V g
k := m ;
f0 j k n ^ a [j 1] < w a [k ] ^ k j < V g
end (* collect branches; definitions J and vf *)
fJ ^ vf < V g
18 / 30
Binary Search: Conclusion
const n : N; w : Z; a : array [0::n ) of R;
var k ; j ; m : N;
fP : a is ascendingg
j := 0; k := n ;
fJ : 0 j k n ^ a [j 1] < w a [k ]g
(* vf = k j *)
while j 6= k do
m := (j + k ) div 2;
if a [m ] < w then
j := m + 1;
else
k := m ;
end;
end;
fk = Min fi 2 N j i < n ) w a [i ]gg
if k < n ^ a [k ] 6= w then
k := n ;
end;
fQ : k = Min fi 2 N j i < n ) w = a [i ]gg
19 / 30
Outline
Linear Search
20 / 30
The Dutch National Flag problem (DNFP)
21 / 30
The Dutch National Flag problem (DNFP)
21 / 30
The Dutch National Flag problem (DNFP)
21 / 30
DNFP: Statement
I An array a of length n, which stores three sorts of elements
(denoted 0, 1, and 2, representing the balls of different colors).
22 / 30
DNFP: Statement
I An array a of length n, which stores three sorts of elements
(denoted 0, 1, and 2, representing the balls of different colors).
I For each index i 2 [0::n ), we have a [i ] = 0 _ a [i ] = 1 _ a [i ] = 2.
22 / 30
DNFP: Statement
I An array a of length n, which stores three sorts of elements
(denoted 0, 1, and 2, representing the balls of different colors).
I For each index i 2 [0::n ), we have a [i ] = 0 _ a [i ] = 1 _ a [i ] = 2.
I We can swap elements, assuming the following specification:
f0 i = I < n ^ 0j =J < n ^ a [i ] = X ^ a [j ] = Y g
swap(i ; j )
fi = I ^ j = J ^ a [i ] = Y ^ a [j ] = X g
22 / 30
DNFP: Statement
I An array a of length n, which stores three sorts of elements
(denoted 0, 1, and 2, representing the balls of different colors).
I For each index i 2 [0::n ), we have a [i ] = 0 _ a [i ] = 1 _ a [i ] = 2.
I We can swap elements, assuming the following specification:
f0 i = I < n ^ 0j =J < n ^ a [i ] = X ^ a [j ] = Y g
swap(i ; j )
fi = I ^ j = J ^ a [i ] = Y ^ a [j ] = X g
I We look for a command that, after termination, ensures that
there are indices r and w such that:
0r w n
^ (8i : 0 i r a [i ] = 0)
< ;
^ (8i : r i w a [i ] = 1)
< ;
^ (8i : w i n a [i ] = 2)
< ;
23 / 30
DNFP: Invariant (1/3)
23 / 30
DNFP: Invariant (2/3)
What is a good invariant for the required an iterative process?
I It is natural to design an invariant that partitions the array into
four segments: red, white, blue, and ‘mixed’ (unsorted).
I There are four alternatives:
24 / 30
DNFP: Invariant (2/3)
What is a good invariant for the required an iterative process?
I It is natural to design an invariant that partitions the array into
four segments: red, white, blue, and ‘mixed’ (unsorted).
I There are four alternatives:
0 n
red white blue unsorted
24 / 30
DNFP: Invariant (2/3)
What is a good invariant for the required an iterative process?
I It is natural to design an invariant that partitions the array into
four segments: red, white, blue, and ‘mixed’ (unsorted).
I There are four alternatives:
0 n
red white blue unsorted
0 n
red white unsorted blue
24 / 30
DNFP: Invariant (2/3)
What is a good invariant for the required an iterative process?
I It is natural to design an invariant that partitions the array into
four segments: red, white, blue, and ‘mixed’ (unsorted).
I There are four alternatives:
0 n
red white blue unsorted
0 n
red white unsorted blue
0 n
red unsorted white blue
24 / 30
DNFP: Invariant (2/3)
What is a good invariant for the required an iterative process?
I It is natural to design an invariant that partitions the array into
four segments: red, white, blue, and ‘mixed’ (unsorted).
I There are four alternatives:
0 n
red white blue unsorted
0 n
red white unsorted blue
0 n
red unsorted white blue
0 n
unsorted red white blue
25 / 30
DNFP: Invariant (3/3)
I The preferable option is to maintain the ‘mixed’ segment in the
interior of the array (why?)
I The invariant modifies the postcondition by introducing a new
index/variable b:
0r w bn
^ (8i : 0 i < r ; a [ i ] = 0)
^ (8i : r i < w ; a [i ] = 1)
^ (8i : b i < n ; a [i ] = 2)
Graphically:
0 r w b n
red white unsorted blue
I With this invariant, the variant function is
The guard of the loop is
25 / 30
DNFP: Invariant (3/3)
I The preferable option is to maintain the ‘mixed’ segment in the
interior of the array (why?)
I The invariant modifies the postcondition by introducing a new
index/variable b:
0r w bn
^ (8i : 0 i < r ; a [ i ] = 0)
^ (8i : r i < w ; a [i ] = 1)
^ (8i : b i < n ; a [i ] = 2)
Graphically:
0 r w b n
red white unsorted blue
I With this invariant, the variant function is vf = b w .
The guard of the loop is
25 / 30
DNFP: Invariant (3/3)
I The preferable option is to maintain the ‘mixed’ segment in the
interior of the array (why?)
I The invariant modifies the postcondition by introducing a new
index/variable b:
0r w bn
^ (8i : 0 i < r ; a [ i ] = 0)
^ (8i : r i < w ; a [i ] = 1)
^ (8i : b i < n ; a [i ] = 2)
Graphically:
0 r w b n
red white unsorted blue
I With this invariant, the variant function is vf = b w .
The guard of the loop is B : w < b.
25 / 30
DNFP: Idea of the Body (1/3)
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
26 / 30
DNFP: Idea of the Body (1/3)
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
w := w +1
26 / 30
DNFP: Idea of the Body (1/3)
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
w := w +1
This yields:
0 0 0 0 0 0 1 1 1 1 ? ? ? 2 2 2 2
26 / 30
DNFP: Idea of the Body (2/3)
In the general case, we have:
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
27 / 30
DNFP: Idea of the Body (2/3)
In the general case, we have:
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
swap(b 1; w );
b := b 1
27 / 30
DNFP: Idea of the Body (2/3)
In the general case, we have:
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
swap(b 1; w );
b := b 1
This yields:
0 0 0 0 0 0 1 1 1 ? ? ? 2 2 2 2 2
27 / 30
DNFP: Idea of the Body (3/3)
In the general case, we have:
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
28 / 30
DNFP: Idea of the Body (3/3)
In the general case, we have:
r w b n
0 0 0 0 0 0 1 1 1 ? ? ? ? 2 2 2 2
swap(r ; w );
r := r + 1; w := w +1
This yields:
0 0 0 0 0 0 0 1 1 1 ? ? ? 2 2 2 2
28 / 30
DNFP: Conclusion
const n : N; a : array [0::n ) of Z;
var r ; w ; b : Z;
fP : (as discussed above)g
r := 0; w := 0; b := n ;
fJ : (as discussed above)g
(* vf = b w *)
while w < b do
if a [w ] = 1 then
w := w + 1;
else
if a [w ] = 2 then
swap(b 1; w );
b := b 1;
else
if a [w ] = 0 then
swap(r ; w );
r := r + 1; w := w + 1;
end;
end;
end
fQ : (as discussed above)g
29 / 30
The End
30 / 30