Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Doc/Prog_Prove/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 21 kB image not shown  

Quelle  Bool_nat_list.thy   Sprache: Isabelle

 
(*<*)
theory Bool_nat_list
imports Complex_Main
begin
(*>*)

text
\vspace{-4ex}
\section{\texorpdfstring{Types 🍋bool🍋nat and list}{Types bool, nat and list}}

These are the most important predefined types. We go through them one by one.
Based on examples we learn how to define (possibly recursive) functions and
prove theorems about them by induction and simplification.

\subsection{Type \indexed{🍋bool}{bool}}

The type of boolean values is a predefined datatype
@{datatype[display] bool}
with the two values \indexed{🍋True}{True} and \indexed{🍋False}{False} and
with many predefined functions:  ¬, etc. Here is how conjunction could be defined by pattern matching:


fun conj :: "bool \ bool \ bool" where
"conj True True = True" |
"conj _ _ = False"

textBoth the datatype and function definitions roughly follow the syntax
of functional programming languages.

\subsection{Type \indexed{🍋nat}{nat}}

Natural numbers are another predefined datatype:
@{datatype[display] nat}\index{Suc@🍋Suc}
All values of type 🍋nat are generated by the constructors
0 and 🍋SucThus the values of type 🍋nat are
0🍋Suc 0🍋Suc(Suc 0), etc.
There are many predefined functions: +*, etc. Here is how you could define your own addition:


fun add :: "nat \ nat \ nat" where
"add 0 n = n" |
"add (Suc m) n = Suc(add m n)"

textAnd here is a proof of the fact that 🍋add m 0 = m:

lemma add_02: "add m 0 = m"
apply(induction m)
apply(auto)
done
(*<*)
lemma "add m 0 = m"
apply(induction m)
(*>*)
txtThe \isacom{lemma} command starts the proof and gives the lemma
a name, add_02. Properties of recursively defined functions
need to be established by induction in most cases.
Command \isacom{apply}(induction m) instructs Isabelle to
start a proof by induction on mIn response, it will show the
following proof state\ifsem\footnote{See page \pageref{proof-state} for how to
display the proof state.}\fi:
@{subgoals[display,indent=0]}
The numbered lines are known as \emph{subgoals}.
The first subgoal is the base case, the second one the induction step.
The prefix m. is Isabelle's way of saying ``for an arbitrary but fixed \m\''. The \\\ separates assumptions from the conclusion.
The command \isacom{apply}(auto) instructs Isabelle to try
and prove all subgoals automatically, essentially by simplifying them.
Because both subgoals are easy, Isabelle can do it.
The base case 🍋add 0 0 = 0 holds by definition of 🍋add,
and the induction step is almost as simple:
add🍋~(Suc m) 0 = Suc(add m 0) = Suc m
using first the definition of 🍋add and then the induction hypothesis.
In summary, both subproofs rely on simplification with function definitions and
the induction hypothesis.
As a result of that final \isacom{done}, Isabelle associates the lemma
just proved with its name. You can now inspect the lemma with the command


thm add_02

txtwhich displays @{thm[show_question_marks,display] add_02} The free
variable m has been replaced by the \concept{unknown}
?m. There is no logical difference between the two but there is an
operational one: unknowns can be instantiated, which is what you want after
some lemma has been proved.

Note that there is also a proof method induct, which behaves almost
like induction; the difference is explained in \autoref{ch:Isar}.

\begin{warn}
Terminology: We use \concept{lemma}, \concept{theoremand \concept{rule}
interchangeably for propositions that have been proved.
\end{warn}
\begin{warn}
  Numerals (012\dotsand most of the standard
  arithmetic operations (+-*,
  <, etc.) are overloaded: they are available
  not just for natural numbers but for other types as well.
  For example, given the goal x + 0 = x, there is nothing to indicate
  that you are talking about natural numbers. Hence Isabelle can only infer
  that 🍋x is of some arbitrary type where 0 and +
  exist. As a consequence, you will be unable to prove the goal.
%  To alert you to such pitfalls, Isabelle flags numerals without a
%  fixed type in its output: @ {prop"x+0 = x"}.
  In this particular example, you need to include
  an explicit type constraint, for example x+0 = (x::nat)If there
  is enough contextual information this may not be necessary: 🍋Suc x =
  x automatically implies x::nat because 🍋Suc is not
  overloaded.
\end{warn}

\subsubsection{An Informal Proof}

Above we gave some terse informal explanation of the proof of
🍋add m 0 = m. A more detailed informal exposition of the lemma
might look like this:
\bigskip

\noindent
\textbf{Lemma🍋add m 0 = m

\noindent
\textbf{Proofby induction on m.
\begin{itemize}
\item Case 0 (the base case): 🍋add 0 0 = 0
  holds by definition of 🍋add.
\item Case 🍋Suc m (the induction step):
  We assume 🍋add m 0 = m, the induction hypothesis (IH),
  and we need to show add (Suc m) 0 = Suc m.
  The proof is as follows:\smallskip

  \begin{tabular}{@ {}rcl@ {\quad}l@ {}}
  🍋add (Suc m) 0 &=🍋Suc(add m 0)
  & by definition of add\\
              &=🍋Suc m & by IH
  \end{tabular}
\end{itemize}
Throughout this book, \concept{IH} will stand for ``induction hypothesis''.

We have now seen three proofs of 🍋add m 0 = 0: the Isabelle one, the
terse four lines explaining the base case and the induction step, and just now a
model of a traditional inductive proof. The three proofs differ in the level
of detail given and the intended reader: the Isabelle proof is for the
machine, the informal proofs are for humans. Although this book concentrates
on Isabelle proofs, it is important to be able to rephrase those proofs
as informal text comprehensible to a reader familiar with traditional
mathematical proofs. Later on we will introduce an Isabelle proof language
that is closer to traditional informal mathematical language and is often
directly readable.

\subsection{Type \indexed{list}{list}}

Although lists are already predefined, we define our own copy for
demonstration purposes:

(*<*)
apply(auto)
done 
declare [[names_short]]
(*>*)
datatype 'a list = Nil | Cons '"'a list"
(*<*)
for map: map
(*>*)

text
\begin{itemize}
\item Type 🍋'a list\ is the type of lists over elements of type \<^typ>\'a. Because 🍋'a\ is a type variable, lists are in fact \concept{polymorphic}: the elements of a list can be of arbitrary type (but must all be of the same type).
\item Lists have two constructors: 🍋Nil, the empty list, and 🍋Cons, which puts an element (of type 🍋'a\) in front of a list (of type \<^typ>\'a list).
Hence all lists are of the form 🍋Nil, or 🍋Cons x Nil,
or 🍋Cons x (Cons y Nil), etc.
\item \isacom{datatype} requires no quotation marks on the
left-hand side, but on the right-hand side each of the argument
types of a constructor needs to be enclosed in quotation marks, unless
it is just an identifier (e.g., 🍋nat or 🍋'a\).
\end{itemize}
We also define two standard functions, append and reverse:

fun app :: "'a list \ 'a list \ 'a list" where
"app Nil ys = ys" |
"app (Cons x xs) ys = Cons x (app xs ys)"

fun rev :: "'a list \ 'a list" where
"rev Nil = Nil" |
"rev (Cons x xs) = app (rev xs) (Cons x Nil)"

textBy default, variables xsys and zs are of
list type.

Command \indexed{\isacom{value}}{value} evaluates a termFor example,

value "rev(Cons True (Cons False Nil))"

textyields the result 🚫rev(Cons True (Cons False Nil)). This works symbolically, too:

value "rev(Cons a (Cons b Nil))"

textyields 🚫rev(Cons a (Cons b Nil)).
\medskip

Figure~\ref{fig:MyList} shows the theory created so far.
Because list🍋Nil🍋Cons, etc.are already predefined,
 Isabelle prints qualified (long) names when executing this theoryfor example, MyList.Nil
 instead of 🍋Nil.
 To suppress the qualified names you can insert the command
 \texttt{declare [[names\_short]]}.
 This is not recommended in general but is convenient for this unusual example.
% Notice where the
%quotations marks are needed that we mostly sweep under the carpet.  In
%particular, notice that \isacom{datatype} requires no quotation marks on the
%left-hand side, but that on the right-hand side each of the argument
%types of a constructor needs to be enclosed in quotation marks.

\begin{figure}[htbp]
\begin{alltt}
\input{MyList.thy}\end{alltt}
\caption{A theory of lists}
\label{fig:MyList}
\index{comment}
\end{figure}

\subsubsection{Structural Induction for Lists}

Just as for natural numbers, there is a proof principle of induction for
lists. Induction over a list is essentially induction over the length of
the list, although the length remains implicit. To prove that some property
P holds for all lists xs, i.e., \mbox{🍋P(xs)},
you need to prove
\begin{enumerate}
\item the base case 🍋P(Nil) and
\item the inductive case 🍋P(Cons x xs) under the assumption 🍋P(xs)for some arbitrary but fixed x and xs.
\end{enumerate}
This is often called \concept{structural inductionfor lists.

\subsection{The Proof Process}

We will now demonstrate the typical proof process, which involves
the formulation and proof of auxiliary lemmas.
Our goal is to show that reversing a list twice produces the original
list.

theorem rev_rev [simp]: "rev(rev xs) = xs"

txtCommands \isacom{theoremand \isacom{lemma} are
interchangeable and merely indicate the importance we attach to a
proposition. Via the bracketed attribute simp we also tell Isabelle
to make the eventual theorem a \conceptnoidx{simplification rule}: future proofs
involving simplification will replace occurrences of 🍋rev(rev xs) by
🍋xs. The proof is by induction:

apply(induction xs)

txt
As explained above, we obtain two subgoals, namely the base case (🍋Niland the induction step (🍋Cons):
@{subgoals[display,indent=0,margin=65]}
Let us try to solve both goals automatically:


apply(auto)

txtSubgoal~1 is proved, and disappears; the simplified version
of subgoal~2 becomes the new subgoal~1:
@{subgoals[display,indent=0,margin=70]}
In order to simplify this subgoal further, a lemma suggests itself.

\subsubsection{A First Lemma}

We insert the following lemma in front of the main theorem:

(*<*)
oops
(*>*)
lemma rev_app [simp]: "rev(app xs ys) = app (rev ys) (rev xs)"

txtThere are two variables that we could induct on: xs and
ys. Because 🍋app is defined by recursion on
the first argument, xs is the correct one:


apply(induction xs)

txtThis time not even the base case is solved automatically:
apply(auto)
txt
\vspace{-5ex}
@{subgoals[display,goals_limit=1]}
Again, we need to abandon this proof attempt and prove another simple lemma
first.

\subsubsection{A Second Lemma}

We again try the canonical proof procedure:

(*<*)
oops
(*>*)
lemma app_Nil2 [simp]: "app xs Nil = xs"
apply(induction xs)
apply(auto)
done

text
Thankfully, this worked.
Now we can continue with our stuck proof attempt of the first lemma:


lemma rev_app [simp]: "rev(app xs ys) = app (rev ys) (rev xs)"
apply(induction xs)
apply(auto)

txt
We find that this time auto solves the base case, but the
induction step merely simplifies to
@{subgoals[display,indent=0,goals_limit=1]}
The missing lemma is associativity of 🍋app,
which we insert in front of the failed lemma rev_app.

\subsubsection{Associativity of 🍋app}

The canonical proof procedure succeeds without further ado:

(*<*)oops(*>*)
lemma app_assoc [simp]: "app (app xs ys) zs = app xs (app ys zs)"
apply(induction xs)
apply(auto)
done
(*<*)
lemma rev_app [simp]: "rev(app xs ys) = app (rev ys)(rev xs)"
apply(induction xs)
apply(auto)
done

theorem rev_rev [simp]: "rev(rev xs) = xs"
apply(induction xs)
apply(auto)
done
(*>*)
text
Finally the proofs of @{thm[source] rev_app} and @{thm[source] rev_rev}
succeed, too.

\subsubsection{Another Informal Proof}

Here is the informal proof of associativity of 🍋app
corresponding to the Isabelle proof above.
\bigskip

\noindent
\textbf{Lemma🍋app (app xs ys) zs = app xs (app ys zs)

\noindent
\textbf{Proofby induction on xs.
\begin{itemize}
\item Case Nil🍋app (app Nil ys) zs = app ys zs =
  \mbox{🍋app Nil (app ys zs)holds by definition of app.
\item Case Cons x xs: We assume
  \begin{center} \hfill 🍋app (app xs ys) zs =
  🍋app xs (app ys zs) \hfill (IH) \end{center}
  and we need to show
  \begin{center} 🍋app (app (Cons x xs) ys) zs = app (Cons x xs) (app ys zs).\end{center}
  The proof is as follows:\smallskip

  \begin{tabular}{@ {}l@ {\quad}l@ {}}
  🍋app (app (Cons x xs) ys) zs\\
  = app (Cons x (app xs ys)) zs & by definition of app\\
  = Cons x (app (app xs ys) zs) & by definition of app\\
  = Cons x (app xs (app ys zs)) & by IH\\
  = app (Cons x xs) (app ys zs) & by definition of app
  \end{tabular}
\end{itemize}
\medskip

\noindent Didn't we say earlier that all proofs are by simplification? But
in both cases, going from left to right, the last equality step is not a
simplification at all! In the base case it is 🍋app ys zs = app Nil (app
ys zs). It appears almost mysterious because we suddenly complicate the
term by appending Nil on the left. What is really going on is this:
when proving some equality \mbox{🍋s = t}, both s and t are
simplified until they ``meet in the middle''. This heuristic for equality proofs
works well for a functional programming context like ours. In the base case
both 🍋app (app Nil ys) zs and 🍋app Nil (app
ys zs) are simplified to 🍋app ys zs, the term in the middle.

\subsection{Predefined Lists}
\label{sec:predeflists}

Isabelle's predefined lists are the same as the ones above, but with
more syntactic sugar:
\begin{itemize}
\item [] is \indexed{🍋Nil}{Nil},
\item 🍋x # xs is 🍋Cons x xs\index{Cons@🍋Cons},
\item [x🚫1, , x🚫n] is x🚫1 #  # x🚫n # []and
\item 🍋xs @ ys is 🍋app xs ys.
\end{itemize}
There is also a large library of predefined functions.
The most important ones are the length function
length :: 'a list \ nat\\index{length@\<^const>\length\} (with the obvious definition),
and the \indexed{🍋map}{map} function that applies a function to all elements of a list:
\begin{isabelle}
\isacom{fun🍋map :: @{typ[source] "('a \ 'b) \ 'a list \ 'b list"\isacom{where}\\
"\@{thm list.map(1) [of f]}\" |\\
"\@{thm list.map(2) [of f x xs]}\"
\end{isabelle}

\ifsem
Also useful are the \concept{head} of a list, its first element,
and the \concept{tail}, the rest of the list:
\begin{isabelle}\index{hd@🍋hd}
\isacom{funhd :: 'a list \ 'a\\
🍋hd(x#xs) = x
\end{isabelle}
\begin{isabelle}\index{tl@🍋tl}
\isacom{funtl :: 'a list \ 'a list\\
🍋tl [] = [] |\\
🍋tl(x#xs) = xs
\end{isabelle}
Note that since HOL is a logic of total functions, 🍋hd [] is defined,
but we do not know what the result is. That is🍋hd [] is not undefined
but underdefined.
\fi
%

From now on lists are always the predefined lists.

\ifsem\else
\subsection{Types 🍋int and 🍋real}

In addition to 🍋nat there are also the types 🍋int and 🍋real, the mathematical integers
and real numbers. As mentioned above, numerals and most of the standard arithmetic operations are overloaded.
In particular they are defined on 🍋int and 🍋real.

\begin{warn}
There are two infix exponentiation operators:
🍋(^) for 🍋nat and 🍋int (with exponent of type 🍋nat in both cases)
and 🍋(powr) for 🍋real.
\end{warn}
\begin{warn}
Type  🍋int is already part of theory 🍋Main, but in order to use 🍋real as well, you have to import
theory 🍋Complex_Main instead of 🍋Main.
\end{warn}

There are three coercion functions that are inclusions and do not lose information:
\begin{quote}
\begin{tabular}{rcl}
🍋int &::🍋nat ==> int\\
🍋real &::🍋nat ==> real\\
🍋real_of_int &::🍋int ==> real\\
\end{tabular}
\end{quote}

Isabelle inserts these inclusions automatically once you import Complex_Main.
If there are multiple type-correct completions, Isabelle chooses an arbitrary one.
For example, the input \noquotes{@{term[source] "(i::int) + (n::nat)"}} has the unique
type-correct completion 🍋(i::int) + int(n::nat)In contrast,
\noquotes{@{term[source] "((n::nat) + n) :: real"}} has two type-correct completions,
\noquotes{@{term[source]"real(n+n)"}} and \noquotes{@{term[source]"real n + real n"}}.

There are also the coercion functions in the other direction:
\begin{quote}
\begin{tabular}{rcl}
🍋nat &::🍋int ==> nat\\
🍋floor &::🍋real ==> int\\
🍋ceiling &::🍋real ==> int\\
\end{tabular}
\end{quote}
\fi

\subsection*{Exercises}

\begin{exercise}
Use the \isacom{value} command to evaluate the following expressions:
@{term[source] "1 + (2::nat)"}, @{term[source] "1 + (2::int)"},
@{term[source] "1 - (2::nat)"and @{term[source] "1 - (2::int)"}.
\end{exercise}

\begin{exercise}
Start from the definition of 🍋add given above.
Prove that 🍋add is associative and commutative.
Define a recursive function double :: 🍋nat ==> nat
and prove 🍋double m = add m m.
\end{exercise}

\begin{exercise}
Define a function count :: 🍋'a \ 'a list ==> nat
that counts the number of occurrences of an element in a list. Prove
🍋count x xs  length xs.
\end{exercise}

\begin{exercise}
Define a recursive function snoc :: 🍋'a list \ '==> 'a list\
that appends an element to the end of a list. With the help of snoc
define a recursive function reverse :: 🍋'a list \ 'a list
that reverses a list. Prove 🍋reverse(reverse xs) = xs.
\end{exercise}

\begin{exercise}
Define a recursive function sum_upto :: 🍋nat ==> nat such that
\mbox{sum_upto n= 0 + ... + n and prove
🍋 sum_upto (n::nat) = n * (n+1) div 2.
\end{exercise}

(*<*)
end
(*>*)

Messung V0.5
C=96 H=100 G=97

¤ Dauer der Verarbeitung: 0.42 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.