(* Instead of proving the existence of a number corresponding to the half of n,
we could be interested in computing it. The best way to do it is to define this
-division operation together with the remainder, that in our case is just a boolean
-value: tt if the input term is even, and ff if the input term is odd. Since we
-must return a pair, we could use a suitably defined record type, or simply a product
-type nat × bool, defined in the basic library. The product type is just a sort of
-general purpose record, with standard fields fst and snd, called projections.
-A pair of values n and m is written (pair … m n) or \langle n,m \rangle -
-visually rendered as 〈n,m〉
+division operation together with the remainder, that in our case is just a
+boolean value: tt if the input term is even, and ff if the input term is odd.
+Since we must return a pair, we could use a suitably defined record type, or
+simply a product type nat × bool, defined in the basic library. The product type
+is just a sort of general purpose record, with standard fields fst and snd, called
+projections.
+A pair of values n and m is written (pair … m n) or \langle n,m \rangle - visually
+rendered as 〈n,m〉
We first write down the function, and then discuss it.*)
(* The function is computed by recursion over the input n. If n is 0, then the
quotient is 0 and the remainder is tt. If n = S a, we start computing the half
of a, say 〈q,b〉. Then we have two cases according to the possible values of b:
-if b is tt, then we must return 〈q,ff〉, while if b = ff then we must return 〈S q,tt〉.
-
-It is important to point out the deep, substantial analogy between the algorithm for
-computing div2 and the the proof of ex_half. In particular ex_half returns a
-proof of the kind ∃n.A(n)∨B(n): the really informative content in it is the witness
-n and a boolean indicating which one between the two conditions A(n) and B(n) is met.
-This is precisely the quotient-remainder pair returned by div2.
-In both cases we proceed by recurrence (respectively, induction or recursion) over the
-input argument n. In case n = 0, we conclude the proof in ex_half by providing the
-witness O and a proof of A(O); this corresponds to returning the pair 〈O,ff〉 in div2.
-Similarly, in the inductive case n = S a, we must exploit the inductive hypothesis
-for a (i.e. the result of the recursive call), distinguishing two subcases according
-to the the two possibilites A(a) or B(a) (i.e. the two possibile values of the remainder
-for a). The reader is strongly invited to check all remaining details.
+if b is tt, then we must return 〈q,ff〉, while if b = ff then we must return
+〈S q,tt〉.
+
+It is important to point out the deep, substantial analogy between the algorithm
+for computing div2 and the the proof of ex_half. In particular ex_half returns a
+proof of the kind ∃n.A(n)∨B(n): the really informative content in it is the
+witness n and a boolean indicating which one between the two conditions A(n) and
+B(n) is met. This is precisely the quotient-remainder pair returned by div2.
+In both cases we proceed by recurrence (respectively, induction or recursion) over
+the input argument n. In case n = 0, we conclude the proof in ex_half by providing
+the witness O and a proof of A(O); this corresponds to returning the pair 〈O,ff〉 in
+div2. Similarly, in the inductive case n = S a, we must exploit the inductive
+hypothesis for a (i.e. the result of the recursive call), distinguishing two subcases
+according to the the two possibilites A(a) or B(a) (i.e. the two possibile values of
+the remainder for a). The reader is strongly invited to check all remaining details.
Let us now prove that our div2 function has the expected behaviour.
*)
|#a #Hind #q #r
cut (\ 5a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"\ 6div2\ 5/a\ 6 a \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a title="Pair construction" href="cic:/fakeuri.def(1)"\ 6〈\ 5/a\ 6\ 5a href="cic:/matita/basics/types/fst.def(1)"\ 6fst\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"\ 6div2\ 5/a\ 6 a), \ 5a href="cic:/matita/basics/types/snd.def(1)"\ 6snd\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"\ 6div2\ 5/a\ 6 a)〉) [//]
cases (\ 5a href="cic:/matita/basics/types/snd.def(1)"\ 6snd\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"\ 6div2\ 5/a\ 6 a))
- [#H >(\ 5a href="cic:/matita/tutorial/chapter2/div2S1.def(3)"\ 6div2S1\ 5/a\ 6 … H) #H1 destruct @\ 5a href="cic:/matita/basics/logic/eq_f.def(3)"\ 6eq_f\ 5/a\ 6 \ 5span style="text-decoration: underline;"\ 6>\ 5/span\ 6\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 <\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 @(Hind … H)
+ [#H >(\ 5a href="cic:/matita/tutorial/chapter2/div2S1.def(3)"\ 6div2S1\ 5/a\ 6 … H) #H1 destruct @\ 5a href="cic:/matita/basics/logic/eq_f.def(3)"\ 6eq_f\ 5/a\ 6 \ 5span style="text-decoration: underline;"\ 6>\ 5/span\ 6\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 whd in ⊢ (???%); <\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 @(Hind … H)
|#H >(\ 5a href="cic:/matita/tutorial/chapter2/div2SO.def(3)"\ 6div2SO\ 5/a\ 6 … H) #H1 destruct >\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 @\ 5a href="cic:/matita/basics/logic/eq_f.def(3)"\ 6eq_f\ 5/a\ 6 @(Hind … H)
]
qed.
|#a * #p #qrspec
cut (p \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a title="Pair construction" href="cic:/fakeuri.def(1)"\ 6〈\ 5/a\ 6\ 5a href="cic:/matita/basics/types/fst.def(1)"\ 6fst\ 5/a\ 6 … p, \ 5a href="cic:/matita/basics/types/snd.def(1)"\ 6snd\ 5/a\ 6 … p〉) [//]
cases (\ 5a href="cic:/matita/basics/types/snd.def(1)"\ 6snd\ 5/a\ 6 … p)
- [#H @(\ 5a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"\ 6mk_Sub\ 5/a\ 6 … \ 5a title="Pair construction" href="cic:/fakeuri.def(1)"\ 6〈\ 5/a\ 6\ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 (\ 5a href="cic:/matita/basics/types/fst.def(1)"\ 6fst\ 5/a\ 6 … p),\ 5a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"\ 6ff\ 5/a\ 6〉) whd #q #r #H1 destruct @\ 5a href="cic:/matita/basics/logic/eq_f.def(3)"\ 6eq_f\ 5/a\ 6 \ 5span style="text-decoration: underline;"\ 6>\ 5/span\ 6\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 <\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 @(qrspec … H)
+ [#H @(\ 5a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"\ 6mk_Sub\ 5/a\ 6 … \ 5a title="Pair construction" href="cic:/fakeuri.def(1)"\ 6〈\ 5/a\ 6\ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 (\ 5a href="cic:/matita/basics/types/fst.def(1)"\ 6fst\ 5/a\ 6 … p),\ 5a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"\ 6ff\ 5/a\ 6〉) whd #q #r #H1 destruct @\ 5a href="cic:/matita/basics/logic/eq_f.def(3)"\ 6eq_f\ 5/a\ 6 \ 5span style="text-decoration: underline;"\ 6>\ 5/span\ 6\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6
+ whd in ⊢ (???%); <\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 @(qrspec … H)
|#H @(\ 5a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"\ 6mk_Sub\ 5/a\ 6 … \ 5a title="Pair construction" href="cic:/fakeuri.def(1)"\ 6〈\ 5/a\ 6\ 5a href="cic:/matita/basics/types/fst.def(1)"\ 6fst\ 5/a\ 6 … p,\ 5a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"\ 6tt\ 5/a\ 6〉) whd #q #r #H1 destruct >\ 5a href="cic:/matita/tutorial/chapter2/add_S.def(2)"\ 6add_S\ 5/a\ 6 @\ 5a href="cic:/matita/basics/logic/eq_f.def(3)"\ 6eq_f\ 5/a\ 6 @(qrspec … H)
]
qed.