1\chapter{Esempio: il Teorema di Euclide}
2\label{chap:euclid}
3
4\setcounter{sessioncount}{0}
5
6In questo capitolo, dimostriamo in \holn{} che per ogni numero, c'� un
7numero primo che � pi� grande, cio�, che i numeri primi formano una
8sequenza infinita. Questa dimostrazione � stata estratta e adattata da un
9pi� ampio esempio, dovuto a John Harrison, in cui egli dimostrava il caso
10$n = 4$ dell'ultimo teorema di Fermat. Lo sviluppo della dimostrazione ha lo scopo
11di servire come un'introduzione all'esecuzione di dimostrazioni interattive di alto livello
12in \holn\footnote{Le dimostrazioni discusse di sotto si possono trovare in
13\texttt{examples/euclid.sml} della distribuzione \HOL{}.}.
14Molti dei dettagli possono essere difficili da cogliere per il lettore alle prime armi;
15ciononostante, si raccomanda di seguire l'esempio in modo completo
16al fine di ottenere una vera sensazione dell'uso di \HOL{} per dimostrare teoremi non-banali.
17
18Alcuni tutorial sulla descrizione di sistemi di dimostrazione, mostrano il sistema mentre esegue
19incredibili gesta di dimostrazione automatica di teoremi. In questo esempio, \textit{non}
20abbiamo seguito questo approccio; piuttosto, cerchiamo di mostrare come si affronta
21nella realt� il problema di dimostrare teoremi in \holn{}: quando
22� possibile pi� di un modo per dimostrare qualcosa, considereremo
23le scelte; quando sorge una difficolt�, tenteremo di spiegare come affrontare
24il problema in modo chiaro.
25
26Si `guida' \holn{} interagendo con il loop interattivo ML. In questo
27stile interattivo, si eseguono chiamate a funzioni ML per richiamare
28un contesto logico gi� stabilito, ad esempio, attraverso \ml{load}; per definire
29nuovi concetti, ad esempio, attraverso \ml{Hol\_datatype},  \ml{Define}, e \ml{Hol\_reln};
30e per eseguire dimostrazioni usando l'interfaccia goalstack, e
31gli strumenti di dimostrazione da \ml{bossLib} (o se essi falliscono, dalle
32librerie di basso livello).
33
34Cominciamo. Per prima cosa, avviamo il sistema, con il comando \ml{<holdir>/bin/hol}.
35Quindi con ``\ml{open}'' apriamo la teoria aritmetica; questo significa che tutti i binding \ML{}
36dalla teoria \HOL{} sono resi disponibili al loop interattivo.
37\begin{session}
38\begin{verbatim}
39- open arithmeticTheory;
40  ...
41\end{verbatim}
42\end{session}
43Ora iniziamo la formalizzazione. Al fine di definire il concetto di
44numero primo, abbiamo prima bisogno di definire la relazione di \emph{divisibilit�}:
45
46\begin{session}
47\begin{verbatim}
48- val divides_def = Define `divides a b = ?x. b = a * x`;
49
50Definition has been stored under "divides_def".
51> val divides_def = |- !a b. divides a b = ?x. b = a * x : thm
52\end{verbatim}
53\end{session}
54
55La definizione � aggiunta alla teoria corrente con il nome
56\ml{divides\_def}, ed � anche restituita dall'invocazione di
57\ml{Define}. Approfittiamo di questo ed effettuiamo un binding del nome
58\ML{} \ml{divides\_def} alla definizione. Nel modo usuale di
59interagire con \HOL, un tale binding \ML{} � fatto per ogni
60definizione e teorema (utile) dimostrato: l'ambiente \ML{} viene
61cos� usato come un luogo conveniente per mantenere definizioni e teoremi per
62un futuro riferimento nella sessione.
63
64Vogliamo trattare \ml{divides} come un infisso (non-associativo):
65\begin{session}
66\begin{verbatim}
67- set_fixity "divides" (Infix(NONASSOC, 450));
68\end{verbatim}
69\end{session}
70Poi definiamo la propriet� di essere un numero \emph{primo}: un numero $p$ �
71primo se e solo se non � uguale a $1$ e non ha altri divisori oltre
72$1$ e s� stesso:
73
74\begin{session}
75\begin{verbatim}
76- val prime_def =
77    Define `prime p = ~(p=1) /\ !x. x divides p ==> (x=1) \/ (x=p)`;
78
79Definition has been stored under "prime_def".
80> val prime_def =
81    |- !p. prime p = ~(p = 1) /\ !x. x divides p ==> (x = 1) \/ (x = p)
82    : thm
83\end{verbatim}
84\end{session}
85
86Questo conclude le definizioni da fare. Ora dobbiamo ``solo'' dimostrare
87che ci sono infiniti numeri primi. Se fossimo arrivati ad affrontare questo
88problema senza un background, allora saremmo costretti a passare per un processo
89non completamente chiaro e spesso tremendamente difficile di ricerca dei giusti lemmi
90richiesti per dimostrare il nostro teorema desiderato\footnote{Questo naturalmente � un
91problema generale quando si affronta qualsiasi tipo di dimostrazione.}. Fortunatamente, stiamo
92lavorando a partire da un dimostrazione gi� completata e possiamo dedicarci al problema
93decisamente pi� semplice di spiegare come dimostrare i teoremi richiesti.
94
95\paragraph{Strumenti di dimostrazione}
96Lo sviluppo illustrer� che c'� spesso pi� di un modo di
97affrontare una dimostrazione HOL, persino quando si ha in mente un'unica dimostrazione
98(informale). In questo esempio, spesso \emph{troviamo} dimostrazioni usando
99la tattica di riscrittura \ml{RW\_TAC} per espandere le definizioni ed eseguire semplificazioni
100di base, riducendo spesso un goal alla sua essenza.
101\begin{session}
102\begin{verbatim}
103RW_TAC;
104val it = fn :simpset -> thm list -> term list * term ->
105             (term list * term) list * (thm list -> thm)
106\end{verbatim}
107\end{session}
108Il tipo ML di \ml{RW\_TAC} �
109\ml{:simpset -> thm list -> tactic}\footnote{Sfortunatamente, il sistema MoscowML non stampa
110il tipo delle tattiche nella sua forma abbreviata.}.
111Quando \ml{RW\_TAC} � applicata a un \textit{simpset}---per questo esempio sar�
112sempre \ml{arith\_ss}---e a una lista di teoremi, i
113teoremi saranno aggiunti al simpset come regole di riscrittura aggiuntive.
114Vedremo che \ml{arith\_ss} � anche informato in qualche modo circa
115l'aritmetica\footnote{Specialmente l'aritmetica lineare: formule puramente
116universali, che coinvolgono gli operatori {\tt SUC}, $+$, $-$, letterali
117numerici, $<$, $\leq$, $>$, $\geq$, $=$, e la moltiplicazione per letterali
118numerici}.
119A volte la semplificazione con \ml{RW\_TAC} dimostra il goal immediatamente.
120Spesso comunque, ci rimane un goal che richiede un p� di studio prima di
121realizzare quali lemmi sono necessari per concludere la dimostrazione. Una volta che questi lemmi
122sono stati dimostrati, o individuati nelle teorie progenitrici,
123\ml{METIS\_TAC}\footnote{\ml{METIS\_TAC}
124esegue una ricerca della dimostrazione al primo ordine nello stile della risoluzione.} pu�
125essere invocata con essi, con la speranza che essa individuer� le istanziazioni
126corrette necessarie per concludere la dimostrazione. Si noti che queste due operazioni,
127la semplificazione e la ricerca automatica di una dimostrazione nello stile della risoluzione, non saranno sufficienti per
128eseguire tutte le dimostrazioni in questo esempio: in particolare, il nostro sviluppo, avr�
129anche bisogno dell'analisi dei casi e dell'induzione.
130
131\paragraph{Trovare i teoremi}
132Questo fa sorgere la seguente domanda: come si trovano i giusti lemmi e
133le regole di riscrittura da usare? Questo � piuttosto problematico, specialmente dal momento che il numero di
134teorie progenitrici, e di teoremi al loro interno, � grande. Ci sono molte
135possibilit�.
136\begin{itemize}
137\item Si pu� usare il sistema di help per cercare definizioni e
138teoremi, cos� come procedure di dimostrazione; per esempio, un'invocazione di
139{\small
140\begin{verbatim}
141   help "arithmeticTheory"
142\end{verbatim}}
143mostrer� tutte le definizioni e i teoremi che sono stati archiviati nella
144teoria dell'aritmetica. Comunque, bisogna conoscere il nome completo dell'elemento
145che si sta cercando prima che il sistema di help sia utile, cos� i due
146seguenti strumenti di ricerca sono spesso pi� utili.
147\item \verb+DB.match+ permette l'uso di pattern per individuare il
148teorema cercato. Sar� restituito qualunque teorema archiviato che ha un'istanza del pattern
149come un sotto termine.
150\item \verb+DB.find+ user� frammenti dei nomi come chiavi con cui
151cercare l'informazione
152\end{itemize}
153
154\paragraph{Composizione di tattiche}
155Una volta che � stata trovata una dimostrazione di una proposizione, � d'abitudine, bench�
156non necessario, avviare un processo di \emph{revisione}, in cui la
157sequenza di tattiche originaria � composta in un'unica tattica. A volte,
158la tattica risultante � molto pi� breve, e in un certo senso pi� gradevole
159da un punto di vista estetico. Alcuni utenti spendono un bel p� di tempo per raffinare queste tattiche,
160nonostante non sembri esserci un reale maggior beneficio nel fare questo, dal momento che esse
161sono ricette di dimostrazione \emph{ad hoc}, una per ciascun teorema. Nel
162seguito, mostreremo in pochi casi come questo viene fatto.
163
164\section{Divisibilit�}
165
166Iniziamo dimostrando un numero di teoremi circa la relazione
167\verb+divides+. Vedremo che ciascuno di questi teoremi iniziali pu� essere
168dimostrato con una singola invocazione di \ml{METIS\_TAC}. Sia \ml{RW\_TAC}
169sia \ml{METIS\_TAC} sono ragionatori piuttosto potenti, e la scelta di un
170ragionatore in una situazione particolare � una questione di esperienza. La
171ragione principale per cui \ml{METIS\_TAC} funziona cos� bene � che \verb+divides+
172� definita per mezzo di un quantificatore esistenziale, e \ml{METIS\_TAC}
173� piuttosto buono per istanziare in modo automatico gli esistenziali nel
174corso di una dimostrazione. Per un semplice esempio, si consideri la dimostrazione di $\forall x.\
175x\; \mathtt{divides}\; 0$. Si inserisce una nuova proposizione da dimostrare
176attraverso ``\ml{g}'', che avvia un nuovo goalstack.
177
178\begin{session}
179\begin{verbatim}
180- g `!x. x divides 0`;
181
182> val it =
183    Proof manager status: 1 proof.
184    1. Incomplete:
185         Initial goal:
186         !x. x divides 0
187
188     : proofs
189\end{verbatim}
190\end{session}
191Il manager di dimostrazione ci dice che c'� soltanto una dimostrazione da gestire, e
192ripete il goal dato. Ora espandiamo la definizione di
193\verb+divides+. Si noti che ha luogo un'$\alpha$-conversione al fine di
194mantenere distinta la $x$ del goal e la $x$ nella definizione di
195\ml{divides}:
196\begin{session}
197\begin{verbatim}
198- e (RW_TAC arith_ss [divides_def]);
199
200OK..
2011 subgoal:
202> val it =
203    ?x'. (x = 0) \/ (x' = 0)
204\end{verbatim}
205\end{session}
206E' naturalmente piuttosto facile istanziare il quantificatore esistenziale a
207mano.
208\begin{session}
209\begin{verbatim}
210- e (EXISTS_TAC ``0``);
211
212OK..
2131 subgoal:
214> val it =
215    (x = 0) \/ (0 = 0)
216\end{verbatim}
217\end{session}
218Poi un passo di semplificazione conclude la dimostrazione.
219\begin{session}
220\begin{verbatim}
221- e (RW_TAC arith_ss []);
222OK..
223
224Goal proved.
225|- (x = 0) \/ (0 = 0)
226
227Goal proved.
228|- ?x'. (x = 0) \/ (x' = 0)
229> val it =
230    Initial goal proved.
231    |- !x. x divides 0
232\end{verbatim}
233\end{session}
234
235Cosa � appena successo qui? L'applicazione di \ml{RW\_TAC} al goal
236lo ha decomposto in una lista vuota di subgoal; in altre parole, il goal � stato
237dimostrato da \ml{RW\_TAC}. Una volta che il goal � stato dimostrato, � tirato fuori
238dal goalstack, stampato a video, e il teorema diventa
239disponibile per l'uso al livello dello stack. Quando tutti i subgoal
240richiesti da \textit{quel} livello sono stati dimostrati, anche il goal corrispondente a
241quel livello pu� essere dimostrato. Questo processo di `svolgimento' continua fino a quando
242lo stack � vuoto, o fino a quando raggiunge un goal con pi� di un subgoal
243non dimostrato rimanente. Questo processo pu� essere difficile da
244visualizzare,\footnote{Forse per il fatto che abbiamo usato uno stack per implementare quello
245che teoricamente � un albero!} ma ci� non importa, dal momento che il goalstack � stato
246scritto espressamente per permettere all'utente d'ignorare tali dettagli.
247
248Se le tre interazioni sono combinate insieme con \ml{THEN} per
249formare una singola tattica, possiamo provare la dimostrazione
250dall'inizio (usando la funzione \ml{restart}) e questa volta richieder�
251soltanto un unico passo:
252\begin{session}
253\begin{verbatim}
254- restart();
255>   ...
256
257- e (RW_TAC arith_ss [divides_def] THEN EXISTS_TAC ``0``
258     THEN RW_TAC arith_ss []);
259OK..
260
261> val it =
262    Initial goal proved.
263    |- !x. x divides 0
264\end{verbatim}
265\end{session}
266Abbiamo visto un modo di dimostrare il teorema. Comunque, come menzionato
267in precedenza, c'� un altro modo: si potrebbe lasciare che \ml{METIS\_TAC} espanda la
268definizione di \ml{divides} e trovi l'istanziazione richiesta per
269\verb+x'+ dal teorema \ml{MULT\_CLAUSES}\footnote{Potreste
270  voler provare a digitare \ml{MULT\_CLAUSES} nel loop interativo
271	per vedere esattamente cosa esso afferma.}.
272\begin{session}
273\begin{verbatim}
274- restart();
275>   ...
276
277- e (METIS_TAC [divides_def, MULT_CLAUSES]);
278OK..
279metis: r[+0+10]+0+0+0+1+2#
280> val it =
281    Initial goal proved.
282    |- !x. x divides 0
283\end{verbatim}
284\end{session}
285Mentre lavora, \ml{METIS\_TAC} stampa a video alcune diagnostiche
286possibilmente interessanti. In ogni caso, avendo eseguito la nostra dimostrazione all'interno del pacchetto goalstack,
287    ora vogliamo avere accesso al valore del teorema che abbiamo
288		dimostrato. Per far questo usiamo la funzione \ml{top\_thm}, e quindi
289		usiamo \ml{drop} per svuotare lo stack:
290\begin{session}
291\begin{verbatim}
292- val DIVIDES_0 = top_thm();
293
294> val DIVIDES_0 = |- !x. x divides 0 : thm
295
296- drop();
297OK..
298> val it = There are currently no proofs. : proofs
299\end{verbatim}
300\end{session}
301
302Abbiamo usato \ml{METIS\_TAC} in questo modo per dimostrare la seguente
303collezione di teoremi circa \ml{divides}. Come menzionato in precedenza, i
304teoremi forniti a \ml{METIS\_TAC} nelle seguenti dimostrazioni (di solito) non
305provengono dal nulla: in molti casi � stato fatto un qualche lavoro esplorativo
306con \ml{RW\_TAC} per espandere le definizioni e vedere quali lemmi sarebbero
307stati richiesti da \ml{METIS\_TAC}.
308
309\begin{description}
310\label{euclid:extra-proofs}
311\item [\small{({\it DIVIDES\_0\/})}]
312\begin{tabular}[t]{l}
313\verb+!x. x divides 0+ \\ \hline
314 \verb+METIS_TAC [divides_def, MULT_CLAUSES]+
315\end{tabular}
316
317\item[\small{({\it DIVIDES\_ZERO\/})}]
318\begin{tabular}[t]{l}
319\verb+!x. 0 divides x = (x = 0)+ \\ \hline
320 \verb+METIS_TAC [divides_def, MULT_CLAUSES]+
321\end{tabular}
322
323\item[\small{({\it DIVIDES\_ONE\/})}]
324\begin{tabular}[t]{l}
325\verb+!x. x divides 1 = (x = 1)+ \\ \hline
326 \verb+METIS_TAC [divides_def, MULT_CLAUSES, MULT_EQ_1]+
327\end{tabular}
328
329\item[\small{({\it DIVIDES\_REFL\/})}]
330\begin{tabular}[t]{l}
331\verb+!x. x divides x+ \\ \hline
332 \verb+METIS_TAC [divides_def, MULT_CLAUSES]+ \\
333\end{tabular}
334
335\item[\small{({\it DIVIDES\_TRANS\/})}]
336\begin{tabular}[t]{l}
337\verb+!a b c. a divides b /\ b divides c ==> a divides c+ \\ \hline
338 \verb+METIS_TAC [divides_def, MULT_ASSOC]+ \\
339\end{tabular}
340\item[\small{({\it DIVIDES\_ADD\/})}]
341\begin{tabular}[t]{l}
342\verb|!d a b. d divides a /\ d divides b ==> d divides (a+b)| \\ \hline
343 \verb|METIS_TAC [divides_def,LEFT_ADD_DISTRIB]|
344\end{tabular}
345
346\item[\small{({\it DIVIDES\_SUB\/})}]
347\begin{tabular}[t]{l}
348\verb+!d a b. d divides a /\ d divides b ==> d divides (a-b)+ \\ \hline
349 \verb+METIS_TAC [divides_def, LEFT_SUB_DISTRIB]+ \\
350\end{tabular}
351
352\item[\small{({\it DIVIDES\_ADDL\/})}]
353\begin{tabular}[t]{l}
354\verb|!d a b. d divides a /\ d divides (a+b) ==> d divides b| \\ \hline
355 \verb+METIS_TAC [ADD_SUB, ADD_SYM, DIVIDES_SUB]+ \\
356\end{tabular}
357
358\item[\small{({\it DIVIDES\_LMUL\/})}]
359\begin{tabular}[t]{l}
360\verb+!d a x. d divides a ==> d divides (x * a)+ \\ \hline
361 \verb+METIS_TAC [divides_def, MULT_ASSOC, MULT_SYM]+ \\
362\end{tabular}
363
364\item[\small{({\it DIVIDES\_RMUL\/})}]
365\begin{tabular}[t]{l}
366\verb+!d a x. d divides a ==> d divides (a * x)+ \\ \hline
367 \verb+METIS_TAC [MULT_SYM, DIVIDES_LMUL]+ \\
368\end{tabular}
369
370\end{description}
371
372\noindent Assumeremo che le dimostrazioni di sopra siano state eseguite, e
373che gli appropriati nomi ML siano stati dati a tutti i teoremi.
374Ora affrontiamo un lemma circa la divisibilit� che non soccombe a una
375singola invocazione di \ml{METIS\_TAC}:
376\begin{description}
377\item [\small{({\it DIVIDES\_LE\/})}]
378\begin{tabular}[t]{l}
379\verb+!m n. m divides n ==> m <= n \/ (n = 0)+ \\ \hline
380\verb+RW_TAC arith_ss [divides_def]+ \\
381\verb+   THEN Cases_on `x`+ \\
382\verb+   THEN RW_TAC arith_ss [MULT_CLAUSES]+ \\
383\end{tabular}
384\end{description}
385Vediamo come questo � dimostrato. Il modo pi� semplice � di iniziare a semplificare
386con la definizione di \ml{divides}:
387\begin{session}
388\begin{verbatim}
389- g `!m n . m divides n ==> m <= n \/ (n = 0)`;
390>   ...
391
392- e (RW_TAC arith_ss [divides_def]);
393
3941 subgoal:
395> val it =
396    m <= m * x \/ (m * x = 0)
397\end{verbatim}
398\end{session}
399
400Considerando il goal, di base abbiamo tre possibilit�: (1) trovare una
401collezione di lemmi che insieme implicano il goal e usare
402\ml{METIS\_TAC}; (2) fare un case split su $m$; oppure (3) fare un case split su
403$x$. La prima non sembra semplice, dal momento che il goal in realt�
404non calza nella `forma' di un qualsiasi teorema pre-dimostrato di cui l'autore sia a
405conoscenza. Bench� l'opzione (2) sar� rigettata alla fine, proviamola
406comunque. Per eseguire il case split, usiamo \verb+Cases_on+, che sta
407per ``trova il termine dato nel goal ed esegui un'analisi dei casi sulle
408possibilit� di costruzione previste dal costruttore del suo datatype'' [corrisponde al pattern matching di ML (ndt)]. Dal momento che
409l'occorrenza di $m$ nel goal ha il tipo $num$, i casi considerati saranno
410se $m$ � $0$ o un successore.
411\begin{session}
412\begin{verbatim}
413- e (Cases_on `m`);
414OK..
4152 subgoals:
416> val it =
417    SUC n <= SUC n * x \/ (SUC n * x = 0)
418
419    0 <= 0 * x \/ (0 * x = 0)
420\end{verbatim}
421\end{session}
422\noindent Il primo subgoal (l'ultimo stampato) � banale:
423
424\begin{session}
425\begin{verbatim}
426- e (RW_TAC arith_ss []);
427OK..
428
429Goal proved.
430  ...
431
432Remaining subgoals:
433> val it =
434    SUC n <= SUC n * x \/ (SUC n * x = 0)
435\end{verbatim}
436\end{session}
437\noindent Proviamo \ml{RW\_TAC} di nuovo:
438\begin{session}
439\begin{verbatim}
440- e (RW_TAC arith_ss []);
441OK..
4421 subgoal:
443> val it =
444    SUC n <= x * SUC n \/ (x = 0)
445\end{verbatim}
446\end{session}
447Il disgiunto a destra � stato semplificato; comunque, il disgiunto a sinistra ha
448fallito di espandere la definizione della moltiplicazione nell'espressione
449$\mathtt{SUC}\ n * x$, cosa che sarebbe stata conveniente. Di fatto l'ha cambiata
450in $x * \mathtt{SUC}\ n$, che non � conveniente.
451Perch�, visto che si suppone che \verb+arith_ss+ e di conseguenza \ml{RW\_TAC} siano esperte
452nell'aritmetica? La risposta � duplice: primo, le clausole ricorsive per l'addizione e la
453moltiplicazione non sono in \verb+arith_ss+ perch� una loro applicazione senza controllo
454da parte del sistema di riscrittura sembra che, in generale, renda alcune
455dimostrazioni \emph{pi�} complicate, piuttosto che pi� semplici; in secondo luogo, il semplificatore
456riorganizzer� i termini aritmetici per rendere pi� semplici alcune dimostrazioni automatiche. Cos�
457l'assenza delle clausole ricorsive per la moltiplicazione
458significa che $\mathtt{SUC}\ n * x$ non si espande a $(n * x) + x$;
459piuttosto, la riorganizzazione porta a $x * \mathtt{SUC}\; n$. OK, aggiungiamo
460la definizione della moltiplicazione. Questo rivela un nuovo problema: come
461individuare questa definizione. La funzione
462\begin{holboxed}
463\begin{verbatim}
464   DB.match : string list -> term
465                -> ((string * string) * (thm * class)) list
466\end{verbatim}
467\end{holboxed}
468
469\noindent
470� spesso utile a questo scopo. Essa prende una lista di nomi di teorie, e
471un pattern, e cerca nella lista delle teorie un teorema,
472una definizione, o un assioma che ha un'istanza del pattern come sotto termine.
473Se la lista dei nomi di teorie � vuota, allora sono incluse nella ricerca
474tutte le teorie caricate. Cerchiamo nella teoria dell'aritmetica il
475sotto termine che deve essere riscritto.
476
477\begin{session}
478\begin{verbatim}
479- DB.match ["arithmetic"] ``SUC n * x``;
480
481> val it =
482   [(("arithmetic", "FACT"),
483     (|- (FACT 0 = 1) /\ !n. FACT (SUC n) = SUC n * FACT n, Def)),
484    (("arithmetic", "LESS_MULT_MONO"),
485     (|- !m i n. SUC n * m < SUC n * i = m < i, Thm)),
486    (("arithmetic", "MULT"),
487     (|- (!n. 0 * n = 0) /\ !m n. SUC m * n = m * n + n, Def)),
488    (("arithmetic", "MULT_CLAUSES"),
489     (|- !m n.
490           (0 * m = 0) /\ (m * 0 = 0) /\ (1 * m = m) /\ (m * 1 = m) /\
491           (SUC m * n = m * n + n) /\ (m * SUC n = m + m * n), Thm)),
492    (("arithmetic", "MULT_LESS_EQ_SUC"),
493     (|- !m n p. m <= n = SUC p * m <= SUC p * n, Thm)),
494    (("arithmetic", "MULT_MONO_EQ"),
495     (|- !m i n. (SUC n * m = SUC n * i) = m = i, Thm)),
496    (("arithmetic", "ODD_OR_EVEN"),
497     (|- !n. ?m. (n = SUC (SUC 0) * m) \/ (n = SUC (SUC 0) * m + 1), Thm))]
498   : ...
499\end{verbatim}
500\end{session}
501
502Per alcuni, questo restituisce un p� troppa informazione; comunque, possiamo
503focalizzare la ricerca stabilendo che il pattern appaia come una regola
504di riscrittura:
505
506\begin{session}
507\begin{verbatim}
508- DB.match [] ``SUC n * x = M``;
509
510> val it =
511    [(("arithmetic", "MULT"),
512      (|- (!n. 0 * n = 0) /\ !m n. SUC m * n = m * n + n, Def)),
513     (("arithmetic", "MULT_CLAUSES"),
514      (|- !m n.
515            (0 * m = 0) /\ (m * 0 = 0) /\ (1 * m = m) /\ (m * 1 = m) /\
516            (SUC m * n = m * n + n) /\ (m * SUC n = m + m * n), Thm)),
517     (("arithmetic", "MULT_MONO_EQ"),
518      (|- !m i n. (SUC n * m = SUC n * i) = m = i, Thm))] : ...
519\end{verbatim}
520\end{session}
521
522Sia {\small\verb+arithmeticTheory.MULT+} sia
523{\small\verb+arithmeticTheory.MULT_CLAUSES+} sarebbero accettabili;
524scegliamo l'ultima.
525
526\begin{session}
527\begin{verbatim}
528- b();
529  ...
530
531e (RW_TAC arith_ss [MULT_CLAUSES]);
532
533OK..
5341 subgoal:
535> val it =
536    SUC n <= x + n * x \/ (x = 0)
537\end{verbatim}
538\end{session}
539Ora vediamo che, al fine di fare progressi nella dimostrazione, dovremo fare
540un case split su $x$ comunque, e che avremmo dovuto fare lo split su di esso
541fin dall'inizio. Di conseguenza facciamo un backup. Dovremo fare un backup (undo) tre volte.
542\begin{session}
543\begin{verbatim}
544- b();
545> val it =
546    SUC n <= SUC n * x \/ (SUC n * x = 0)
547
548- b();
549> val it =
550    SUC n <= SUC n * x \/ (SUC n * x = 0)
551
552
553    0 <= 0 * x \/ (0 * x = 0)
554
555- b();
556> val it =
557    m <= m * x \/ (m * x = 0)
558\end{verbatim}
559\end{session}
560
561Ora possiamo andare avanti e fare un'analisi dei casi su $x$. Eseguiremo anche\linebreak
562l'invocazione a una tattica composta, dal momento che sappiamo gi� che dovremo
563invocare \ml{RW\_TAC} in entrambi i rami dell'analisi dei casi. Questo pu� essere
564fatto usando \ml{THEN}. Quando $t_1 \ \mbox{\ml{THEN}}\ t_2$ � applicato
565a un goal $g$, prima $t_1$ � applicato a $g$, dando una lista di nuovi
566subgoal, poi $t_2$ � applicato ad ogni membro della lista. Tutti i goal
567risultanti da queste applicazioni di $t_2$ sono raccolti insieme e
568restituiti.
569\begin{session}
570\begin{verbatim}
571- e (Cases_on `x` THEN RW_TAC arith_ss [MULT_CLAUSES]);
572OK..
573
574Goal proved.
575|- m <= m * x \/ (m * x = 0)
576> val it =
577    Initial goal proved.
578    |- !m n. m divides n ==> m <= n \/ (n = 0)
579\end{verbatim}
580\end{session}
581Questo � stato facile! Ovviamente fare un case split su $x$ era la scelta
582giusta. Il processo di {\it trovare\/} la dimostrazione ora � terminato, e
583tutto ci� che rimane da fare � impacchettare la dimostrazione in una singola
584tattica come abbiamo visto di sopra. Al posto di usare \ml{top\_thm} e il goalstack,
585possiamo bypassarlo e usare la funzione \ml{store\_thm}. Questa funzione
586prende una stringa, un termine e una tattica e applica la tattica al termine
587per ottenere un teorema, e quindi archivia il teorema nella teoria corrente
588sotto il nome dato.
589\begin{session}
590\begin{verbatim}
591- val DIVIDES_LE = store_thm (
592     "DIVIDES_LE",
593     ``!m n. m divides n ==> m <= n \/ (n = 0)``,
594     RW_TAC arith_ss  [divides_def]
595       THEN Cases_on `x`
596       THEN RW_TAC arith_ss  [MULT_CLAUSES]);
597
598> val DIVIDES_LE = |- !m n. m divides n ==> m <= n \/ (n = 0) : thm
599\end{verbatim}
600\end{session}
601Archiviare i teoremi nel nostro script di salvataggio della sessione in questo stile
602(piuttosto che con il goalstack) risulta in uno script pi� conciso, e
603rende anche pi� facile trasformare il nostro script in un file di teoria, come facciamo
604nella sessione~\ref{sec:script-to-theory}.
605
606\subsection{Divisibilit� e fattoriale}
607
608Il prossimo lemma, {\small{\it DIVIDES\_FACT\/}}, dice che ogni numero
609maggiore di $0$ e $\leq n$ divide il fattoriale di
610$n$. Il fattoriale si trova in \verb+arithmeticTheory.FACT+ ed � stato
611definito per ricorsione primitiva:
612\begin{description}
613\item [\small{({\it FACT\/})}]
614\begin{minipage}[t]{0.5\textwidth}
615\begin{verbatim}
616  (FACT 0 = 1) /\
617  (!n. FACT (SUC n) = SUC n * FACT n)
618\end{verbatim}
619\end{minipage}
620\end{description}
621Una dimostrazione lucidata di {\small{\it DIVIDES\_FACT\/}} � la
622seguente\footnote{Questa e le successive dimostrazioni usano i teoremi dimostrati
623  alla pagina~\pageref{euclid:extra-proofs}, che sono state aggiunte all'ambiente \ML{}
624	dopo essere state dimostrate.}:
625\begin{description}
626\item [\small{({\it DIVIDES\_FACT\/})}]
627\begin{tabular}[t]{l}
628\verb+!m n. 0 < m /\ m <= n ==> m divides (FACT n)+ \\ \hline
629\verb+RW_TAC arith_ss [LESS_EQ_EXISTS]+ \\
630\verb+ THEN Induct_on `p`+ \\
631\verb+ THEN RW_TAC arith_ss [FACT,ADD_CLAUSES]+ \\
632\verb+ THENL [Cases_on `m`, ALL_TAC]+ \\
633\verb+ THEN METIS_TAC [FACT, DECIDE ``!x. ~(x < x)``,+ \\
634\verb+                 DIVIDES_RMUL, DIVIDES_LMUL, DIVIDES_REFL]+ \\
635\end{tabular}
636\end{description}
637Esamineremo questa dimostrazione nel dettaglio, cos� dovremmo prima tentare di
638comprendere perch� il teorema � vero. Qual � l'intuizione sottostante?
639Supponiamo che $0 < m \leq n$, e cos� $\mbox{\tt FACT}\ n = 1 * \cdots * m *
640\cdots * n$. Mostrare che $m\ \mbox{\tt divides}\ (\mbox{\tt FACT}\ n)$
641significa esibire un $q$ tale che $q * m = \mbox{\tt FACT}\ n$. Cos� $q
642= \mbox{\tt FACT}\ n \div m$. Se dovessimo intraprendere questo approccio alla
643dimostrazione, finiremmo per dover trovare e applicare dei lemmi circa $\div$.
644Questo sembra portarci un p� fuori strada; non c'� una dimostrazione
645che non usa la divisione? Ebbene s�, possiamo dimostrare il teorema per
646induzione su $n - m$: nel caso migliore, dovremo dimostrare $n\;
647\mbox{\tt divides}\ (\mbox{\tt FACT}\; n)$, che dovrebbe essere facile; nel
648caso induttivo, l'ipotesi d'induzione sembrerebbe doverci dare
649ci� di cui abbiamo bisogno. Questa strategia per il caso induttivo � un p� vaga,
650perch� stiamo provando a figurarci mentalmente una formula piuttosto
651complicata, ma possiamo contare sul fatto che il sistema calcoli in modo accurato il
652i casi d'induzione per noi. Se il caso induttivo si riveler� non essere
653ci� che ci aspettavamo, dovremo ripensare il nostro approccio.
654\begin{session}
655\begin{verbatim}
656- g `!m n. 0 < m /\ m <= n ==> m divides (FACT n)`;
657
658> val it =
659    Proof manager status: 1 proof.
660    1. Incomplete:
661         Initial goal:
662         !m n. 0 < m /\ m <= n ==> m divides FACT n
663\end{verbatim}
664\end{session}
665Al posto di eseguire un'induzione direttamente su $n-m$, faremo un'induzione su una variabile
666testimone, ottenuta usando il teorema \verb+LESS_EQ_EXISTS+.
667\begin{session}
668\begin{verbatim}
669- LESS_EQ_EXISTS;
670> val it = |- !m n. m <= n = (?p. n = m + p) : thm
671
672- e (RW_TAC arith_ss [LESS_EQ_EXISTS]);
673OK..
6741 subgoal:
675> val it =
676    m divides FACT (m + p)
677    ------------------------------------
678       0 < m
679\end{verbatim}
680\end{session}
681\noindent Ora eseguiamo un'induzione su $p$:
682\begin{session}
683\begin{verbatim}
684- e (Induct_on `p`);
685OK..
6862 subgoals:
687> val it =
688    m divides FACT (m + SUC p)
689    ------------------------------------
690      0.  0 < m
691      1.  m divides FACT (m + p)
692
693    m divides FACT (m + 0)
694   ------------------------------------
695      0 < m
696\end{verbatim}
697\end{session}
698\noindent Il primo goal pu� ovviamente essere semplificato:
699\begin{session}
700\begin{verbatim}
701- e (RW_TAC arith_ss []);
702OK..
7031 subgoal:
704> val it =
705    m divides FACT m
706    ------------------------------------
707      0 < m
708\end{verbatim}
709\end{session}
710\noindent Ora possiamo fare un'analisi dei casi su $m$: se � $0$, abbiamo un
711goal banale; se � un successore, allora possiamo usare la definizione di
712\ml{FACT} e i teoremi \ml{DIVIDES\_RMUL} e
713\ml{DIVIDES\_REFL}.
714\begin{session}
715\begin{verbatim}
716- e (Cases_on `m`);
717OK..
7182 subgoals:
719> val it =
720    SUC n divides FACT (SUC n)
721    ------------------------------------
722      0 < SUC n
723
724    0 divides FACT 0
725    ------------------------------------
726      0 < 0
727\end{verbatim}
728\end{session}
729
730 Qui il primo subgoal ha un'assunzione che � falsa, Possiamo
731 dimostrare questo al sistema usando la funzione
732\ml{DECIDE} per dimostrare un semplice fatto dell'aritmetica (cio�, che nessun
733numero $x$ � minore di s� stesso), e quindi passare il teorema
734risultante a \ml{METIS\_TAC}, che pu� combinare questo con l'assunzione
735contraddittoria\footnote{Si noti come il sistema interattivo
736	stampi il teorema dimostrato con \ml{[.]} prima del
737	turnstile. Questa notazione indica che un teorema ha un'assunzione
738(in questo caso l'asserzione falsa $0<0$).}.
739
740\begin{session}
741\begin{verbatim}
742- e (METIS_TAC [DECIDE ``!x. ~(x < x)``]);
743OK..
744metis: r[+0+4]#
745
746Goal proved.
747 [.] |- 0 divides FACT 0
748
749Remaining subgoals:
750> val it =
751    SUC n divides FACT (SUC n)
752    ------------------------------------
753      0 < SUC n
754\end{verbatim}
755\end{session}
756Usando i teoremi identificati di sopra, il subgoal rimanente pu�
757essere dimostrato con \ml{RW\_TAC}.
758
759\begin{session}
760\begin{verbatim}
761- e (RW_TAC arith_ss [FACT, DIVIDES_LMUL, DIVIDES_REFL]);
762OK..
763
764Goal proved.   ...
765
766Remaining subgoals:
767> val it =
768    m divides FACT (m + SUC p)
769    ------------------------------------
770      0.  0 < m
771      1.  m divides FACT (m + p)
772\end{verbatim}
773\end{session}
774Quest'ultimo passo, cio� l'invocazione di \ml{RW\_TAC},
775potrebbe essere ottenuta anche con \ml{METIS\_TAC}. Si noti che
776l'unica differenza � l'uso di \ml{DIVIDES\_LMUL} nel semplificatore
777\emph{al posto di} \ml{DIVIDES\_RMUL} in \ml{METIS\_TAC}. Questo � dovuto al
778gi� menzionato riarrangiamento algebrico dei termini aritmetici nel semplificatore.
779\begin{session}
780\begin{verbatim}
781- b();
782> ...
783
784- e (METIS_TAC [FACT, DIVIDES_RMUL, DIVIDES_REFL]);
785OK..
786
787Goal proved.  ...
788\end{verbatim}
789\end{session}
790Ora abbiamo completato il caso base dell'induzione e possiamo spostarci al
791caso di passo. Una cosa ovvia da provare � la semplificazione con le
792definizioni dell'addizione e del fattoriale:
793\begin{session}
794\begin{verbatim}
795- e (RW_TAC arith_ss [FACT, ADD_CLAUSES]);
796
797OK..
7981 subgoal:
799> val it =
800    m divides FACT (m + p) * SUC (m + p)
801    ------------------------------------
802      0.  0 < m
803      1.  m divides FACT (m + p)
804\end{verbatim}
805\end{session}
806\noindent E ora, per mezzo di \ml{DIVIDES\_RMUL} e l'ipotesi d'induzione, abbiamo
807finito:
808\begin{session}
809\begin{verbatim}
810- e (METIS_TAC [DIVIDES_RMUL]);
811OK..
812metis: r[+0+5]+0+0+0+0+1#
813
814Goal proved.
815  ...
816> val it =
817    Initial goal proved.
818    |- !m n. 0 < m /\ m <= n ==> m divides FACT n
819\end{verbatim}
820\end{session}
821Abbiamo concluso la ricerca della dimostrazione, e possiamo spostarci al compito di
822creare una singola tattica a partire dalla sequenza delle invocazioni delle tattiche che abbiamo
823appena fatto. Assumiamo che sia stata tenuta traccia della sequenza delle invocazioni
824in un file o nel buffer di un editor di testo. Avremmo dunque qualcosa
825di simile a ci� che segue:
826\begin{hol}
827\begin{verbatim}
828    e (RW_TAC arith_ss [LESS_EQ_EXISTS]);
829    e (Induct_on `p`);
830    (*1*)
831    e (RW_TAC arith_ss  []);
832    e (Cases_on `m`);
833    (*1.1*)
834    e (METIS_TAC [DECIDE ``!x. ~(x < x)``]);
835    (*1.2*)
836    e (RW_TAC arith_ss [FACT, DIVIDES_LMUL, DIVIDES_REFL]);
837    (*2*)
838    e (RW_TAC arith_ss [FACT, ADD_CLAUSES]);
839    e (METIS_TAC [DIVIDES_RMUL]);
840\end{verbatim}
841\end{hol}
842\noindent
843
844Abbiamo aggiunto uno schema di numerazione per tenere traccia dei rami nella
845dimostrazione. Possiamo cucire insieme l'espressioni di sopra nella seguente tattica
846composta:
847
848\begin{hol}
849\begin{verbatim}
850    RW_TAC arith_ss [LESS_EQ_EXISTS]
851     THEN Induct_on `p`
852     THENL [RW_TAC arith_ss [] THEN Cases_on `m`
853            THENL [METIS_TAC [DECIDE ``!x. ~(x < x)``],
854                   RW_TAC arith_ss [FACT, DIVIDES_LMUL, DIVIDES_REFL]],
855            RW_TAC arith_ss [FACT, ADD_CLAUSES] THEN METIS_TAC [DIVIDES_RMUL]]
856\end{verbatim}
857\end{hol}
858
859\noindent Questo pu� essere testato per vedere che non abbiamo fatto errori:
860
861\begin{session}
862\begin{verbatim}
863- restart();
864> ...
865
866- e (RW_TAC arith_ss [LESS_EQ_EXISTS]
867       THEN Induct_on `p` THENL
868       [RW_TAC arith_ss [] THEN Cases_on `m` THENL
869          [METIS_TAC [DECIDE ``!x. ~(x < x)``],
870           RW_TAC arith_ss [FACT, DIVIDES_LMUL, DIVIDES_REFL]],
871        RW_TAC arith_ss [FACT, ADD_CLAUSES] THEN METIS_TAC [DIVIDES_RMUL]]);
872OK..
873metis: r[+0+5]+0+0+0+0+1#
874metis: r[+0+4]#
875> val it =
876    Initial goal proved.
877    |- !m n. 0 < m /\ m <= n ==> m divides FACT n
878\end{verbatim}
879\end{session}
880
881Per molti utenti, questa sarebbe la conclusione di questa dimostrazione: la
882tattica ora pu� essere impacchettata in un'invocazione di
883\ml{prove}\footnote{La funzione \ml{prove} prende un termine e una tattica
884e tenta di dimostrare il termine usando la tattica fornita. Essa
885restituisce il teorema dimostrato se la tattica ha successo. Essa non salva
886il teorema alla teoria sviluppata.} o di \ml{store\_thm} e quella
887sarebbe la conclusione. Comunque, un altro utente potrebbe notare
888che questa tattica potrebbe essere abbreviata.
889
890Per iniziare, entrambi i rami dell'induzione iniziano con un'invocazione di
891\ml{RW\_TAC}, e la semantica di \ml{THEN} ci permette di fondere le
892occorrenze di \ml{RW\_TAC} prima di \ml{THENL}. La tattica rimaneggiata
893894\begin{hol}
895\begin{verbatim}
896 RW_TAC arith_ss [LESS_EQ_EXISTS]
897   THEN Induct_on `p`
898   THEN RW_TAC arith_ss [FACT, ADD_CLAUSES]
899   THENL [Cases_on `m` THENL
900            [METIS_TAC [DECIDE ``!x. ~(x < x)``],
901             RW_TAC arith_ss [FACT, DIVIDES_LMUL, DIVIDES_REFL]],
902          METIS_TAC [DIVIDES_RMUL]]
903\end{verbatim}
904\end{hol}
905(Naturalmente, quando una tattica � stata rivisitata, dovrebbe essere testata per vedere
906se continua a dimostrare il goal!) Ora si ricordi che l'uso di \ml{RW\_TAC}
907nel caso base potrebbe essere sostituito da una chiamata a \ml{METIS\_TAC}. Cos�
908sembra possibile fondere i due sotto casi del caso base in un'unica
909invocazione di \ml{METIS\_TAC}:
910
911\begin{hol}
912\begin{verbatim}
913 RW_TAC arith_ss [LESS_EQ_EXISTS]
914   THEN Induct_on `p`
915   THEN RW_TAC arith_ss [FACT, ADD_CLAUSES]
916   THENL [Cases_on `m` THEN
917            METIS_TAC[DECIDE ``!x. ~(x<x)``,FACT,DIVIDES_RMUL,DIVIDES_REFL],
918          METIS_TAC [DIVIDES_RMUL]]
919\end{verbatim}
920\end{hol}
921
922\noindent
923In fine, spingendo questo revisionismo quasi al suo limite, ci
924piacerebbe che ci fosse un'unica invocazione di \ml{METIS\_TAC} per concludere
925la dimostrazione. La semantica di \ml{THEN} e di \ml{ALL\_TAC} vengono
926in nostro aiuto: divideremo la costruzione di $m$ nel caso base,
927come nell'incarnazione attuale della tattica, ma lasceremo il
928caso induttivo di passo inalterato attraverso \ml{THENL}. Questo si ottiene
929usando \verb+ALL_TAC+, questa � una tattica che agisce come una funzione
930d'identit� sul goal.
931\begin{hol}
932\begin{verbatim}
933   RW_TAC arith_ss [LESS_EQ_EXISTS]
934     THEN Induct_on `p`
935     THEN RW_TAC arith_ss [FACT, ADD_CLAUSES]
936     THENL [Cases_on `m`, ALL_TAC]
937     THEN METIS_TAC [DECIDE ``!x. ~(x < x)``,
938                     FACT, DIVIDES_RMUL, DIVIDES_REFL]
939\end{verbatim}
940\end{hol}
941
942\noindent
943Il risultato � che ci saranno tre subgoal risultanti da
944\ml{THENL}: i due sotto casi nel caso base e il caso di passo
945inalterato. Ciascuno � dimostrato con una chiamata a \ml{METIS\_TAC}. Abbiamo finito ora?
946Non necessariamente. Per esempio, il case split esplicito, cio� \ml{Cases\_on `m`},
947pu� essere sostituito fornendo il teorema dei \emph{casi} per i numeri naturali
948(\ml{num\_CASES}) a \ml{METIS\_TAC}. Con questo, il case split su $m$, sar�
949generato automaticamente da \ml{METIS\_TAC} durante la ricerca della dimostrazione. Di conseguenza
950possiamo abbreviare la tattica di nuovo.
951\begin{session}
952\begin{verbatim}
953- num_CASES;
954> val it = |- !m. (m = 0) \/ ?n. m = SUC n : thm
955
956- restart();
957- e (RW_TAC arith_ss [LESS_EQ_EXISTS]
958     THEN Induct_on `p`
959     THEN METIS_TAC [DECIDE ``!x. ~(x < x)``, FACT, num_CASES,
960                     DIVIDES_RMUL, DIVIDES_LMUL, DIVIDES_REFL, ADD_CLAUSES]);
961\end{verbatim}
962\end{session}
963Ora abbiamo concluso il nostro esercizio di revisione delle tattiche. Certamente,
964sarebbe difficile indovinare che questa tattica finale dimostrerebbe il
965goal; i lemmi richiesti per l'invocazione finale di \ml{METIS\_TAC}
966sono stati trovati attraverso un processo incrementale di revisione.
967
968\subsection{Divisibilit� e fattoriale (di nuovo!)}
969
970Nella precedente dimostrazione, abbiamo fatto un passo di semplificazione iniziale al fine
971di esporre una variabile su cui indurre. Comunque, la dimostrazione in realt�
972� su $n - m$. Possiamo esprimere questo in modo diretto? La
973risposta � un s� con riserva: l'induzione pu� essere dichiarata in modo naturale, ma
974porta a dei goal in qualche modo meno naturali.
975\begin{session}
976\begin{verbatim}
977- restart();
978
979- e (Induct_on `n - m`);
980
981OK..
9822 subgoals:
983> val it =
984    !n m. (SUC v = n - m) ==> 0 < m /\ m <= n ==> m divides FACT n
985    ------------------------------------
986      !n m. (v = n - m) ==> 0 < m /\ m <= n ==> m divides FACT n
987
988    !n m. (0 = n - m) ==> 0 < m /\ m <= n ==> m divides FACT n
989\end{verbatim}
990\end{session}
991    Questo � leggermente complicato da leggere, cos� usiamo \ml{STRIP\_TAC} e
992    \ml{REPEAT} per spostare gli antecedenti dei goal nelle
993		assunzioni. L'uso di \ml{THEN} assicura che la tatticca venga applicata
994		in entrambi i rami dell'induzione.
995\begin{session}
996\begin{verbatim}
997- b();
998  ...
999
1000- e (Induct_on `n - m` THEN REPEAT STRIP_TAC);
1001
1002OK..
10032 subgoals:
1004> val it =
1005    m divides FACT n
1006    ------------------------------------
1007      0.  !n m. (v = n - m) ==> 0 < m /\ m <= n ==> m divides FACT n
1008      1.  SUC v = n - m
1009      2.  0 < m
1010      3.  m <= n
1011
1012    m divides FACT n
1013    ------------------------------------
1014      0.  0 = n - m
1015      1.  0 < m
1016      2.  m <= n
1017\end{verbatim}
1018\end{session}
1019Osservando il primo goal, ragioniamo che se $0 = n - m$ e $m
1020\leq n$, allora $m = n$. Possiamo dimostrare questo fatto, usando \ml{DECIDE\_TAC}\footnote
1021{\ml{DECIDE\_TAC} � una procedura di decisione per un'utile classe di formule aritmetiche.}
1022e aggiungerla alle ipotesi per mezzo dell'uso dell'operatore infisso ``\ml{by}'':
1023\begin{session}
1024\begin{verbatim}
1025- e (`m = n` by DECIDE_TAC);
1026OK..
10271 subgoal:
1028> val it =
1029    m divides FACT n
1030    ------------------------------------
1031      0.  0 = n - m
1032      1.  0 < m
1033      2.  m <= n
1034      3.  m = n
1035\end{verbatim}
1036\end{session}
1037
1038\noindent Ora possiamo usare \ml{RW\_TAC} per propagare  l'uguaglianza appena derivata
1039attraverso il goal.
1040\begin{session}
1041\begin{verbatim}
1042- e (RW_TAC arith_ss []);
1043
1044OK..
10451 subgoal:
1046> val it =
1047    m divides FACT m
1048    ------------------------------------
1049      0.  0 = m - m
1050      1.  0 < m
1051      2.  m <= m
1052\end{verbatim}
1053\end{session}
1054    A questo punto nella dimostrazione precedente abbiamo fatto un'analisi dei casi su $m$.
1055		Comunque, abbiamo gi� l'ipotesi che $m$ � positivo
1056		(insieme alle altre due ipotesi al momento inutili). Cos� sappiamo che
1057		$m$ � il successore di qualche numero $k$. Potremmo desiderare di affermare
1058		questo fatto con un'invocazione di ``\ml{by}'' nel modo seguente:
1059\[
1060    \mbox{\ml{`?k. m = SUC k` by <tactic>}}
1061\]
1062Ma qual � la tattica? Se proviamo \ml{DECIDE\_TAC}, essa fallir� dal momento che
1063non gestisce enunciati esistenziali. Anche un'applicazione di
1064\ml{RW\_TAC} si dimostrer� insoddisfacente. Cosa fare?
1065
1066Quando capita una situazione di questo tipo, � spesso meglio iniziare una nuova dimostrazione per il
1067lemma richiesto. Questo si pu� fare semplicemente invocando ``\ml{g}''
1068di nuovo. Un nuovo goalstack sar� creato e aggiunto a quello
1069corrente\footnote{Questa aggiunta di tentativi di dimostrazione (goalstack) � differente
1070  dall'aggiunta di goal e giustificazioni all'interno di un particolare
1071	goalstack.} e sar� stampata una panoramica dei tentativi di dimostrazione
1072esistenti:
1073\begin{session}
1074\begin{verbatim}
1075- g `!m. 0 < m ==> ?k. m = SUC k`;
1076
1077> val it =
1078    Proof manager status: 2 proofs.
1079    2. Incomplete:
1080         Initial goal:
1081         !m n. 0 < m /\ m <= n ==> m divides FACT n
1082
1083
1084         Current goal:
1085         m divides FACT m
1086         ------------------------------------
1087           0.  0 = m - m
1088           1.  0 < m
1089           2.  m <= m
1090
1091    1. Incomplete:
1092         Initial goal:
1093         !m. 0 < m ==> ?k. m = SUC k
1094\end{verbatim}
1095\end{session}
1096    Il nostro nuovo goal pu� essere dimostrato abbastanza velocemente. Una volta che lo abbiamo dimostrato,
1097		possiamo legarlo a un nome ML e usarlo nella dimostrazione precedente, 	per
1098		mezzo di una specie di gioco di prestigio con la funzione ``\ml{before}''\footnote{Una
1099		  versione infissa del combinatore {\tt K}, definito da {\tt fun (x before
1100        y) = x}.}
1101\begin{session}
1102\begin{verbatim}
1103- e (Cases THEN RW_TAC arith_ss []);
1104
1105OK..
1106> val it =
1107    Initial goal proved.
1108    |- !m. 0 < m ==> ?k. m = SUC k
1109
1110- val lem = top_thm() before drop();
1111
1112OK..
1113> val lem = |- !m. 0 < m ==> ?k. m = SUC k : thm
1114\end{verbatim}
1115\end{session}
1116
1117Ora possiamo ritornare al filo principale della dimostrazione. Lo stato del
1118subgoal corrente della dimostrazione pu� essere mostrato usando la funzione
1119``\ml{p}''.
1120
1121\begin{session}
1122\begin{verbatim}
1123- p ();
1124
1125> val it =
1126    m divides FACT m
1127    ------------------------------------
1128      0.  0 = m - m
1129      1.  0 < m
1130      2.  m <= m
1131\end{verbatim}
1132\end{session}
1133    Ora possiamo usare \ml{lem} nella dimostrazione. Un p� opportunisticamente,
1134		vireremo sull'invocazione usata nella precedente dimostrazione (pi� o meno)
1135		allo stesso punto, sperando che questo risolva il goal:
1136\begin{session}
1137\begin{verbatim}
1138- e (`?k. m = SUC k` by
1139     METIS_TAC[lem] THEN RW_TAC arith_ss [FACT, DIVIDES_LMUL, DIVIDES_REFL]);
1140OK..
1141metis: r[+0+6]+0+0+0+0+0+1#
1142
1143Goal proved.   ...
1144
1145Remaining subgoals:
1146> val it =
1147    m divides FACT n
1148    ------------------------------------
1149      0.  !n m. (v = n - m) ==> 0 < m /\ m <= n ==> m divides FACT n
1150      1.  SUC v = n - m
1151      2.  0 < m
1152      3.  m <= n
1153\end{verbatim}
1154\end{session}
1155    Funziona! Questo si occupa del caso base, Per il passo d'induzione,
1156		le cose sembrano un p� pi� complicate che nella dimostrazione precedente.
1157		Comunque, possiamo fare progressi realizzando che l'ipotesi
1158		implica che $0 < n$ e cos�, di nuovo per mezzo di \ml{lem}, possiamo trasformare $n$
1159		in un successore, abilitando di conseguenza l'espansione di \ml{FACT}, come nella
1160		dimostrazione precedente:
1161\begin{session}
1162\begin{verbatim}
1163- e (`0 < n` by DECIDE_TAC THEN `?k. n = SUC k` by METIS_TAC [lem]);
1164OK..
1165metis: r[+0+8]+0+0+0+0+0+0+2#
11661 subgoal:
1167> val it =
1168    m divides FACT n
1169    ------------------------------------
1170      0.  !n m. (v = n - m) ==> 0 < m /\ m <= n ==> m divides FACT n
1171      1.  SUC v = n - m
1172      2.  0 < m
1173      3.  m <= n
1174      4.  0 < n
1175      5.  n = SUC k
1176\end{verbatim}
1177\end{session}
1178\noindent La dimostrazione ora si conclude nello stesso modo di quella precedente:
1179\begin{session}
1180\begin{verbatim}
1181- e (RW_TAC arith_ss [FACT, DIVIDES_RMUL]);
1182OK..
1183
1184Goal proved.  ...
1185> val it =
1186    Initial goal proved.
1187    |- !m n. 0 < m /\ m <= n ==> m divides FACT n
1188\end{verbatim}
1189\end{session}
1190\noindent Lasciamo i dettagli del cucire insieme la dimostrazione al lettore
1191interessato.
1192
1193\section{Primariet�}
1194
1195Ora ci spostiamo a stabilire alcuni fatti circa la primariet� dei
1196primi numeri: $0$ e $1$ non sono primi, ma $2$ lo �. Inoltre, tutti
1197i primi sono positivi. Queste sono piuttosto semplici da dimostrare.
1198
1199\begin{description}
1200
1201\item [\small{({\it NOT\_PRIME\_0\/})}]
1202\begin{tabular}[t]{l}
1203\verb+~prime 0+ \\ \hline
1204\verb+RW_TAC arith_ss [prime_def,DIVIDES_0]+ \\
1205\end{tabular}
1206
1207\item [\small{({\it NOT\_PRIME\_1\/})}]
1208\begin{tabular}[t]{l}
1209\verb+~prime 1+ \\ \hline
1210\verb+RW_TAC arith_ss [prime_def]+ \\
1211\end{tabular}
1212
1213\item [\small{({\it PRIME\_2\/})}]
1214\begin{tabular}[t]{l}
1215\verb+prime 2+ \\ \hline
1216\verb+RW_TAC arith_ss [prime_def]+ \\
1217\verb+ THEN METIS_TAC [DIVIDES_LE, DIVIDES_ZERO,+ \\
1218\verb+                 DECIDE ``~(2=1)``, DECIDE ``~(2=0)``,+ \\
1219\verb+                 DECIDE ``x <= 2 = (x=0) \/ (x=1) \/ (x=2)``]+ \\
1220\end{tabular}
1221
1222\item [\small{({\it PRIME\_POS\/})}]
1223\begin{tabular}[t]{l}
1224\verb+!p. prime p ==> 0<p+ \\ \hline
1225\verb+Cases THEN RW_TAC arith_ss [NOT_PRIME_0]+ \\
1226\end{tabular}
1227\end{description}
1228
1229\section{Esistenza dei fattori primi}
1230
1231Ora siamo nella posizione di dimostrare un lemma pi� sostanziale: ogni numero
1232diverso da $1$ ha un fattore primo. La dimostrazione procede attraverso
1233un'\emph{induzione completa} su $n$. L'induzione completa �
1234necessaria dal momento che un fattore primo non sar� un predecessore. Dopo
1235l'induzione, la dimostrazione si divide nei casi se $n$ � primo o
1236no. Il primo caso ($n$ � primo) �
1237banale. Nel secondo caso, ci deve essere un $x$ che divide $n$, e
1238$x$ non � $1$ o $n$. Per {\small\it DIVIDES\_LE}, $n=0$ o $x \leq n$. Se
1239$n=0$, allora $2$ � un primo che divide $0$. Dall'altro lato, se $x \leq
1240n$, ci sono due casi: se $x < n$ allora possiamo usare l'ipotesi
1241d'induzione e per la transitivit� di \ml{divides} abbiamo finito; altrimenti,
1242$x=n$ e quindi abbiamo una contraddizione con il fatto che $x$ non � $1$
1243n� $n$. La tattica ripulita � la seguente:
1244\begin{description}
1245\item [\small{({\it PRIME\_FACTOR\/})}]
1246\begin{tabular}[t]{l}
1247\verb+!n. ~(n = 1) ==> ?p. prime p /\ p divides n+ \\ \hline
1248\verb+completeInduct_on `n`+ \\
1249\verb+  THEN RW_TAC arith_ss []+ \\
1250\verb+  THEN Cases `prime n` THENL+ \\
1251\verb+  [METIS_TAC [DIVIDES_REFL], + \\
1252\verb+   `?x. x divides n /\ ~(x=1) /\ ~(x=n)` + \\
1253\verb+    by METIS_TAC[prime_def]+ \\
1254\verb+     THEN METIS_TAC [LESS_OR_EQ, PRIME_2, +\\
1255\verb+                  DIVIDES_LE,DIVIDES_TRANS,DIVIDES_0]]+ \\
1256\end{tabular}
1257\end{description}
1258Iniziamo invocando l'induzione completa. Questo ci d� un'ipotesi
1259d'induzione che vale per ogni numero $m$ strettamente minore di $n$:
1260\begin{session}
1261\begin{verbatim}
1262- g `!n. ~(n = 1) ==> ?p. prime p /\ p divides n`;
1263
1264- e (completeInduct_on `n`);
1265OK..
12661 subgoal:
1267> val it =
1268    ~(n = 1) ==> ?p. prime p /\ p divides n
1269    ------------------------------------
1270      !m. m < n ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1271\end{verbatim}
1272\end{session}
1273Possiamo spostare l'antecedente nelle ipotesi e fare il nostro case
1274split. Si noti che il termine dato a \ml{Cases\_on} non deve per forza essere nel
1275goal:
1276\begin{session}
1277\begin{verbatim}
1278- e (RW_TAC arith_ss [] THEN Cases_on `prime n`);
1279OK..
12802 subgoals:
1281> val it =
1282    ?p. prime p /\ p divides n
1283    ------------------------------------
1284      0.  !m. m < n ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1285      1.  ~(n = 1)
1286      2.  ~prime n
1287
1288    ?p. prime p /\ p divides n
1289    ------------------------------------
1290      0.  !m. m < n ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1291      1.  ~(n = 1)
1292      2.  prime n
1293\end{verbatim}
1294\end{session}
1295\noindent Come menzionato, il primo caso � dimostrato con la riflessivit� della
1296divisibilit�:
1297\begin{session}
1298\begin{verbatim}
1299- e (METIS_TAC [DIVIDES_REFL]);
1300OK..
1301metis: r[+0+7]+0+0+0+0+1#
1302
1303Goal proved.  ...
1304\end{verbatim}
1305\end{session}
1306\noindent
1307Nel secondo caso, otteniamo un divisore di $n$ che non � $1$ n� $n$
1308(dal momento che $n$ non � primo):
1309\begin{session}
1310\begin{verbatim}
1311- e (`?x. x divides n /\ ~(x=1) /\ ~(x=n)` by METIS_TAC [prime_def]);
1312OK..
1313metis: r[+0+11]+0+0+0+0+0+0+1+1+1+1+0+1+1#
13141 subgoal:
1315> val it =
1316    ?p. prime p /\ p divides n
1317    ------------------------------------
1318      0.  !m. m < n ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1319      1.  ~(n = 1)
1320      2.  ~prime n
1321      3.  x divides n
1322      4.  ~(x = 1)
1323      5.  ~(x = n)
1324\end{verbatim}
1325\end{session}
1326A questo punto, la tattica ripulita invoca semplicemente \ml{METIS\_TAC} con
1327una collezione di teoremi. Tenteremo un'esposizione pi�
1328dettagliata. Data l'ipotesi, e {\small\it DIVIDES\_LE}, possiamo
1329affermare $x < n \lor n = 0$ e cos� dividere la dimostrazione in due casi:
1330\begin{session}
1331\begin{verbatim}
1332- e (`x < n \/ (n=0)` by METIS_TAC [DIVIDES_LE,LESS_OR_EQ]);
1333OK..
1334metis: r[+0+14]+0+0+0+0+0+0+0+0+0+0+1+0+1#
13352 subgoals:
1336> val it =
1337    ?p. prime p /\ p divides n
1338    ------------------------------------
1339      0.  !m. m < n ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1340      1.  ~(n = 1)
1341      2.  ~prime n
1342      3.  x divides n
1343      4.  ~(x = 1)
1344      5.  ~(x = n)
1345      6.  n = 0
1346
1347    ?p. prime p /\ p divides n
1348    ------------------------------------
1349      0.  !m. m < n ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1350      1.  ~(n = 1)
1351      2.  ~prime n
1352      3.  x divides n
1353      4.  ~(x = 1)
1354      5.  ~(x = n)
1355      6.  x < n
1356\end{verbatim}
1357\end{session}
1358Nel primo subgoal, possiamo vedere che gli antecedenti dell'ipotesi
1359d'induzione sono soddisfatti e cos� $x$ ha un divisore primo. Possiamo quindi usare
1360la transitivit� della divisibilit� per ottenere il fatto che questo divisore di $x$ �
1361anche un divisore di $n$, concludendo quindi questo ramo della dimostrazione:
1362\begin{session}
1363\begin{verbatim}
1364- e (METIS_TAC [DIVIDES_TRANS]);
1365OK..
1366metis: r[+0+11]+0+0+0+0+0+0+0+1+0+4+1+0+3+0+2+2+1#
1367
1368Goal proved.
1369\end{verbatim}
1370\end{session}
1371\noindent I goal rimanenti possono essere chiariti per semplificazione:
1372\begin{session}
1373\begin{verbatim}
1374- e (RW_TAC arith_ss  []);
1375OK..
13761 subgoal:
1377> val it =
1378    ?p. prime p /\ p divides 0
1379    ------------------------------------
1380      0.  !m. m < 0 ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1381      1.  ~(0 = 1)
1382      2.  ~prime 0
1383      3.  x divides 0
1384      4.  ~(x = 1)
1385      5.  ~(x = 0)
1386
1387- DIVIDES_0;
1388> val it = |- !x. x divides 0 : thm
1389
1390- e (RW_TAC arith_ss  [it]);
1391OK..
13921 subgoal:
1393> val it =
1394    ?p. prime p
1395    ------------------------------------
1396      0.  !m. m < 0 ==> ~(m = 1) ==> ?p. prime p /\ p divides m
1397      1.  ~(0 = 1)
1398      2.  ~prime 0
1399      3.  x divides 0
1400      4.  ~(x = 1)
1401      5.  ~(x = 0)
1402\end{verbatim}
1403\end{session}
1404I due passi della semplificazione esplorativa ci hanno portato a uno stato dove
1405tutto ci� che dobbiamo fare � esibire un primo. E ne abbiamo gi� uno a portata di mano:
1406\begin{session}
1407\begin{verbatim}
1408- e (METIS_TAC [PRIME_2]);
1409OK..
1410metis: r[+0+6]#
1411
1412Goal proved.   ...
1413> val it =
1414    Initial goal proved.
1415    |- !n. ~(n = 1) ==> ?p. prime p /\ p divides n
1416\end{verbatim}
1417\end{session}
1418Di nuovo, � necessario fare del lavoro per comporre e magari ripulire una singola
1419tattica, dai passi individuali di dimostrazione, ma non lo descriveremo\footnote{
1420Di fatto, la tattica pu� essere semplificata in un'induzione completa
1421 seguita da un'invocazione di \ml{METIS\_TAC} con lemmi adeguati.}.
1422Piuttosto andiamo avanti, perch� il nostro obiettivo finale � a portata di mano.
1423
1424\section{Il teorema di Euclide}
1425
1426\noindent{\bf Teorema.} Ogni numero ha un primo pi� grande di lui.\\
1427\noindent  {\it Dimostrazione Informale.} \\
1428\noindent Assumiamo l'opposto; allora c'� un $n$
1429tale che tutti i $p$ pi� grandi di $n$ non sono primi. Si consideri $\mbox{\tt
1430FACT}(n) + 1$: esso non � uguale a 1 cos�, per {\small{\it PRIME\_FACTOR}},
1431c'� un primo $p$ che lo divide. Si noti che $p$ divide anche
1432$\mbox{\tt FACT}(n)$ perch� $p \leq n$\footnote{Per {\small{\it DIVIDES\_FACT}} [ndt].}. Per {\small{\it DIVIDES\_ADDL}},
1433abbiamo $p=1$. Ma allora $p$ non � primo, il che � una contraddizione. \\
1434\noindent {\it Fine della dimostrazione}.
1435
1436Una traduzione in HOL della dimostrazione pu� essere data nel modo seguente:
1437\begin{description}
1438\item [\small{({\it EUCLID\/})}]
1439\begin{tabular}[t]{l}
1440\verb+!n. ?p. n < p /\ prime p+ \\ \hline
1441\verb+SPOSE_NOT_THEN STRIP_ASSUME_TAC+ \\
1442\verb!  THEN MP_TAC (SPEC ``FACT n + 1`` PRIME_FACTOR)! \\
1443\verb+  THEN RW_TAC arith_ss [FACT_LESS, DECIDE ``~(x=0) = 0<x``]+ \\
1444\verb+  THEN METIS_TAC [NOT_PRIME_1, NOT_LESS, PRIME_POS, + \\
1445\verb+                  DIVIDES_FACT, DIVIDES_ADDL, DIVIDES_ONE]+ \\
1446\end{tabular}
1447\end{description}
1448Consideriamo questo a parte e osserviamolo nel dettaglio. Una dimostrazione per
1449contraddizione pu� essere avviata usando la funzione di \ml{bossLib}
1450\ml{SPOSE\_NOT\_THEN}. Con essa, si assume la negazione del
1451goal attuale e quindi la si usa nel tentativo di dimostrare la falsit�
1452(\verb+F+). La negazione assunta $\neg(\forall n.\ \exists p.\ n < p
1453\land \mbox{\tt prime}\ p)$ � semplificata un p� in $\exists n.\
1454\forall p.\ n < p \supset \, \neg \,\mbox{\tt prime}\ p$ e poi �
1455passata alla tattica \ml{STRIP\_ASSUME\_TAC}. Questo sposta il suo argomento
1456alla lista delle assunzioni del goal dopo aver eliminato la quantificazione
1457esistenziale su $n$.
1458\begin{session}
1459\begin{verbatim}
1460- g `!n. ?p. n < p /\ prime p`;
1461
1462- e (SPOSE_NOT_THEN STRIP_ASSUME_TAC);
1463OK..
14641 subgoal:
1465> val it =
1466    F
1467    ------------------------------------
1468      !p. n < p ==> ~prime p
1469\end{verbatim}
1470\end{session}
1471Cos� abbiamo l'ipotesi che tutti i $p$ al di sopra di un certo $n$ non
1472specificato non sono primi, e il nostro compito � di mostrare che ci� non pu� essere. A questo
1473punto approfittiamo della grande ispirazione di Euclide e costruiamo un
1474termine esplicito da $n$. Nella dimostrazione informale ci viene chiesto di `considerare'
1475il termine $\mbox{\tt FACT}\ n + 1$\footnote{Il parser di HOL pensa che
1476$\mbox{\tt FACT}\ n + 1$ sia equivalente a $(\mbox{\tt FACT}\ n) + 1$.}
1477Questo termine avr� certe propriet� (cio�, ha un fattore primo) che
1478porta a una contraddizione. Domanda: come `consideriamo' questo termine nella
1479dimostrazione formale HOL? Risposta: istanziando un lemma con esso e portando il
1480lemma nella dimostrazione. Il lemma e la sua istanziazione sono \footnote{La
1481funzione {\tt SPEC} implementa la regola della specializzazione universale.}:
1482\begin{session}
1483\begin{verbatim}
1484- PRIME_FACTOR;
1485> val it = |- !n. ~(n = 1) ==> (?p. prime p /\ p divides n) : thm
1486
1487- val th = SPEC ``FACT n + 1`` PRIME_FACTOR;
1488> val th =
1489    |- ~(FACT n + 1 = 1) ==> (?p. prime p /\ p divides FACT n + 1)
1490\end{verbatim}
1491\end{session}
1492E' evidente che l'antecedente di \ml{th} pu� essere eliminato. In
1493\holn{}, si potrebbe fare questo in un cosiddetto stile di dimostrazione {\it in avanti\/} (dimostrando
1494$\vdash \neg(\mbox{\tt FACT}\ n + 1 = 1)$ e poi applicando {\it
1495modus ponens}, il cui risultato pu� poi essere usato nella dimostrazione), oppure
1496si potrebbe portare \ml{th} nella dimostrazione e semplificarlo {\it in
1497situ}. Scegliamo il secondo approccio.
1498\begin{session}
1499\begin{verbatim}
1500- e (MP_TAC (SPEC ``FACT n + 1`` PRIME_FACTOR));
1501OK..
15021 subgoal:
1503> val it =
1504    (~(FACT n + 1 = 1) ==> ?p. prime p /\ p divides FACT n + 1) ==> F
1505    ------------------------------------
1506      !p. n < p ==> ~prime p
1507\end{verbatim}
1508\end{session}
1509    L'invocazione di \ml{MP\_TAC} ($\vdash M$) applicata a un goal
1510		$(\Delta, g)$ restituisce il goal $(\Delta, M \supset g)$. Ora
1511		semplifichiamo:
1512\begin{session}
1513\begin{verbatim}
1514- e (RW_TAC arith_ss []);
1515OK..
15162 subgoals:
1517> val it =
1518    ~prime p \/ ~(p divides FACT n + 1)
1519    ------------------------------------
1520      0.  !p. n < p ==> ~prime p
1521      1.  prime p
1522
1523    ~(FACT n = 0)
1524    ------------------------------------
1525      !p. n < p ==> ~prime p
1526\end{verbatim}
1527\end{session}
1528    Si ricordi che zero � minore di qualsiasi fattoriale, un fatto che si trova in
1529		\ml{arithmeticTheory} sotto il nome \ml{FACT\_LESS}. Cos� possiamo
1530		risolvere il goal principale per semplificazione:
1531\begin{session}
1532\begin{verbatim}
1533- e (RW_TAC arith_ss [FACT_LESS, DECIDE ``!x. ~(x=0) = 0 < x``]);
1534OK..
1535Goal proved.  ...
1536\end{verbatim}
1537\end{session}
1538Si noti l'uso `on-the-fly' di \verb+DECIDE+ per fornire una riscrittura
1539\textit{ad hoc}. Osservando il goal rimanente, si potrebbe pensare che il nostro obiettivo, di
1540dimostrare la falsit�, � andato perso. Ma questo non � vero: un goal
1541$\neg P \lor \neg Q$ � logicamente equivalente a $P \imp Q \imp \mathtt{F}$.
1542Nell'invocazione seguente, usiamo l'uguaglianza
1543$\vdash A \imp B = \neg A \lor B$ come una regola di riscrittura orientata da destra a sinistra per mezzo
1544dell'uso di \ml{GSYM}\footnote{In parole povere, \ml{GSYM} scambia i lati sinistro e
1545destro di qualsiasi equazione che trova.}.
1546\begin{session}
1547\begin{verbatim}
1548- IMP_DISJ_THM;
1549> val it = |- !A B. A ==> B = ~A \/ B : thm
1550
1551- e (RW_TAC arith_ss [GSYM IMP_DISJ_THM]);
1552OK..
15531 subgoal:
1554> val it =
1555    ~(p divides FACT n + 1)
1556    ------------------------------------
1557      0.  !p. n < p ==> ~prime p
1558      1.  prime p
1559     : goalstack
1560\end{verbatim}
1561\end{session}
1562
1563Possiamo procedere velocemente per mostrare che $p \ \mathtt{divides}\ (\mathtt{FACT}\; n)$,
1564e di conseguenza che $p = 1$, quindi che $p$ non � primo, a quel punto abbiamo finito.
1565Questo pu� essere impacchettato tutto in una singola invocazione di \ml{METIS\_TAC}:
1566\begin{session}
1567\begin{verbatim}
1568- e (METIS_TAC [DIVIDES_FACT, DIVIDES_ADDL, DIVIDES_ONE,
1569                NOT_PRIME_1, NOT_LESS, PRIME_POS]);
1570metis: r[+0+12]+0+0+0+0+0+0+0+1+1+0+0+0+0+1+1+1+1+4#
1571
1572Goal proved.
1573 [..] |- ~(p divides FACT n + 1)
1574
1575Goal proved.
1576 [.] |- ~prime p \/ ~(p divides FACT n + 1)
1577
1578Goal proved.
1579 [.]
1580|- (~(FACT n + 1 = 1) ==> ?p. prime p /\ p divides FACT n + 1) ==> F
1581
1582Goal proved.
1583 [.] |- F
1584> val it =
1585    Initial goal proved.
1586    |- !n. ?p. n < p /\ prime p : goalstack
1587\end{verbatim}
1588\end{session}
1589    Il teorema di Euclide ora � dimostrato, e possiamo riposare. Comunque, questa
1590		presentazione della dimostrazione finale sar� insoddisfacente per alcuni,
1591		dal momento che la dimostrazione � completamente nascosta nell'invocazione del
1592		ragionatore automatico. Bene allora, proviamo un'altra dimostrazione, questa volta
1593		impiegando il cosiddetto stile `asserzionale'. Quando usato in modo uniforme,
1594		questo permette una presentazione leggibile e lineare che rispecchia la
1595		dimostrazione informale. Il seguente dimostra il teorema di Euclide nello
1596		stile asserzionale. Pensiamo che sia abbastanza leggibile, certamente molto
1597		di pi� della dimostrazione standard basata su tattiche appena data\footnote{Si noti
1598		  che {\tt CCONTR\_TAC}, che � utilizzata per avviare la dimostrazione,
1599			istanzia una dimostrazione per contraddizione negando il goal e
1600			spostandolo nelle ipotesi, lasciando {\tt F} come il nuovo goal.}.
1601
1602\begin{description}
1603\item [\small{({\it AGAIN\/})}]
1604\begin{tabular}[t]{l}
1605\verb+!n. ?p. n < p /\ prime p+ \\ \hline
1606\verb|CCONTR_TAC THEN | \\
1607\verb|`?n. !p. n < p ==> ~prime p`  by METIS_TAC []             THEN| \\
1608\verb|`~(FACT n + 1 = 1)`           by RW_TAC arith_ss  [FACT_LESS,| \\
1609\verb|                                    DECIDE``~(x=0)=0<x``] THEN| \\
1610\verb|`?p. prime p /\  | \\
1611\verb|     p divides (FACT n + 1)`  by METIS_TAC [PRIME_FACTOR] THEN| \\
1612\verb|`0 < p`                       by METIS_TAC [PRIME_POS]    THEN| \\
1613\verb|`p <= n`                      by METIS_TAC [NOT_LESS]     THEN| \\
1614\verb|`p divides FACT n`            by METIS_TAC [DIVIDES_FACT] THEN| \\
1615\verb|`p divides 1`                 by METIS_TAC [DIVIDES_ADDL] THEN| \\
1616\verb|`p = 1`                       by METIS_TAC [DIVIDES_ONE]  THEN| \\
1617\verb|`~prime p`                    by METIS_TAC [NOT_PRIME_1]  THEN| \\
1618\verb|METIS_TAC []| \\
1619\end{tabular}
1620\end{description}
1621
1622\section{Trasformare lo script in una teoria}
1623\label{sec:script-to-theory}
1624
1625Avendo dimostrato il nostro risultato, probabilmente vogliamo impacchettarlo in un modo
1626che lo renda disponibile per le sessioni future, ma che non ci richieda di
1627di passare di nuovo attraverso lo sforzo di dimostrare il teorema. Persino avere
1628uno script completo da cui sia possibile fare un copia e incolla � una
1629soluzione soggetta ad errori.
1630
1631Al fine di fare questo abbiamo bisogno un file con il nome
1632$x$\ml{Script.sml}, dove $x$ � il nome della teoria che desideriamo
1633esportare. Questo file ha quindi bisogno di essere compilato. Di fatto, usiamo realmente
1634il compilatore di Moscow ML, accuratamente aumentato con il contesto logico
1635appropriato. Comunque, il linguaggio accettato dal compilatore non �
1636esattamente lo stesso di quello accettato dal sistema interattivo, cos� abbiamo
1637bisogno di fare un poco di lavoro per smussare lo script originario nella
1638forma corretta.
1639
1640Daremo un'illustrazione di conversione a una forma che possa essere
1641compilata usando lo script
1642\[
1643  \mbox{\ml{<holdir>/examples/euclid.sml}}
1644\] come nostra linea di base. Questo
1645file � gi� vicino ad essere nella forma corretta. Ha tutte le
1646dimostrazioni dei teoremi in una forma ``cucita'' cos� che quando eseguito, non
1647coinvolge per nulla il goal-stack. Nella sua forma data, pu� essere eseguito
1648come input per \textsf{hol} cos�:
1649
1650\setcounter{sessioncount}{0}
1651\begin{session}
1652\begin{verbatim}
1653$ cd examples/
1654$ ../bin/hol < euclid.sml
1655  ...
1656
1657> val EUCLID = |- !n. ?p. n < p /\ prime p : thm
1658  ...
1659
1660> val EUCLID_AGAIN = |- !n. ?p. n < p /\ prime p : thm
1661-
1662\end{verbatim}
1663\end{session}
1664
1665Comunque, vogliamo creare una \ml{euclidTheory} che possiamo caricare in
1666altre sessioni interattive. Cos�, il nostro primo passo � creare un file
1667\ml{euclidScript.sml}, e copiare in esso il corpo di
1668\ml{euclid.sml}
1669
1670La prima linea non-commentata apre \ml{arithmeticTheory}. Comunque, quando
1671si scrive per il compilatore, � necessario menzionare esplicitamente gli altri
1672moduli \HOL{} da cui dipende. Dobbiamo aggiungere
1673\[
1674\mbox{\ml{open HolKernel boolLib Parse bossLib}}
1675\]
1676La linea successiva che presenta una difficolt� �
1677\[
1678  \mbox{\ml{set\_fixity "divides" (Infixr 450);}}
1679\]
1680Mentre � legittimo digitare espressioni direttamente nel
1681sistema interattivo, il compilatore richiede che ogni espressione di primo livello
1682sia una dichiarazione. Soddisfiamo questo requisito alterando questa linea
1683in una dichiarazione ``non fare nulla'' che non registra il risultato
1684dell'espressione:
1685\[
1686\mbox{\ml{val \_{} = set\_fixity "divides" (Infixr 450)}}
1687\]
1688Gli unici altri cambiamenti extra sono inserire tra parentesi il resto del testo dello script
1689con le chiamate a \ml{new\_theory} e \ml{export\_theory}. Cos�,
1690prima della definizione di \ml{divides}, aggiungiamo:
1691\[
1692\mbox{\ml{val \_{} = new\_theory "euclid";}}
1693\]
1694and at the end of the file:
1695\[
1696\mbox{\ml{val \_{} = export\_theory();}}
1697\]
1698
1699Ora, possiamo compilare lo script che abbiamo creato usando lo
1700strumento \textsf{Holmake}. Per mantenere le cose un p� pi� ordinate, per prima cosa spostiamo
1701il nostro script in una nuova directory.
1702
1703\begin{session}
1704\begin{verbatim}
1705$ mkdir euclid
1706$ mv euclidScript.sml euclid
1707$ cd euclid
1708$ ../../bin/Holmake
1709Analysing euclidScript.sml
1710Trying to create directory .HOLMK for dependency files
1711Compiling euclidScript.sml
1712Linking euclidScript.uo to produce theory-builder executable
1713<<HOL message: Created theory "euclid".>>
1714Definition has been stored under "divides_def".
1715Definition has been stored under "prime_def".
1716Meson search level: .....
1717Meson search level: .................
1718 ...
1719Exporting theory "euclid" ... done.
1720Analysing euclidTheory.sml
1721Analysing euclidTheory.sig
1722Compiling euclidTheory.sig
1723Compiling euclidTheory.sml
1724\end{verbatim}
1725\end{session}
1726
1727Ora abbiamo creato quattro nuovi file, varie forme di \ml{euclidTheory}
1728con quattro differenti suffissi. Solo \ml{euclidTheory.sig} � realmente
1729adatta per un consumo da parte dell'uomo. Mentre siamo ancora nella directory
1730\ml{euclid} che abbiamo creato, possiamo provare:
1731
1732\begin{session}
1733\begin{alltt}
1734\$ ../../bin/hol
1735[...]
1736
1737[closing file "/local/scratch/mn200/Work/hol98/tools/end-init-boss.sml"]
1738- load "euclidTheory";
1739> val it = () : unit
1740- open euclidTheory;
1741> type thm = thm
1742  val DIVIDES_TRANS =
1743    |- !a b c. a divides b /\ b divides c ==> a divides c
1744    : thm
1745  ...
1746  val DIVIDES_REFL = |- !x. x divides x : thm
1747  val DIVIDES_0 = |- !x. x divides 0 : thm
1748\end{alltt}
1749\end{session}
1750
1751\section{Sommario}
1752
1753Il lettore ora ha visto un teorema interessante dimostrato, in grande dettaglio,
1754in \holn{}. La discussione ha illustrato gli strumenti di alto  livello forniti in
1755\ml{bossLib} e ha toccato questioni che includono la selezione degli strumenti, l'undo,
1756la `levigatura delle tattiche', la semplificazione esplorativa, e la `biforcazione' di
1757nuovi tentativi di dimostrazione. Abbiamo anche tentato di dare un'idea dei processi di
1758pensiero che un utente potrebbe impiegare. Ci� che segue � una raccolta pi� o meno
1759casuale di altre osservazioni.
1760\begin{itemize}
1761
1762\item Nonostante la dimostrazione del teorema di Euclide sia breve e semplice da
1763comprendere quando presentata in modo informale, � stata richiesta una quantit�
1764forse sorprendente di sviluppo a supporto dell'impostazione dell'argomento
1765classico di Euclide.
1766
1767\item Il supporto alla dimostrazione fornito da \ml{bossLib}
1768(\verb+RW_TAC+, \ml{METIS\_TAC}, \ml{DECIDE\_TAC}, \ml{DECIDE},
1769\ml{Cases\_on}, \ml{Induct\_on}, e dal costrutto ``\ml{by}'') � stato
1770quasi completo per questo esempio: raramente � stato necessario ricorrere a
1771tattiche di basso livello.
1772
1773\item La semplificazione � un cavallo di battaglia delle tattiche; persino quando � stato usato
1774un ragionatore automatico come \ml{METIS\_TAC}, la sua applicazione � stata spesso
1775preparata da qualche semplificazione esplorativa. Vale la pena quindi prendere
1776confidenza con i punti di forza e di debolezza del semplificatore.
1777
1778\item Un problema comune con i sistemi interattivi di dimostrazione � trattare con
1779le ipotesi. Spesso \ml{METIS\_TAC} e il costrutto ``\ml{by}'' permettono
1780di usare le ipotesi senza ricorrere direttamente alla loro indicizzazione
1781(o al dar loro un nome, che equivale alla stessa cosa). Questo � desiderabile,
1782dal momento che le ipotesi sono concettualmente un {\it insieme}, e inoltre,
1783l'esperienza ha mostrato che il proliferare dell'indicizzazione nelle ipotesi risulta in
1784script di dimostrazione difficili da manutenere. Comunque, pu� confondere lavorare con
1785un grande insieme di ipotesi, nel qual caso i seguenti approcci possono essere
1786utili.
1787
1788Ci si pu� riferire direttamente alle ipotesi usando \ml{UNDISCH\_TAC} (rende
1789l'ipotesi designata l'antecedente del goal),
1790\ml{ASSUM\_LIST} (fornisce l'intera lista delle ipotesi a una tattica),
1791\ml{POP\_ASSUM} (da la prima ipotesi a una tattica), e
1792\ml{PAT\_ASSUM} (da a una tattica la prima ipotesi
1793{\it che soddisfa il matching\/}). (Si veda \REFERENCE{} per maggiori dettagli su tutte queste cose.)
1794I numeri associati alle ipotesi dal gestore di dimostrazione verosimilmente potrebbero
1795essere usati per accedere alle ipotesi (sarebbe piuttosto semplice scrivere una
1796tattica simile). Comunque, iniziare una nuova dimostrazione � a volte la
1797cosa pi� illuminante da fare.
1798
1799In alcuni casi, � utile essere in grado di cancellare un'ipotesi. Questo si pu�
1800ottenere passando l'ipotesi a una tattica che la ignora.
1801Per esempio, per scartare la prima ipotesi, si pu� invocare
1802\ml{POP\_ASSUM (K ALL\_TAC)}.
1803
1804\item Nell'esempio, non abbiamo usato le caratteristiche pi� avanzate di
1805\ml{bossLib}, in gran parte perch� non forniscono, finora, molte pi�
1806funzionalit� rispetto alla semplice sequenza di semplificazione, procedure
1807di decisione, e ragionamento automatico al primo ordine. Il tatticale
1808\ml{THEN} � dunque servito come una sostituzione adeguata. Nel futuro,
1809questi punti d'ingresso dovrebbero diventare pi� potenti.
1810
1811\item E' quasi sempre necessario avere un'idea della dimostrazione {\it
1812    informale\/} al fine di avere successo quando di fa una dimostrazione
1813	formale. Tuttavia, troppo spesso i novizi adottano la seguente
1814	strategia: (1) riscrivere il goal con alcune definizioni rilevanti, e
1815	quindi (2) fare affidamento sulla sintassi del goal risultante per guidare
1816	la selezione delle tattiche successive. Un tale approccio costituisce un chiaro
1817	caso di cane che si morde la coda, ed � una strategia povera da adottare.
1818	La comprensione della struttura di alto livello della dimostrazione � uno dei
1819	fattori pi� importanti negli esercizi di verifica di successo.
1820
1821L'autore ha notato che molti degli esperti di verifica pi� di successo
1822lavorano usando un foglio di carta per tenere traccia dei passi principali che
1823devono essere fatti. Forse distogliere lo sguardo sulla carte aiuta a rompere
1824l'effetto ipnotizzante dello schermo del computer.
1825
1826Dall'altra parte, uno dei vantaggi di avere una logica meccanizzata
1827� che la macchina pu� essere usata come un calcolatore di espressioni formali,
1828e cos� l'utente lo pu� usare per esplorare velocemente e accuratamente varie
1829possibilit� di dimostrazione.
1830
1831\item Gli strumenti molto potenti come \ml{METIS\_TAC}, \ml{DECIDE\_TAC}, e
1832\ml{RW\_TAC} sono il modo principale per fare progressi in una dimostrazione in
1833\ml{bossLib}. In molti casi, essi fanno ci� che si desidera, o addirittura
1834riescono a stupire l'utente con la loro potenza. Nella formalizzazione del
1835teorema di Euclide, gli strumenti hanno funzionato piuttosto bene. Tuttavia, a volte
1836sono eccessivamente aggressivi, o semplicemente fanno errori. In questi casi, si devono
1837usare, o persino scrivere, degli strumenti di dimostrazione pi� specializzati, e di conseguenza
1838alla fine bisogna imparare il supporto sottostante a \ml{bossLib}.
1839
1840\item Avere una buona conoscenza dei lemmi disponibile, e di dove essi
1841si trovano, � una parte essenziale per avere successo. Spesso gli strumenti
1842potenti possono sostituire i lemmi in un dominio ristretto, ma in generale, si
1843deve sapere cosa � stato gi� dimostrato. Abbiamo visto che i punti di ingresso
1844in \verb+DB+ aiutano a trovare velocemente i lemmi.
1845
1846\end{itemize}
1847
1848
1849%%% Local Variables:
1850%%% mode: latex
1851%%% TeX-master: "tutorial"
1852%%% End:
1853