• Keine Ergebnisse gefunden

Isabelle/HOL [39] is an interactive theorem prover, based on Higher-Order Logic (HOL).

It allows to declare data structures, functions, and properties about those in a style similar to functional programming languages. More importantly, Isabelle/HOL allows to show the mathematical correctness of those properties. In contrast to automatic theorem provers, the user/developer guides Isabelle/HOL interactively to develop a final proof.

This thesis, to a large amount, consists of developments done in Isabelle/HOL. Therefore, this section shall allow a reader not familiar with the software and its syntax to read and understand the snippets in the rest of the thesis. Of course, it is not feasible to cover all possible concepts of Isabelle used in this thesis. We thus sometimes rely on the understanding from the context, or that the point made by the snippet should be comprehensible without knowing every keyword.

A good introduction into the language and the prover system can be found in the book Concrete Semanticsby Nipkow and Klein [38].

2.1.1 Basic Notation

Similar to other functional languages, function application is writtenf a b instead off(a,b). Also, lambda terms with the standard syntaxλx. t(i. e., the function mappingxtot) are employed.

In general, types are not explicitly expressed but are inferred. When explicitly assigning a typeτ to some term t, we writet ::τ. Types can either be a type variable written'a, some otherwise declared type (e. g., the well-knownbool, int, nat,. . . ), functions'a⇒'b, or compound types. The latter ones are written in a postfix notation, thus'a listdenotes a list of some type'a. Other basic compound types are sets ('a set) and tuples ('a×'b).

On basic datatypes we have well known syntactic sugar like+onintandnat, or∪on sets. On lists, Isabelle introducesx#xsto denote prepending the elementxto the listxs.

Also, it denotes appending to listsxsandysbyxs@ys.

2.1.2 Defining new Types

Isabelle/HOL supports various ways of defining new types. We will only show the ones used throughout the thesis.

Synonyms for existing types, i. e., syntactic sugar only, are defined with type_synonym('k,'v)map = 'k⇒'v option

Here, we define a new type('k,'v)mapthat is identical to the function from'kto optional 'v. The type'v optioncan either beNoneto denote an empty result, orSome v.

Inductive datatypes are introduced using thedatatypeconstruction, listing each possible constructor:

datatype 'a option = None | Some 'a The construction can be recursive:

datatype nat = Zero | Suc nat

A third way, which we heavily rely on, is the definition of compound structures, calledrecordin Isabelle. Having defined a new record type'a pointfor two-dimensional coordinates of any kind as

record'a point = x :: 'a

y :: 'a

the fields are accessed via accessor functions named similar to the fields, i. e.,x pto get the x-coordinate of some pointp. An instance of that record is constructed with the following syntax:

Lx = 0, y = 0M

Updates1 are written similar:

pLy := 5M

Records can also be extended. So, for instance, we can add a z-coordinate to the point definition above, yielding a type'a coord:

record'a coord = 'a point + z :: 'a

Instances of type'a coordare now also of type'a point2. 2.1.3 Definitions

In Isabelle/HOL, there are, again, multiple ways of introducing new functions. We will show the ones used in this thesis.

The most simple variant is an abbreviation of some construct. Similar to type synonyms, they do not serve as a construct in their own right but are only used for pretty-printing:

abbreviationf_of_x≡f x

Full-fledged new definitions are given similarly:

definitionfirst_of_list xs≡xs!0 Or more verbose:

definitionfirst_of_list :: 'a list⇒'awhere first_of_list xs≡xs!0

1As we are in the functional world, this is not an in-place update but returns an updated instance.

2Strictly speaking, they are of type('a,'more)point_scheme, but we will ignore this for the thesis.

2.1 Isabelle/HOL

In this thesis, the semantical differences of definition and abbreviation will not show.

They are only used side-by-side to copy their usage in the theories and for those readers knowing Isabelle.

Similarly, in definitions we will use≡and=interchangebly. That is, the definition above might also be written

definitionfirst_of_list xs = xs!0

A third variant for definitions is also used sparingly: fun allows for recursion and pattern-matching on arguments:

funsum :: nat⇒nat⇒natwhere sum Zero b = b

| sum(Suc a)b = sum a(Suc b)

2.1.4 Lemmas and Proving Them Lemmas are defined as follows:

lemmazero_less_or_equal:

0≤(x::nat)

When assumptions are needed, they can be supplied in different forms:

lemmasum_greater:

x > 0 =⇒ y > 0 =⇒ x + y > 0 lemmasum_greater:

Jx > 0; y > 0K =⇒ x + y > 0 lemmasum_greater:

assumesx > 0andy > 0 showsx + y > 0

Further, there exist some synonyms forlemma, for instancetheoremandcorollary. They only serve as a semantical hint to the human reader and do not have any other effect.

This thesis will only very seldomly contain proofs of lemmas, they are to be found in the referenced Isabelle theory files instead. But sometimes they are given as an illustration.

A proof can be very short, consisting of one or two calls to proof-procedures:

lemmasum_greater:

x > 0 =⇒ y > 0 =⇒ x + y > 0 bysimp

lemmafoo:

(* some more complicated property *) bysimp blast

But only a fraction of all properties can be shown in such an easy way. For most of them, a manual proof is needed:

lemmabar:

(* something very elaborate *) proof

(* here follows the manual proof *) qed

We will spare the details of how such a proof looks like and will refer to Isabelle documen-tation [9].

2.1.5 Local Context

Quite often a collection of properties shares a common set of assumptions and/or defini-tions (e. g., an invariant on a data structure). It is possible to repeat them for each lemma, but this clutters the core message of that lemma. For this reason, Isabelle allows local contexts, calledlocale, that fix those assumptions and definitions:

localeexample =

fixesds :: data_structure assumesvalid ds begin

lemmasome_property:

some_property ds proof

(* in the proof, the fact that ds is valid may be used freely *) qed

end

For presentation, we do not use the form above. Instead we use a semantically equivalent variant, where we separate the declaration of the locale from the definitions there-in:

localeexample =

fixesds :: data_structure assumesvalid ds

lemma(inexample)some_property:

some_property ds

Similar to records, locales can build a hierarchy. Sublocales hereby inherit lemmas and definitions of their parent(s). For example, we might define a locale for general graphs:

localegraph =

fixesE ::('v×'v)set

definition(ingraph)V≡Range E ∪Domain E

On this we base finite graphs, introducing additional assumptions that allow additional properties to be shown:

localefin_graph = graph E forE ::('v×'v)set + assumesfinite E

2.1 Isabelle/HOL

lemma(infin_graph)finite_V:

finite V

This hiearchy can also be built after the fact: When using explicit inheritance like above, the assumptions from the parent locales are added to the one being defined. But when the child locale already has them given/shown otherwise, duplication would occur.

Therefore one can omit the explicit inheritance and show the sublocale status afterwards.

For instance automata might not be constructed in terms of graphs, but it can be shown that an automata also can be seen as one:

localeautomaton =. . .

sublocale(inautomaton)fin_graph proof

. . . qed

Eventually, after having finished a locale, one can interpret a locale, possibly with concrete parameters. Without this, the properties and definitions of the locale would not be accessible outside of the locale. For instance

interpretationgen!: fin_graph EforE

would make all lemmas and definitions of fin_graph accessible with the prefix genbut adding a parameterEand the implicit assumptions of the locale. On the other hand, given some concrete graphGone could do:

interpretationconc!: fin_graph G proof

(* show that G meets all assumptions *) qed

Now all lemmas and properties would (also) be accessible with theconcprefix, but having been fixed forG. This, albeit with slightly different syntax, is often used in proofs to make facts accessible for some concrete instance of that locale which is created in the process of the proof.

2.1.6 Deviation from the Theories

In this work, we wanted to be true to the Isabelle theories. But sometimes we had to deviate from them in order to fit something for the writing or to omit certain technicalities that would distract from the point in question. The deviation also includes slight changes to the syntax, leaving out some punctuation or rearranging arguments for better readability.

One larger change from the theories is using one locale, where the theories may employ two or more: In Isabelle it is not possible to use abbreviations or definitions in the assumptions of the locale that are only valid inside the locale. For that reason, we often had a locale holding the definitions and a second one adding the properties. This approach unfortunately bloats the inheritance hierarchy and complicates understanding. That is why we haven chosen to ignore this limitation in writing.

A second point is using explicit sets of edgesEand initial nodesV0to represent graphs.

In the theories they are often, but not always, passed around as a structure. To improve homogeneity, we have not followed this path here.

Im Dokument CAVA – A Verified Model Checker  (Seite 13-18)