Data Specification (Beispiel 3)

Werbung
Data Specification (Beispiel 3)
Beispiel 3: natürliche Zahlen
Nat =
data specification
nat = 0
| . +1 (. −1 : nat);
variables n : nat → nat;
order predicates . < . : nat × nat;
end data specification
n +1 −1 = n; (: 0 −1 ist unspezifiziert :)
¬ n < n; m < n ∧ n < k → m < k ;
¬ n < 0; m < n +1 ↔ (m = n ∨ m < n)
Generierte Axiome:
130
Data Specification (Beispiel 4)
Beispiel 4: Listen
List =
data specification
using Nat, Elem;
list = . + . (. .first : elem; . .rest : list) with consp
| [] with nilp;
variables l : list;
(: ist Unterterm für Listen = ist Endstück :)
order predicates . ≪ . : list × list;
size functions length : list → nat;
end data specification
131
Selektoren als partielle Funktionen
Problem: Was tun, wenn ein Selektor auf den falschen Summand
angewandt wird?
Hier: Was sind [] .first und [] .rest?
.first und .rest sollten für [] gar nicht definiert sein ⇒ Partielle Funktionen
In KIV: []. first und [].rest sind unspezifiziert (i. e. kein Axiom)
Semantik: [].rest ist in jeder Algebra (Datenstruktur) irgendeine andere Liste
⇒ Echte Implementierung muss irgendeine Liste zurückgeben
Pragmatik: Formeln mit [].rest sollten nicht vorkommen.
Wenn doch, muss die Sequenz ohne die Formeln beweisbar sein.
Bem.: Alternativen sind möglich aber komplizierter
(u.a. Fehlerelemente, echte Partialität, etc.)
132
Data Specification (Beispiel 3)
Neue Axiome für List3:
nilp([]);
¬ nilp(a + l);
¬ consp([]);
consp(a + l);
(a + l).first = a; (: kein Axiom für [] .first :)
(a + l).rest = l; (: kein Axiom für [] .rest :)
¬ l ≪ [];
l ≪ (a + l 1 ) ↔ l = l 1 ∨ l ≪ l 1 ;
(: beweisbar, aber der Einfachheit halber generiert :)
¬ l ≪ l ; l1 ≪ l2 ∧ l2 ≪ l3 → l1 ≪ l3 ;
length([]) = 0;
length(a + l) = length(l) +1;
133
Data Specification allgemein
Definition (Datendefinition)
Eine Datendefinition D hat die Form (optionales in eckigen Klammern):
s = c1 (sel1,1 : s1,1 ; . . . ; sel1,n1 : s1,n1 ) [with p1 ]
| ...
| ck (selk,1 : sk,1 ; . . . ; selk,nk : sk,nk ) [with pk ];
[order predicate . ≪ .;][size function sz;]
Überladen: seli,j = seli′ ,j ′ erlaubt, falls si,j = si′ ,j ′ ,
ansonsten alle Operationen paarweise verschieden.
134
Eigenschaften von Data Specifications
Satz:
Alle Data Specifications sind immer konsistent. Sie sind immer
monomorph bis auf unspezifizierte Selektoren und Parameter.
Intuition bei Listen ist also:
1. Wir haben exakt den Datentyp der Listen beschrieben.
2. Für die Realisierung auf einem Rechner ist lediglich offen,
• was für ein Elementtyp verwendet wird und
• was für eine Element bzw. Liste [].first und [].rest zurückgeben.
135
Datentyp-Definitionen in Java
Implementierung von Datentyp-Definitionen in Java:
abstract class s {} /* Dies entspricht der Sorte s */
/* Subklasse für Konstruktor c1 */
class c1 extends s {
s11 sel11; /* ein Feld pro Selektor */
s12 sel12; ...
s1n1 : sel1n1;
/* Konstruktor */
public c1(s11 se1, s12 se2, ...) {
sel11 = se1; sel12 = se2; ...}
}
/* Subklasse für Konstruktor c2 */
class c2 extends s {
...
}
136
Strukturierte Spezifikation:
Anreicherung um
nichtrekursive und rekursive
Definitionen
137
Strukturierte Spezifikationen
Motivation
Spezifikationen werden sehr schnell sehr groß
⇒ Strukturierung erforderlich
1. Übersichtlichkeit & Verständlichkeit
2. Wiederverwendung von Komponenten
3. Unabhängige Entwicklung von Komponenten
4. Strukturierung und Wiederverwendung von Beweisen
138
Strukturierte Spezifikationen in KIV
• KIV zeigt strukt. Spezifikationen als Spezifikationsgraph an
• In KIV enthält jeder Knoten neben der Spezifikation außerdem eine
Theorembasis
• Die Theorembasis enthält eine Menge von Theoremen (Sequenzen)
über der Gesamtsignatur
• Für jede Sequenz kann ein Beweis vorhanden sein, der zeigt, daß die
Sequenz aus SP und anderen Theoremen folgt (keine zyklischen
Abhängigkeiten)
• Theoreme aus darunterliegenden Spezifikation werden mit insert
spec-lemma statt insert lemma angewandt
• KIV hat ein Korrektheitsmanagement, um Abhängigkeiten zwischen
Beweisen zu verwalten
139
Strukturierte Spezifikationen:
Vereinigung und Anreicherung
• Vereinigung
⋆ Wirft Signaturen + Axiome zusammen
⋆ Syntax: union specification
<SPEC1> + <SPEC2> + ...
end union specification
⋆ Nichtdisjunkte Vereinigung nur, wenn gemeinsamer Teil in
gleicher Unterspezifikation (sonst Gefahr der Inkonsistenz!)
• Anreicherung
⋆ Addiert neue Signaturen + Axiome
⋆ Syntax: enrich <SPEC1>, <SPEC2>, ... with
<signature> <induction> <axioms>
end enrich
⋆ Implizit: Ausgangsspezifikation der Anreicherung ist die Vereinigung
von <SPEC1>, <SPEC2>, ...
140
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.
141
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)
142
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.
143
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).
144
Beispiel: Anreicherung um nichtrek. Fkt.
Nat12max =
enrich Nat with
constants 1 : nat; 2 : nat;
functions max : nat × nat → nat;
axioms
1 = 0 +1;
2 = 0 +1 +1;
m < n → max(m, n) = n;
¬ m < n → max(m, n) = m;
end enrich
Die Anreicherung Nat12max ist hierarchiepersistent und eindeutig
(beachte: In KIV sind die Zahlen 1,2 schon vordefiniert).
Beachte: Das Axiom max(m,n) = k ↔ (m < n ∧ k = n) ∨ (¬ m < n ∧ k = m)
bildet keine nichtrek. Definition. Axiome f(x) = y ↔ . . . sollte man vermeiden!
145
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)).first = a (: unvollst. Def :)
a ∈ l ↔ ∃ l′ , l′′ . l′ + a + l′′ = l
nodups(l) ↔ ¬ ∃ l1 , l2 , l3 , a. l = l1 + a + l2 + a + l3
146
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 )
(p kommt in ε, ϕ1 , ϕ2 nicht vor)
• Funktionen mit 3 unvollständigen Fällen:
ε ∧ δ → f (x, y) = t1 ,
ε ∧ ¬ δ → f (x, y) = t2 ,
¬ ε ∧ δ → f (x, y) = t3 (f kommt in ε, δ , ϕ1 , ϕ2 nicht vor)
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.
147
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.
148
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)).
149
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.
Das zweite und dritte Axiom sind äquivalent zu:
l’= [] → ordered(a + l’),
l’= b + l → ordered(a + l’) ↔ a < b ∧ ordered(l’)
(vollständige Fallunterscheidung). Die Gleichungen vor
der Implikation wurden eingesetzt (bessere Simplifierregel!).
150
Rekursive Definition allgemein
hier speziell: Funktionen/Prädikate mit 3 Argumenten
Definitionen im ersten rekursiv, Listen (allgemein: 1 Axiom pro Konstruktor)
• Prädikat: p-base: p([], y, z) ↔ ϕ1
p-rec : p(a + x, y, z) ↔ ϕ2
(x, y, z verschieden. ϕ1 hat keine Aufrufe von p.
ϕ2 hat nur Aufrufe von p der Form p(x, t1 , t2 ))
• Funktion: f-base: f ([], x, y) = t0
f-rec: f (a + x, y, z) = t
(x, y, z verschieden. t1 hat keine Aufrufe von f .
t hat nur Aufrufe von f der Form f (x, t4 , t5 ))
• Zusätzliche Fallunterscheidung in den Axiomen ist ok.
Z.B. statt f (a + z, y, z) = t 3 unvollständigen Fälle:
ε ∧ δ → f (a + x, y, z) = t1 ,
ε ∧ ¬ δ → f (a + x, y, z) = t2 ,
¬ ε ∧ δ → f (a + x, y, z) = t3
(ε, δ , t1 , t2 , t3 enthalten nur Aufrufe von f der Form f (x, t4 , t5 )
151
Strukturierte Spezifikationen:
Umbenennung und Parameter
152
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
153
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 also 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
154
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 ein Parameter ist.
• Vereinigung und Anreicherung übernimmt den (oder die) Parameter der
Unterspezifikationen
• Variante: generic data specification: Wie data specification nur mit
Parameter
155
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
156
Strukturierte Spezifikationen:
Aktualisierung (2)
Aktualisierung:
• Der Parameter muss in die aktuelle Spez. abgebildet werden
• Abbildung darf nicht-injektiv sein: pair(elem, elem) → 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
157
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
158
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 Argumentsorten).
159
Strukturierte Spezifikation:
Nichtfreie Datentypen
160
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
161
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)
Einzige Ausnahme, bei der das Prinzip nicht funktioniert: integers
(für die KIV-Axiome wurde ein Einzelbeweis für Monomorphie geführt)
162
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;
163
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
164
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!
165
Konsistenz nichtfreier Datentypen
2 Alternativen, um Konsistenz sicherzustellen:
1. Semantische Überlegung: Es gibt den spezifizierten Datentyp auf
Rechnern, und er erfüllt die Axiome ⇒ Konsistenz
2. Beweise über dem freien Datentyp, den man erhält, wenn man
• Extensionalität x = y ↔ ϕ(x,y) weglässt.
• generated by durch freely generated by ersetzt.
• Idee: Der freie Datentyp ist konsistent und monomorph.
Den nichtfreien erhält man, indem man Konstruktorterme, die per
Extensionalität „gleich“ sind, in Klassen zusammenwirft.
• Dazu muss ϕ eine Äquivalenzrelation sein:
ϕ(a, a), ϕ(a, b) → ϕ(b, a), ϕ(a, b) ∧ ϕ(b, c) → ϕ(a, c)
• Für „gleiche“ Terme t1 , t2 muss Operation f dasselbe liefern:
ϕ(t1 , t2 ) → f (t1 ) = f (t2 ) bzw. ϕ(t1 , t2 ) → ϕ(f (t1 ), f (t2 ))
• Äquivalenzrel. + Verträglichkeit = Kongruenz
• Formeln über dem freien Datentyp beweisbar ⇒ Konsistenz
166
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 [], +;
167
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
168
Zusammenfassung: Datentyp-Spezifikation
Vorgehen zur Spezifikation von Datentypen:
1. Bestimme Datenmengen ⇒ Sorten
2. Bestimme Konstruktoren
3. Falls frei ⇒ data specification
4. Falls nichtfrei ⇒ Extensionalitätsaxiom + (rek. oder nichtrek.) Definition
der im Axiom verwendeten Funktionen (mit evtl. Kongruenzbeweis)
5. Für weitere Funktionen: rek. oder nichtrek. Definitionen
(enrichment)
169
Herunterladen