Anreicherung: Vorgehen • Neue Axiome hinzuzunehmen macht eine Spezifikation sehr schnell inkonsistent (siehe Versuch 3!) ⇒ Gewünscht: Nur „konsistenzerhaltende“ Anreicherungen • Formaler Begriff: Konsistenzerhaltend = Hierarchiepersistent • Neue Operationen sollten „monomorphieerhaltend“ sein: Wenn genau ein Datentyp spezifiziert, sollte die Operation ebenfalls eindeutig festgelegt sein • Formaler Begriff: Monomorphieerhaltend = Eindeutig Vorgehen: Anreicherung nur durch rekursive und nichtrekursive Definitionen für neue Operationen. Diese sind hierarchiepersistent und eindeutig. 138 Nichtrekursive Definitionen (Motivation) • Grundidee: Definition als Abkürzung einer grossen Formel • Prädikat: p(x) ↔ ϕ (p kommt in Formel ϕ nicht vor) • Funktion: f (x) = t (f kommt im Term t nicht vor) 139 Beispiel: Anreicherung um nichtrek. Prädikat NatDiv = enrich Nat with predicates | : nat × nat; axioms m | n ↔ ∃ k. k * m = n; end enrich Die Anreicherung NatDiv ist hierarchiepersistent und eindeutig. 140 Beispiel: Anr. um nichtrek. Prädikat (mit FU) NatPrime = enrich NatDiv with predicates prime : nat; axioms ¬ prime(0); ¬ prime(1); n ≥ 2 → (prime(n) ↔ ∀ m. m | n → m = 1 ∨ m = n); end enrich Die Anreicherung NatPrime ist hierarchiepersistent und eindeutig (FU nach n = 0, n = 1, n ≥ 2 ist vollständig). 141 Beispiel: Anreicherung um nichtrek. Konstante Nat12 = enrich Nat with constants 1 : nat; 2 : nat; axioms 1 = 0 +1; 2 = 0 +1 +1; end enrich Die Anreicherung Nat12 ist hierarchiepersistent und eindeutig (beachte: In KIV sind die Zahlen schon vordefiniert). 142 Weitere Beispiele für nichtrekursive Definitionen m ≤ n ↔ ∃ k. m + k = n m < n ↔ m ≤ n ∧ m 6= n m>n↔n<m even(n) ↔ ∃ m. n = m + m odd(n) ↔ ¬ even(n) m < n → min(m, n) = m, ¬ m < n → min(m, n) = n x ≥ 0 → abs(x) = x, x < 0 → abs(x) = −x last(l + (a + [])) = a (: unvollst. Def :) a ∈ l ↔ ∃ l′ , l′′ . l′ + a + l′′ = l isprefix(l, l′ ) ↔ ∃ l′′ . l + l′′ = l′ nodups(l) ↔ ¬ ∃ l1 , l2 , l3 , a. l = l1 + a + l2 + a + l3 143 Nichtrekursive Definitionen allgemein • Prädikat: p(x) ↔ ϕ (p kommt in Formel ϕ nicht vor) • Funktion: f (x) = t (f kommt im Term t nicht vor) • Prädikat mit 2 vollständigen Fällen: ε → (q(x, y) ↔ ϕ1 ), ¬ ε → (q(x, y) ↔ ϕ2 ) • Funktionen mit 3 unvollständigen Fällen: ε ∧ δ → f (x, y) = t1 , ε ∧ ¬ δ → f (x, y) = t2 , ¬ ε ∧ δ → f (x, y) = t3 Satz: Die Hinzunahme einer neuen Operation (Funktion oder Prädikat) mit nichtrekursiver Definition ist immer hierarchiepersistent. Wenn die Fälle vollständig sind, ist die Erweiterung sogar eindeutig. 144 Rekursive Definitionen (Motivation) • Datentypen bestehen aus (der Semantik von) Konstruktortermen • Rekursive Definitionen geben Definition durch Reduktion auf kleinere Konstruktorterme • Entsprechen einem rekursiven Programm, das den Term abläuft Length = enrich List with functions length : list → nat; axioms length([]) = 0; length(a + l) = length(l) +1; end enrich Satz: Die Hinzunahme einer neuen Operation mit rekursiver Definition zu einem freien Datentyp ist immer hierarchiepersistent. Wenn die Fälle vollständig sind, ist die Erweiterung immer eindeutig. 145 Beispiel: Anreicherung um rek. Definition Append = enrich List with functions . + . : list × list → list; axioms [] + l = l; (a + l) + l’ = a + (l + l’); end enrich Append ist hierarchiepersistent und eindeutig (+ ist überladen: Sowohl Element vor Liste hängen (rot und schwarz), als auch 2 Listen zusammenhängen (blau)). 146 Beispiel: Anreicherung um rek. Prädikat (FU) Sorted = enrich List with predicates sorted : list axioms ordered([]), ordered(a + []), ordered(a + b + l) ↔ a < b ∧ ordered(b + l) end enrich Ordered ist hierarchiepersistent und eindeutig, da die FU vollständig ist (jede Liste ist entweder = [], a + [], a + b + l). 147 Strukturierte Spezifikationen: Umbenennung und Parameter 148 Strukturierte Spezifikationen: Umbenennung Umbenennung: • Benennt die Operationen einer Spezifikation um • Nützlich um 2 Kopien zu erhalten • Syntax: rename <SPEC> by morphism <renaming1>; ... <renamingn>; end rename • renaming = <sort/op/var> → <sort/op/var>; • Identische Umbenennungen weglassen (werden beim Ansehen der Spezifikation aber angezeigt) • Nicht 2 Symbole auf dasselbe abbilden: Injektiv umbenennen • Entweder alle Variablen oder keine umbenennen 149 Beispiel Umbenennung: Listen zu Stacks List by morphism list → stack; [] → empty; (: Typangabe für überladenes Symbol :) + :: (elem × list → list) → push; (: pop nicht mehr postfix, Schreibweise stattdessen pop(x), default ist in/prae/postfix uebernehmen :) .rest → pop prio 0; (: top soll nun praefix sein :) .first → top .; (: eigentlich keine Stack-Operation, nur um Overloading zu zeigen :) + :: (list × list → list) → concat prio 0; x → st; y → st0; z → st1; rename end rename 150 Strukturierte Spezifikationen: Generische Spezifikation Generische Spezifikation: • Syntax: generic specification parameter <SPEC> using <SPEC1>, ..., <SPECn> target <signature> <induction> <axioms> end generic specification • Wie Anreicherung (von <SPEC>, <SPEC1>, ..., <SPECn>), nur wird von <SPEC> explizit gesagt, dass es sich um einen Parameter handelt • Vereinigung und Anreicherung übernimmt den (oder die) Parameter der Unterspezifikationen • Variante: generic data specification: Wie data specification nur mit 151 Parameter Strukturierte Spezifikationen: Aktualisierung (1) Aktualisierung: • Instanziert Parameter (oder einen Parameter) einer Spezifikation • Beispiel: Listen beliebiger Elemente → Listen von Zahlen • Syntax: actualize <SPEC> with <ASPEC1>,...,<ASPECn> by morphism <renaming1>; ... <renamingn>; end actualize • renaming = <sort/op/var> → <sort/op/var>; • Die Vereinigung von <ASPEC1>,...,<ASPECn> heisst aktuelle Spezifikation • Identische Umbenennungen weglassen • Entweder alle Variablen oder keine umbenennen 152 Strukturierte Spezifikationen: Aktualisierung (2) Aktualisierung: • Der Parameter muss in die aktuelle Spez. abgebildet werden • Abbildung darf nicht-injektiv sein: pair(elem1 , elem2 ) → pair(nat , nat ) • Der Nicht-Parameter-Teil darf nur injektiv und disjunkt zur aktuellen Spezifikation umbenannt werden, z. B. list → natlist • Die instanzierten Axiome des Parameters müssen Axiome in der aktuellen Spezifikation sein • Verallgemeinerung instantiated specification: ⋆ Axiome werden bewiesen ⋆ mapping statt morphism erlaubt es, eine Sorte auf ein Tupel von Sorten abzubilden 153 Aktualisierung: Beispiel (1) Order = specification sorts elem; constants d : elem; predicates ≪ : elem × elem; variables a, b, c : elem; axioms ¬ a ≪ a; a ≪ b ∧ b ≪ c → a ≪ c; ¬ a ≪ d; (: d ist minimal :) end specification List-Ord = generic data specification parameter Order using Nat list = [] | . + . (. .first : elem; . .rest : list); size functions length : list → nat; end generic data specification 154 Aktualisierung: Beispiel (2) NatList = List-Ord with Nat by morphism list → natlist; elem → nat; ≪ → <; d → 0; a → n; b → n0; c → n1; actualize end actualize Die instanzierten Axiome (u. a. ¬ n < 0) sind (modulo Umbenennung) in Nat vorhanden. Die Listenoperationen (+, .rest etc.) werden nicht umbenannt (sie bekommen nur die neuen Sorten als Argumente). 155 Strukturierte Spezifikation: Nichtfreie Datentypen 156 Nichtfreie Datentypen: Der typische Fehler Orderedlist = enrich List3 with predicates .<. : elem × elem ; ordered : list ; axioms ¬ a < a; a < b ∨ a = b ∨ b < a; a < b ∧ b < c → a < c; ordered([]); ordered(a + []); ordered(a + b + l) ↔ a < b ∧ ordered (b + l); end enrich NICHT ∀ l. ordered(l) addieren!!! Das wäre INKONSISTENT!!! Allgemein: Ein generierter Datentyp enthält immer alle Konstruktorterme. Man kann nicht nachträglich welche ausschliessen. Man kann nur einen nichtfreien Datentyp bilden, der Terme identifiziert 157 Spezifikation nichtfreier Datentypen • Spezifikationen nichtfreier Datentypen werden sehr leicht inkonsistent oder uneindeutig • Konstruiere nichtfreien Datentyp dadurch, daß alle Terme, die die gleichen Elemente repräsentieren sollen, in einer Klasse zusammengefaßt werden • Deshalb als erstes nach der Bestimmung der Konstruktoren: Definiere Gleichheit durch Extensionalitätsaxiom: x = y ↔ ϕ(x, y) • Dann: Die in ϕ benutzten Operationen werden rekursiv definiert • Damit: Monomorph: Höchstens ein Datentyp spezifiziert • Vorsicht: Rek. Def. kann inkonsistent sein! • Jetzt: Arrays, im Praktikum: Mengen (einfacher) 158 Beispiel: Arrayspezifikation, Teil 1 Array= specification using Nat; Elem; sorts array; functions mkar .[.] .[.] #. : : : : nat × elem array × nat × elem array × nat array → → → → array; array; elem; nat; induction array generated by mkar, []; variables d : elem; a, a’ : array; 159 Beispiel: Arrayspezifikation, Teil 2 Festlegungen: • Konstruktor mkar(n, d) bekommt Initialelement d (Alternative: Unspezifizierte Initialisierung) • Für m ≥ # a ist Selektion a[m] unspezifiziert • Für m ≥ # a ist Modifikation Identität: a[m, d] = a axioms a = a’ ↔ # a = # a’ ∧ ∀ n. n < # a → a[n] = a’[n]; # mkar(n,d) = n; # a[m , d] = # a; m < n → mkar(n,d)[m] = d; m < # a → a[m , d][m] = d; n 6= m → a[m , d][n] = a[n]; end specification 160 Inkonsistente rekursive Definition • Annahmen: ⋆ Mengen von nat. Zahlen definiert ⋆ Die Mengen sind von ∅ und insert generiert ⋆ Für Mengen gilt: insert(a,insert(a,∅)) = insert(a,∅) • Rekursive Definition: sum(∅) = 0, sum(insert(a, s)) = a + sum(s) • Inkonsistent, da aus insert(1,insert(1,∅))) = insert(1,∅) folgt: 2 = sum(insert(1,insert(1,∅))) = sum(insert(1,∅)) = 1 • Korrekte Definition: sum(∅) = 0, ¬ a ∈ s → sum(insert(a, s)) = a + sum(s) (im Fall a ∈ s ist insert(a, s) = s) • Operation sum muss mit der Definition der Gleichheit auf Mengen, i. e. dem Extensionalitätsaxiom verträglich sein! 161 Anforderungen an nichtfreie Datentypen • Semantische Überlegungen zur Spezifikation nichtfreier Datentypen: ⋆ Es gibt den Datentyp ⇒ Konsistenz (wenn Axiome für den intendierten Datentyp gelten) ⋆ Die im Extensionalitätsaxiom durch ϕ beschriebene Relation muss wenigstens Äquivalenzrelation sein: − Reflexivität: ϕ(a, a) − Kommutativität: ϕ(a, b) → ϕ(b, a) − Transitivität: ϕ(a, b) ∧ ϕ(b, c) → ϕ(a, c) • Für gleiche Konstruktorterme t1 , t2 muss Operation f dasselbe liefern: ϕ(t1 , t2 ) → f (t1 ) = f (t2 ) ⇒ Beweisverpflichtungen • Äquivalenzrel. + Verträglichkeit = Kongruenz 162 Korrekte Spez. der geordneten Listen (1) Orderedlist = specification sorts elem; ordlist; constants [] : ordlist; functions .+. : elem × ordlist → ordlist ; min : ordlist → elem ; butmin : ordlist → ordlist ; predicates . < . : elem × elem ; variables a, b, c : elem; l, l ′ : ordlist; induction ordlist generated by [], +; 163 Korrekte Spez. der geordneten Listen (2) axioms ¬ a < a; a < b ∨ a = b ∨ b < a; a < b ∧ b < c → a < c; l = l′ ↔ l = [] ∧ l’ = [] ∨ l 6= [] ∧ l’ 6= [] ∧ min(l) = min(l′ ) ∧ butmin(l) = butmin(l′ ); min(a + []) = a; a < b → min(a + b + l) = min(a + l); ¬ a < b → min(a + b + l) = min(b + l); butmin(a + []) = []; a < b → butmin(a + b + l) = b + butmin(a + l); ¬ a < b → butmin(a + b + l) = a + butmin(b + l); end specification 164 Noethersche Induktion 165 Noethersche Induktion (1) Definition (Noethersche Relationen) Sei ≪ ⊆ A × A. Die Relation ≪ heißt noethersch (oder wohlfundiert, engl. well-founded) wenn es keine unendlichen ≪-Ketten gibt: . . . ≪ a3 ≪ a2 ≪ a1 ≪ a0 Satz (Ordnungsprädikate) Ordnungsprädikate von Datendefinitionen sind noethersch in jedem Modell der Spezifikation. 166 Noethersche Induktion (2) Satz (Noethersche Induktion) Für noethersche Relationen ≪ gilt: Wenn für jedes a aus E(a′ ) für alle Elemente a′ ≪ a die Aussage E(a) gefolgert werden kann, so gilt E für alle Elemente: (∀ a. (∀ a′ . a′ ≪ a ⇒ E(a′ )) ⇒ E(a)) ⇒ ∀ b. E(b) Definition (Noethersche Induktionsregel) Sei y := free(Γ ⊢ ∆) \ {x} und ≪ noethersch. Induktion über x: IND(≪) ∀ y.∀ x′ . x′ ≪x→( Γ→ Γ⊢∆ V 167 W ′ x ∆)x , Γ ⊢∆ Noethersche Induktion (Beispiele) Beispiel: Natürliche Zahlen ∀ n0 . n0 < n → ϕ(n0 ) ⊢ ϕ(n) ⊢ ∀ n. ϕ(n) Beispiel: Listen ∀ l0 . (l0 ≪ l) → ϕ(l0 ) ⊢ ϕ(l) ⊢ ∀ l. ϕ(l) 168 Noethersche Induktion (Beispielprädikate) Größenordnung: Sei size : s → nat . Dann ist ≪ noethersch mit x ≪ y :↔ size(x) < size(y). Lexikalische Ordnung: Betrachte Spezifikation Pair2 von vorher. Seien <1 : elem1 × elem1 und <2 : elem2 × elem2 noethersch. Dann auch ≪ mit mkpair(a, b) ≪ mkpair(a′ , b′ ) :⇔ a <1 a′ ∨ (a = a′ ∧ b <2 b′ ). Untermengenordnung: Seien s, s′ zwei endliche Mengen (Spezifikation später). Dann ist s ⊂ s′ ↔ s ⊆ s ∧ s 6= s′ noethersch, da s ⊂ s′ → card(s) < card(s′ ). 169