21.01.2015 Aufrufe

¨Ubungen zu ” Modellierung verteilter Systeme“

¨Ubungen zu ” Modellierung verteilter Systeme“

¨Ubungen zu ” Modellierung verteilter Systeme“

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Technische Universität München SoSe 2013<br />

Institut für Informatik Lösungsblatt 4<br />

Prof. Dr. M. Broy, Dr. A. Malkis Ausgabe: 28. Mai 2013<br />

M. Gleirscher, V. Koutsoumpas, D. Marmsoler Besprechung: 6. Juni 2013<br />

Übungen <strong>zu</strong> ”<br />

<strong>Modellierung</strong> <strong>verteilter</strong> Systeme“<br />

Aufgabe 1 Bank<br />

Gegeben ist die Spezifikation des Gesamtsystems Bank sowie dessen Verteilung auf zwei Teilsysteme<br />

Bargeldbe<strong>zu</strong>g und Kontoverwaltung (Abbildung 1):<br />

x: A U C<br />

y: B U D<br />

Bank<br />

(a)<br />

Bank<br />

a: A<br />

b: B<br />

Bargeldbe<strong>zu</strong>g<br />

i1: I1<br />

i2: I2<br />

c: C<br />

Kontoverwaltung<br />

(b)<br />

d: D<br />

var s : Array[n] Nat<br />

Abbildung 1: (a) Schnittstellensicht des Systems Bank, im Kontext dessen Nutzer. (b) Die Komponenten<br />

Bargeldbe<strong>zu</strong>g (Abstraktion eines Bankomaten bzw. eines Schalters) und Kontoverwaltung (Abstraktion<br />

eines Schalters bzw. eines Online-Portals) des Systems Bank.<br />

Gegeben sind ebenso folgende, informell beschriebene Eigenschaften:<br />

(1) Annahme über den Nutzer: ”<br />

Keine Überziehung: Falls <strong>zu</strong> keinem Zeitpunkt die Summe der erfolgreichen<br />

Bargeldabhebungen höher als die Summe der Einzahlungen ist, boniert das System dies<br />

mit leicht erhöhten Zinsen.“ Anmerkung: Um das Modell für die Aufgabe knapp <strong>zu</strong> halten, ist die<br />

Kontoverzinsung im Modell nicht <strong>zu</strong> berücksichtigen.<br />

(2) Ungezeitete Lebendigkeitseigenschaft: ”<br />

Unendlich oft sollen vom Nutzer Auszahlungen mindestens<br />

in Höhe aller Einzahlungen getätigt werden können.“<br />

Führen Sie nun folgende Schritte durch:


(a) Entwerfen Sie je eine knapp gehaltene Moore-Maschine für die Teilsysteme Bargeldbe<strong>zu</strong>g (Auszahlung)<br />

und Kontoverwaltung (Einzahlung, Auszahlungsprüfung).<br />

(b) Führen Sie nun die zeitasynchrone, nachrichtensynchrone Komposition Bargeldbe<strong>zu</strong>g ‖ Kontoverwaltung<br />

durch und erstellen Sie eine Schnittstellenabstraktion der Ergebnismaschine.<br />

(c) Stellen Sie die beiden Zustandsmaschinen aus (a) als konstruktive Spezifikation von Stromfunktionen<br />

dar und leiten das Ergebnis der Komposition der beiden Stromfunktionen f 1 ⊗ f 2 her.<br />

(d) Die Ergebnisse aus (b) und (c) stellen das System Bank dar. Prüfen Sie nun anhand Ihrer Kompositionsergebnisse,<br />

ob die Eigenschaften (1) und (2) vom System Bank erfüllt werden.<br />

Lösung der Aufgabe 1<br />

Teilaufgabe a) Die Abbildungen 2 und 3 zeigen zwei Vorschläge für die gefragten Moore-Maschinen. Für<br />

die Teilaufgabe c) sei mit diesen Zustandsübergangsdiagrammen auch die beiden Strukturen (∆ b , Σ b0 ) für den<br />

Bargeldbe<strong>zu</strong>g und (∆ k , Σ k0 ) für die Kontoverwaltung gegeben.<br />

aabbruch;<br />

i1check(false,x,id)<br />

Bereit<br />

ahebeAb(x,id)<br />

Fernprüfung<br />

i2!prüfe(x,id)<br />

-<br />

Abhebung<br />

b!geld(x,id)<br />

i1check(true,x,id)<br />

Abbildung 2: Moore-Maschine für Bargeldbe<strong>zu</strong>g<br />

{s[1..n]:=0}<br />

Bereit<br />

czahleEin(x,id)<br />

{s[id]:=s[id]+x}<br />

Einzahlung<br />

d!ok<br />

c<strong>zu</strong>rück<br />

i2prüfe(x,id)<br />

- {if (s[id]>=x AND customerOk(id))<br />

then s[id]:=s[id]-x}<br />

Prüfung<br />

i1!check(s[id]>=x AND customerOk(id),x,id)<br />

i2prüfe(x,id)<br />

Abbildung 3: Moore-Maschine für Kontoverwaltung


Teilaufgabe b) Abbildung 4 zeigt im ersten Schritt die asynchron in Zeit und Nachrichten “roh” komponierte<br />

Moore-Maschine für Bank. Kurzbezeichnungen für Ein- und Ausgabeaktionen:<br />

QT ≡ “aabbruch; i1check(false,x,id)”,<br />

OK ≡ “i1check(true,x,id)”,<br />

ZE ≡ “czahleEin(x,id) {s[id]:=s[id]+x}”,<br />

V R ≡ “i1!check(s[id]>=x AND customerOk(id),x,id)”,<br />

UP ≡ “- {if (s[id]>=x AND customerOk(id)) then s[id]:=s[id]-x}”<br />

Es gibt 17 Klassen von Zuständen (sog. Kontroll<strong>zu</strong>stände), die wir im Zustandsübergangsdiagramm (ZÜD)<br />

durch 17 Knoten unterscheiden. Das Kreuzprodukt der Kontroll<strong>zu</strong>stände und der Auswahl je einer Ausgabeaktion<br />

ergibt 3∗3∗2 = 18, lediglich die Kontroll<strong>zu</strong>stände “Bereit/Bereit” sind schon vereinigt, da es dort in beiden<br />

Maschinen keine Ausgabeaktionen gibt. Die Funktion customerOk(id) : N → Bool prüft, ob der Nutzer mit<br />

dem Identifikator id ein Kunde der Bank ist.<br />

OK<br />

i2prüfe(x,id)<br />

Abhebung<br />

Prüfung<br />

VR<br />

UP<br />

Abhebung<br />

Bereit<br />

b!geld(x,id)<br />

i2prüfe(x,id)<br />

OK<br />

i2prüfe(x,id)<br />

ZE<br />

ZE<br />

-<br />

c<strong>zu</strong>rück<br />

ZE<br />

Fernprüfung<br />

Bereit<br />

Abhebung<br />

Einzahlung<br />

d!ok<br />

-<br />

-<br />

Bereit<br />

Prüfung<br />

Fernprüfung<br />

Einzahlung<br />

d!ok<br />

c<strong>zu</strong>rück<br />

-<br />

UP<br />

QT<br />

UP<br />

QT<br />

{s[1..n] :=0}<br />

i2prüfe(x,id)<br />

i2prüfe(x,id)<br />

UP<br />

i2prüfe(x,id)<br />

OK<br />

OK<br />

c<strong>zu</strong>rück<br />

Fernprüfung<br />

Prüfung<br />

VR<br />

QT<br />

ZE<br />

Bereit<br />

Bereit<br />

Abhebung<br />

Einzahlung<br />

b!geld(x,id)<br />

c<strong>zu</strong>rück<br />

-<br />

i2prüfe(x,id)<br />

ahebeAb(x,id)<br />

c<strong>zu</strong>rück<br />

-<br />

Bereit<br />

Einzahlung<br />

Fernprüfung<br />

Bereit<br />

i2!prüfe(x,id)<br />

i2prüfe(x,id)<br />

QT<br />

ZE<br />

UP<br />

QT<br />

OK<br />

ahebeAb(x,id)<br />

i2prüfe(x,id)<br />

Fernprüfung<br />

Einzahlung<br />

i2!prüfe(x,id)<br />

Bereit<br />

Einzahlung<br />

d!ok<br />

i2prüfe(x,id)<br />

ahebeAb(x,id)<br />

Abhebung<br />

Bereit<br />

UP<br />

c<strong>zu</strong>rück<br />

Abhebung<br />

Prüfung<br />

b!geld(x,id)<br />

ahebeAb(x,id)<br />

OK<br />

QT<br />

Fernprüfung<br />

Prüfung<br />

i2!prüfe(x,id)<br />

ahebeAb(x,id)<br />

i2prüfe(x,id)<br />

VR<br />

Bereit<br />

Prüfung<br />

Bargeldbe<strong>zu</strong>g<br />

Kontoverwaltung<br />

Abbildung 4: Asynchron in Zeit und Nachrichten “roh” komponierte Moore-Maschine für Bank.<br />

Abbildung 5 zeigt im zweiten Schritt die nachrichtensynchrone Reduktion der Moore-Maschine für Bank,<br />

wobei keine Nachrichtensynchronität mit dem Benutzer berücksichtigt ist. D.h. ohne Eingabepuffer verliert


Bank z.B. ungünstig kommende “aabbruch” Nachrichten. Entsprechende Transitionen und Zustände sind<br />

entfernt worden. Dies betrifft auch Zusammenhangskomponenten im ZÜD, die (von “Bereit/Bereit” aus) nicht<br />

mehr erreichbar sind. Man beachte, dass uns diese Transformation eine Verklemmungssituation herbeiführt.<br />

Die nötige <strong>zu</strong>sätzliche “i2prüfe”-Transition und deren Konsequenzen im Zustand “Prüfung” betrachten wir im<br />

Rahmen der Aufgabe nicht mehr. Schon hier könnte man bei allen nachrichtensynchronen Übergängen der beiden<br />

Maschinen die Kontroll<strong>zu</strong>stände (hier “Fernprüfung/Bereit” und “Fernprüfung/Einzahlung”) eliminieren, dies<br />

erfolgt aber erst im nächsten Schritt.<br />

Fernprüfung<br />

Prüfung<br />

{s[1..n] :=0}<br />

Bereit<br />

Einzahlung<br />

ahebeAb(x,id)<br />

i2!prüfe(x,id)<br />

Bereit<br />

Prüfung<br />

UP<br />

Bereit<br />

Bereit<br />

c<strong>zu</strong>rück<br />

c<strong>zu</strong>rück<br />

Bereit<br />

Einzahlung<br />

QT<br />

Fernprüfung<br />

Bereit<br />

i2!prüfe(x,id)<br />

i2prüfe(x,id)<br />

ahebeAb(x,id)<br />

-<br />

ZE<br />

d!ok<br />

ahebeAb(x,id)<br />

ahebeAb(x,id)<br />

-<br />

-<br />

Fernprüfung<br />

Prüfung<br />

i2prüfe(x,id)<br />

Fernprüfung<br />

Einzahlung<br />

VR<br />

i2!prüfe(x,id)<br />

OK<br />

Abhebung<br />

Bereit<br />

ZE<br />

Abhebung<br />

Einzahlung<br />

Abhebung<br />

Prüfung<br />

UP<br />

d!ok<br />

b!geld(x,id)<br />

c<strong>zu</strong>rück<br />

Bargeldbe<strong>zu</strong>g<br />

Kontoverwaltung<br />

Potentielle Verklemmung<br />

Abbildung 5: Nachrichtensynchrone Reduktion der Moore-Maschine für Bank.<br />

Abbildung 6 zeigt im dritten Schritt die Schnittstellenabstraktion der Moore-Maschine für Bank. Alle Kommunikation<br />

über i1 und i2 sowie interne Zuweisungen/Referenzen auf s werden eliminiert (leere Transitionen<br />

werden eliminiert; Zustände, welche keine nutzersichtbaren Ausgaben produzieren bzw. keine Nutzereingaben<br />

entgegen nehmen wurden verschmolzen: Unsichtbare Transitionen bzw. Leerschritte (nicht die mit der leeren<br />

Nachricht “–”) werden <strong>zu</strong> Schleifen (bei Hin- und Rücktransitionen) oder verschwinden (bei Transitionen in<br />

eine Richtung). Man beachte die nichtdeterministische Ausgabe “−; y!geld(x, id)” (der Strichpunkt ; vereinigt<br />

hier zwei Transitionen oder Ausgaben zwecks kompakterer Notation) im grünen Zustand sowie den nichtdeterministischen<br />

Übergang mit “−” von dort aus. Damit erhalten wir eine Spezifikation, die nach wie vor eine<br />

Verklemmung aber <strong>zu</strong>sätzlich noch mehr Verhalten <strong>zu</strong>lässt als die ursprüngliche Komposition. Teilaufgabe d)<br />

zeigt auf Basis von Strömen, wie eine solche Spezifikation wieder sinnvoll eingeschränkt werden kann, in dem<br />

<strong>zu</strong>sätzlich geforderte Verhaltenseigenschaften potentielle Spezifikationsänderungen nach sich ziehen. Alternativ<br />

<strong>zu</strong>r Teilaufgabe c) ist mit diesem Zustandsübergangsdiagramm auch die Struktur (∆ bank , Σ bank0 ) für die Bank<br />

gegeben.


Fernprüfung<br />

Prüfung<br />

Bereit<br />

Bereit<br />

xzahleEin(x,id)<br />

x<strong>zu</strong>rück<br />

Bargeldbe<strong>zu</strong>g<br />

Kontoverwaltung<br />

Potentielle Verklemmung<br />

Bereit<br />

Einzahlung<br />

-<br />

y!ok<br />

xhebeAb(x,id)<br />

xhebeAb(x,id)<br />

Bereit<br />

Prüfung<br />

UP<br />

xabbruch; -<br />

xhebeAb(x,id)<br />

"Fernprüfung|Abhebung"<br />

"Bereit|Prüfung|Einzahlung"<br />

-;<br />

y!geld(x,id)<br />

x<strong>zu</strong>rück<br />

Abhebung<br />

Bereit<br />

UP<br />

xzahleEin(x,id)<br />

Abhebung<br />

Einzahlung<br />

y!ok<br />

xhebeAb(x,id)<br />

-<br />

Bereit<br />

Einzahlung<br />

x<strong>zu</strong>rück<br />

Abbildung 6: Schnittstellenabstraktion der Moore-Maschine für Bank.<br />

Teilaufgabe c) Im Folgenden werden wir die beiden Komponenten Bargeldbe<strong>zu</strong>g und Kontoverwaltung als<br />

stromverarbeitende Funktionen darstellen. Wir beginnen damit die Menge der Kanäle für Bargeldbe<strong>zu</strong>g und<br />

Kontoverwaltung wie folgt <strong>zu</strong> definieren:<br />

• Bargeldbe<strong>zu</strong>g: I b = {a, i1}, O b = {b, i2}.<br />

• Kontoverwaltung: I k = {c, i2}, O k = {d, i1}.<br />

Nun können wir die syntaktischen Schnittstellen der beiden Teilsysteme wie folgt definieren:<br />

• Bargeldbe<strong>zu</strong>g: (I b ◮ O b ).<br />

• Kontoverwaltung: (I k ◮ O k ).<br />

Schließlich können wir die semantischen Schnittstellen der Systeme als Funktionen über die <strong>zu</strong>gehörigen syntaktischen<br />

Schnittstellen definieren. Beachten sie dass wir im Folgenden eine Historie als Sequenz von Belegungen<br />

behandeln. Eine Historie −→ I bzw. −→ O einer Komponente mit Schnittstelle (I ◮ O) ist somit eine Sequenz von<br />

funktionen der Art<br />

I → M bzw. O → M.<br />

Im Folgenden werden wir zwei verschiedene Techniken <strong>zu</strong>r rekursiven Definition von stromverarbeitenden Funktionen<br />

einsetzen:


• Direkte Definition über Ein-/Ausgabe: Die Funktion wird rekursiv über das Muster der Eingabebelegungen<br />

definiert.<br />

• Definition unter Verwendung lokaler Zustände: Die Funktion wird rekursiv über das Muster von Eingabebelegungen<br />

in Abhängigkeit einer weiteren Hilfsfunktion definiert. Die Hilfsfunktion repräsentiert eine<br />

Art Daten<strong>zu</strong>stand und wird verwendet um den Kontostand der Kunden <strong>zu</strong> kapseln.<br />

Im Folgenden werden wir die stromverarbeitende Funktion für die Komponente Bargeldbe<strong>zu</strong>g als Ein-/Ausgabe<br />

Funktion definieren. Das Schnittstellenverhalten f b : −→ I b → −→ O b ist dabei wie folgt definiert, wobei das Symbol<br />

ɛ für die leere Übertragung steht und i, i ′ , i ′′ sowie o, o ′ , o ′′ Kanalbelegungen darstellen und rest ∈ −→ I b und<br />

x, id ∈ N:<br />

f b (〈〉) = 〈〉 (1)<br />

i(a) = hebeab(x, id) ∧ i(i1) = ɛ<br />

⇒ f b (〈i〉) = 〈o〉 (2)<br />

∧o(i2) = prüfe(x, id) ∧ o(b) = ɛ<br />

i(a) = hebeab(x, id) ∧ i ′ (i1) = check(true, x, id) ∧ i(i1) = i ′ (a) = ɛ<br />

⇒ f b (〈i〉) = 〈o〉 (3)<br />

∧o(i2) = prüfe(x, id) ∧ o ′ (b) = geld(x, id) ∧ o(b) = o ′ (i2) = ɛ<br />

i(a) = hebeab(x, id) ∧ (i ′ (i1) = check(false, x, id) ∧ i ′ (a) = ɛ ∨ i ′ (a) = abbruch ∧ i ′ (i1) = ɛ) ∧ i(i1) = ɛ<br />

⇒ f b (〈i〉ˆ〈i ′ 〉ˆ〈rest〉) = 〈o〉ˆ〈o ′ 〉ˆf b (〈rest〉) (4)<br />

∧o(i2) = prüfe(x, id) ∧ o(b) = o ′ (b) = o ′ (i2) = ɛ<br />

i(a) = hebeab(x, id) ∧ i ′ (i1) = check(true, x, id) ∧ i(i1) = i ′ (a) = i ′′ (a) = i ′′ (i1) = ɛ<br />

⇒ f b (〈i〉ˆ〈i ′ 〉ˆ〈i ′′ 〉ˆ〈rest〉) = 〈o〉ˆ〈o ′ 〉ˆ〈o ′′ 〉ˆf b (〈rest〉) (5)<br />

∧o(i2) = prüfe(x, id) ∧ o ′ (b) = geld(x, id) ∧ o(b) = o ′ (i2) = o ′′ (b) = o ′′ (i2) = ɛ<br />

Beachten Sie dass f b Präfix-monoton ist, also i 1 ⊑ i 2 ⇒ f b (i 1 ) ⊑ f b (i 2 ) gilt. Dies ist notwendig um sicher<strong>zu</strong>stellen<br />

dass die Funktion auch realisierbar ist. Des weiteren ist <strong>zu</strong> beachten dass die Funktion partiell ist, dass<br />

also nicht jede Eingabehistorie eine Ausgabehistorie liefert.<br />

Um sicher<strong>zu</strong>stellen dass die so definierte Funktion in der Tat eine Abstraktion der Zustandsmaschinen aus<br />

Teilaufgabe a ist, also f b = Abs((∆ b , Σ b0 )) gilt, muss die Abstraktion folgender Bedingung (siehe Foliensatz<br />

6, Folie 25) genügen, wobei Abläufe eine Funktion ist welche alle möglichen Abläufe einer Zustandsmaschine<br />

liefert:<br />

Vermutung. f b (i) = o ⇔ ∃σ n ∈ Abläufe((∆ b , Σ b0 )). σ 0 ∈ Σ b0 ∧ ∀n ∈ N.(σ n+1 , o(n + 1)) = ∆(σ n , i(n + 1))<br />

Ohne Beweis.<br />

Analog da<strong>zu</strong> können wir die stromverarbeitende Funktion der Komponente Kontoverwaltung definieren. Hier<br />

werden wir die stromverarbeitende Funktion aber als Funktion mit lokalen Zuständen definieren. Der Zustand<br />

ist in diesem Fall das Guthaben eines jeden Kunden. Wir können das Schnittstellenverhalten der Komponente


f k : −→ I k → −→ O k dann einfach als f k = f h [nil] definieren, wobei f h : s → ( −→ I k → −→ O k ) eine Funktion ist, die das<br />

Schnittellenverhalten in Abhängigkeit eines Zustandes s : N → N festlegt, wobei s(id) den aktuellen Betrag<br />

eines Kunden mit Identifikation id liefert und nil : N → N die Funktion ist welche den Betrag 0 für jeden<br />

Kunden <strong>zu</strong>rückgibt, also nil(id) = 0 für alle Kunden id. Die Funktion f h wird wie folgt definiert, wobei das<br />

Symbol ɛ für die leere Übertragung steht und i, i ′ , i ′′ sowie o, o ′ , o ′′ Kanalbelegungen darstellen und rest ∈ −→ I k :<br />

f h [s](〈〉) = 〈〉 (1)<br />

i(c) = zahleEin(x, id) ∧ i(i2) = ɛ<br />

⇒ f h [s](〈i〉) = o (2)<br />

∧o(d) = ok ∧ o(i1) = ɛ<br />

i(c) = zahleEin(x, id) ∧ i ′ (i2) = prüfe(x, id) ∧ i(i2) = i ′ (c) = ɛ<br />

⇒ f h [s](〈i〉ˆ〈i ′ 〉) = 〈o〉ˆ〈o ′ 〉 (3)<br />

∧o(d) = ok ∧ o ′ (i1) = check(s(id) > x ∧ customerOk(id), x, id) ∧ o(i1) = o ′ (d) = ɛ<br />

i(i2) = prüfe(x, id) ∧ i(d) = ɛ<br />

⇒ f h [s](〈i〉) = 〈o〉 (4)<br />

∧o(i1) = check(s(id) > x ∧ customerOk(id), x, id) ∧ o(d) = ɛ<br />

i(c) = zahleEin(x, id) ∧ i ′ (c) = <strong>zu</strong>rück ∧ i(i2) = i ′ (i2) = ɛ<br />

⇒ f h [s](〈i〉ˆ〈i ′ 〉ˆ〈rest〉) = 〈o〉ˆ〈o ′ 〉ˆf k [s ′ ](〈rest〉) (5)<br />

{<br />

∧o(d) = ok ∧ o(i1) = o ′ (d) = o ′ (i1) = ɛ ∧ s ′ s(z) wenn z ≠ id<br />

(z) =<br />

s(z) + x sonst<br />

i(c) = zahleEin(x, id) ∧ i ′ (i2) = prüfe(x, id) ∧ i(i2) = i ′ (c) = i ′′ (c) = i ′′ (i2) = ɛ ∧ s(id) > x ∧ customerOk(id)<br />

⇒ f h [s](〈i〉ˆ〈i ′ 〉ˆ〈i ′′ 〉ˆ〈rest〉) = 〈o〉ˆ〈o ′ 〉ˆ〈o ′′ 〉ˆf k [s ′ ](〈rest〉) (6)<br />

∧o(d) = ok ∧ o ′ (i1) = check(s(id) > x ∧ customerOk(id), x, id) ∧ o(i1) = o ′ (d) = o ′′ (d) = o ′′ (i1) = ɛ<br />

{<br />

∧s ′ s(z) wenn z ≠ id ∨ s(id) ≤ x ∨ ¬customerOk(id)<br />

(z) =<br />

s(z) − x sonst<br />

Beachten Sie dass auch f k Präfix-monoton ist, also i 1 ⊑ i 2 ⇒ f k (i 1 ) ⊑ f k (i 2 ) gilt. Dies ist notwendig um<br />

sicher<strong>zu</strong>stellen dass die Funktion auch realisierbar ist. Des weiteren ist <strong>zu</strong> beachten dass die Funktion partiell<br />

ist, dass also nicht jede Eingabehistorie eine Ausgabehistorie liefert.<br />

Um sicher<strong>zu</strong>stellen dass die so definierte Funktion in der Tat eine Abstraktion der Zustandsmaschine aus<br />

Teilaufgabe a ist, also f k = Abs((∆ k , Σ k0 )) gilt, muss die Abstraktion wie schon <strong>zu</strong>vor folgender Bedingung<br />

genügen:<br />

Vermutung. f k (i) = o ⇔ ∃σ n ∈ Abläufe((∆ b , Σ k0 )). σ 0 ∈ Σ k0 ∧ ∀n ∈ N.(σ n+1 , o(n + 1)) = ∆(σ n , i(n + 1))<br />

Ohne Beweis.


Parallele Komposition der Funktionen: Es gibt nun verschiedene Möglichkeiten die Komposition<br />

der beiden stromverarbeitenden Funktionen <strong>zu</strong> definieren. Da wir die Komposition in Teilaufgabe b schon<br />

anhand der Zustandsmaschinen vorgenommen haben und wir wissen dass die Abstraktion durch Komposition<br />

distribuiert, also Abs((∆1, Σ1) ‖ (∆2, Σ2)) = Abs(∆1, Σ1) ⊗ Abs(∆2, Σ2) gilt (siehe Foliensatz 7, Folie 27),<br />

könnten wir einfach eine Funktion für die Zustandsmaschine aus Abbildung 6 angeben, genau so wie wir das<br />

schon <strong>zu</strong>vor für Bargeldbe<strong>zu</strong>g und Kontoverwaltung gemacht haben.<br />

Wir werden im Folgenden jedoch eine alternative Definition anbieten. Wir werden die Komposition der<br />

beiden Funktionen als kleinsten Fixpunkt des folgenden Gleichungssystems definieren. Zunächst definieren wir<br />

aber die Ein-/Ausgabekanäle des <strong>zu</strong>sammengesetzten Systems: I = (I b ∪ I k ) \ (O b ∪ O k ) = {a, i1} ∪ {c, i2} \<br />

{b, i2} ∪ {d, i1} = {a, c} und O = (O b ∪ O k ) \ (I b ∪ I k ) = {b, i2} ∪ {d, i1} \ {a, i1} ∪ {c, i2} = {b, d}. Die<br />

Menge L = (I b ∪ I k ) ∩ (O b ∪ O k ) = ({a, i1} ∪ {c, i2}) ∩ ({b, i2} ∪ {d, i1}) = {i1, i2} sind dabei die Menge<br />

der internen Kanäle des Systems. Die Schnittstelle des <strong>zu</strong>sammengesetzten Systems ist somit durch (I ◮ O)<br />

gegeben. Wir definieren nun eine Funktion f bank : −→ I → −→ O wobei f bank = f b ⊗ f k als kleinster Fixpunkt des<br />

folgenden Gleichungssystems definiert ist. Im Folgenden bezeichnet z | C ′ die Restriktion der Belegung z auf<br />

die Teilmenge C ′ ⊆ C.<br />

• f bank (z) | O b = f b (z | I b )<br />

• f bank (z) | O k = f k (z | I k )<br />

Da f b und f k Präfix-monoton sind und die Menge der stromverarbeitenden Funktionen <strong>zu</strong>sammen mit der<br />

Präfix-ordnung eine ketten vollständige Ordnung bilden, kann man nun zeigen dass der kleinste Fixpunkt<br />

dieses Systems auch wirklich existiert und eindeutig ist (Satz von Kleene). Dadurch ist also die Funktion f bank<br />

wohldefiniert und wir können sie als Definition verwenden.<br />

Die Komposition sollte übrigens wiederum folgender Eigenschaft genügen:<br />

Vermutung. f bank (i) = o ⇔ ∃σ n ∈ Abläufe((∆ bank , Σ bank0 )).σ 0 ∈ Σ bank0 ∧ ∀n ∈ N.(σ n+1 , o(n + 1)) =<br />

∆(σ n , i(n + 1))<br />

Ohne Beweis.<br />

Teilaufgabe d)<br />

Für beide Eigenschaften definieren wir nun eine Hilfsfunktion<br />

fct sum = (s : Stream) N : returnFirstPar(first(s)) + sum(rest(s))<br />

sum(〈〉) = 0<br />

wobei returnFirstPar(String) den ersten Parameterwert eines Terms <strong>zu</strong>rück gibt. So kann die Eigenschaft (1)<br />

wie folgt spezifiziert werden:<br />

Selbiges für die Eigenschaft (2):<br />

sum({zahleEin( , id)} ⊗ x, id) ≥ sum({geld( , id)} ⊗ y, id) (7)<br />

sum({zahleEin( , id)} ⊗ x, id) ≤ sum({geld( , id)} ⊗ y, id) (8)<br />

M ⊗ x filtert aus dem Strom x alle Nachrichten heraus, die nicht in der Nachrichtenmenge M sind.<br />

TODO: Prüfung anhand von Abbildung 6.<br />

Aufgabe 2 Stromverarbeitende Funktionen<br />

• Syntaktische und semantische Korrektheit von Strömen<br />

Sei M = {⊥, 0, 1, 2, . . .}. Seien x, y ∈ M \ {⊥} Elemente aus einem Strom und seien s, t ∈ M ω<br />

Ströme über M mit der Trägermenge M ω = (M \ {⊥}) ∗ ∪ (M \ {⊥}) ∞ und s ≠ 〈 〉. Geben Sie für<br />

die folgenden Terme an, ob diese syntaktisch und ggf. semantisch korrekt, also wahr oder falsch,<br />

sind:


(a) first(〈1, 2, 3〉) = 1<br />

(b) rest(〈1, 2, ⊥, 3, 4〉) = rest(〈1, 2〉)<br />

(c) sˆt = tˆs<br />

(d) first(sˆt) = first(s)<br />

(e) (xˆs)ˆt = xˆ(sˆt)<br />

(f) first(rest(first(〈1, 2, 3〉))) = ⊥<br />

(g) rest(rest(rest(x&(y&s)))) = rest(s)<br />

• Stromverarbeitende Funktionen<br />

(a) Spezifizieren Sie eine Komponente, die zwei sortierte (monotone) Eingabeströme natürlicher<br />

Zahlen vereint und als einen sortierten Ausgabestrom wieder ausgibt. Geben Sie da<strong>zu</strong> die<br />

Signatur und die Spezifikation dieser Komponente an.<br />

(b) Modellieren Sie nun eine realisierende Funktion Ihrer Spezifikation.<br />

(c) Modellieren Sie eine Komponente mit zwei Eingabekanälen und einem Ausgabenkanal, jeweils<br />

vom Typ Nat, die wiederholt die ersten zwei Zahlen von den Eingabeströmen multipliziert<br />

und das Ergebnis auf dem Ausgabestrom ausgibt.<br />

• Axiomatische Spezifikation stromverarbeitender Funktionen<br />

In dieser Aufgabe wollen wir stromverarbeitende Funktionen durch Schnittstellen<strong>zu</strong>sicherungen<br />

spezifizieren. Eine Warteschlange soll Daten vom Typ Data speichern und bei Eingabe des Zeichens<br />

∇ einen gespeicherten Wert nach dem FIFO Prinzip <strong>zu</strong>rückgeben. Beispielsweise soll bei einem<br />

Input<br />

〈1, 2, ∇, 4, ∇〉<br />

der Output<br />

berechnet werden.<br />

〈 , , 1, , 2〉<br />

Modellieren Sie die Komponente indem Sie Schnittstellen<strong>zu</strong>sicherungen angeben.


Lösung der Aufgabe 2<br />

Syntaktische und semantische Korrektheit von Strömen<br />

Diskussion: Syntax vs. Semantik<br />

(a) first(〈1, 2, 3〉) = 1<br />

Richtig<br />

(b) rest(〈1, 2, ⊥, 3, 4〉) = rest(〈1, 2〉)<br />

Richtig, da 1&2& ⊥ &3&4 = 〈1, 2〉<br />

⊥ schneidet den Strom ab. Man sieht das, wenn man den Strom auf Normalform (1&2& . . .)<br />

bringt, dann kann man Axiome der Vorlesung anwenden.<br />

(c) sˆt = tˆs<br />

Syntaktisch richtig, aber semantisch falsch. Konkatenation ist nicht kommutativ.<br />

(d) first(sˆt) = first(s)<br />

Richtig, da s nicht leer ist.<br />

(e) (xˆs)ˆt = xˆ(sˆt)<br />

Syntaktisch falsch, da x eine Nachricht ist und ˆ ist daher nicht anwendbar.<br />

Richtig wären: (x & s)ˆt = x & (sˆt) und (〈x〉ˆs)ˆt = 〈x〉ˆ(sˆt)<br />

(f) first(rest(first(〈1, 2, 3〉))) = ⊥<br />

Syntaktisch falsch, da first eine Nachricht <strong>zu</strong>rück gibt. rest ist dafür nicht definiert. Zusätzliche<br />

Diskussion ob es überhaupt Fälle geben kann, in denen es sinnvoll ist ⊥ in Axiomen<br />

<strong>zu</strong> verwenden. Ja, z.B. in rest(〈〉) =⊥.<br />

(g) rest(rest(rest(x&(y&s)))) = rest(s)<br />

Richtig<br />

Stromverarbeitende Funktionen<br />

• Aufgabe a)<br />

fct merge : Stream Nat, Stream Nat → Stream Nat<br />

sorted(a) ∧ sorted(b) ∧ c = merge(a, b)<br />

=⇒ sorted(c)<br />

∧ ∀i, j : a i ≤ b j ⇒ ∃k : c k = a i<br />

∧ ∀i, j : a i ≥ b j ⇒ ∃k : c k = b j<br />

∧ ∀k : ∃i: c k = a i ∨ c k = b i<br />

sorted(〈 〉)<br />

sorted(〈x〉)<br />

sorted(x&y&s) ⇐⇒ (x ≤ y ∧ sorted(y&s))


• Aufgabe b)<br />

fct merge = (a: Stream Nat, b: Stream Nat)Stream Nat:<br />

if a = 〈 〉 then b<br />

else if b = 〈 〉 then a<br />

else if first(a) ≤ first(b) then first(a)ˆmerge(rest(a), b)<br />

else first(b)ˆmerge(a, rest(b))<br />

• Aufgabe c)<br />

fct smult(s1, s2 : StreamNat)StreamNat :<br />

(first(s1) ∗ first(s2))&smult(rest(s1), rest(s2))<br />

Axiomatische Spezifikation stromverarbeitender Funktionen<br />

Zunächst können wir uns überlegen, wie eine stromverarbeitende Funktion für die Warteschlange aussehen<br />

könnte. Seien nun I = Data ∪ {▽} die Menge der Eingabesymbole und O = Data ∪ { } die Menge der<br />

Ausgabesymbole. Seien außerdem d ∈ Data, ds ∈ Stream Data, s ∈ Stream I. Wir charakterisieren die stromverarbeitende<br />

Funktion q durch:<br />

q(〈〉) = 〈〉<br />

q(〈d〉 ∧ ds ∧ 〈▽〉 ∧ s)) = 〈 〉 ∧ q(ds) ∧ 〈d〉 ∧ q(s)<br />

q(d&ds) = &q(ds)<br />

An der zweiten Gleichung sehen wir, dass immer wenn ein ▽ im Eingabestrom vorkommt, das erste Element<br />

auf den Ausgabestrom geschrieben wird. Die Anzahl der Datenelemente im Ausgabestrom ist also stets gleich<br />

der ▽ Elemente im Eingabestrom. Genauso ist die Anzahl der -Elemente im Ausgabestrom gleich der Anzahl<br />

der Datenelemente im Eingabestrom. Wir müssen außerdem noch sicherstellen, dass die richtigen Datenelemente<br />

in der richtigen Reihenfolge auf den Strom geschrieben werden.<br />

Wir formulieren die Schnittellen<strong>zu</strong>sicherung über den Eingabekanal i ∈ Stream I und den Ausgabekanal<br />

o ∈ Stream O. Seien außerdem x ∈ Stream I und y ∈ Stream O und n ∈ N.<br />

∀x, y : x ⊑ i ∧ y ⊑ o∧ ‖ x ‖=‖ y ‖⇒<br />

Data#y = {▽}#x<br />

∧ { }#y = Data#x<br />

Nun sollten wir diese Zusicherungen noch auf Eingaben einschränken, die wohlgeformt sind, also nie mehr<br />

▽ erhalten als Daten. Da<strong>zu</strong> definieren wir:<br />

valid(i) :⇔ ∀z : z ⊑ i ⇒ Data#z ≥ {▽}#z


Aufgabe 3 Programmieraufgabe: Synchronisation von Prozessen<br />

• Bäckerei-Problem<br />

Beim Betreten des Geschäfts erhält jeder Kunde eine Wartenummer. Der Kunde mit der kleinsten<br />

Nummer wird als nächster bedient. Da es keine Garantie gibt, dass zwei Kunden nicht die gleiche<br />

Wartenummer kriegen, wird im Falle zwei gleicher Nummern der Prozess (Kunde) mit dem<br />

kleinsten Namen als erster bedient. Das bedeutet, wenn P i und P j die gleiche Nummer erhalten<br />

und i < j, dann wird der Prozess P i als erstes bedient.<br />

– Schreiben Sie ein Programm in Pseudo-Code für das Backery-Problem.<br />

Hinweis: Da die Prozessnamen einzigartig und total geordnet sind, ist der Algorithmus<br />

komplett deterministisch.<br />

– Schreiben Sie ein Programm für das Backery-Problem, indem Sie binäre Semaphoren benutzen.<br />

– Optional: Schreiben Sie ein Programm in Java, dass den gleichen Sachverhalt umsetzt und<br />

vergleichen Sie die 2 Programme.<br />

• Das Philosophen-Problem<br />

Fünf Philosophen sitzen gemeinsam an einem runden Tisch, an dem sie unabhängig voneinander<br />

von Zeit <strong>zu</strong> Zeit essen. Jeder Philosoph hat rechts neben seinem Teller nur eine Gabel, benötigt<br />

aber <strong>zu</strong>m Essen zwei Gabeln, also auch die seines linken Nachbarn. Aus diesem Grund können nicht<br />

alle Philosophen gleichzeitig essen, sondern sie müssen sich bezüglich ihrer kritischen Abschnitte<br />

Essen synchronisieren.<br />

– Geben Sie eine Programmlösung unter Verwendung der P- und V-Operationen an, bei der es<br />

<strong>zu</strong> keinerlei Verklemmungen kommen kann.<br />

Hinweis:<br />

∗ Die Philosophen sollen als Prozesse modelliert werden<br />

∗ Jeder Philosoph kann sich in einem der folgende drei Zustände befinden (denkend, hungrig<br />

und essend)


Abbildung 7: Das Philosophen-Problem<br />

Lösung der Aufgabe 3<br />

Backery problem<br />

• Lösung a)<br />

var choosing : array [ 0 . . . n−1] o f boolean ;<br />

number : array [ 0 . . . n−1] o f i n t e g e r ;<br />

i n i t i a l i z e choosing to f a l s e and number to 0<br />

repeat<br />

choosing [ i ]:= true ;<br />

number [ i ]:= max( 0 , number [ 1 ] , . . . , number [ n−1])+1<br />

choosing [ i ]:= f a l s e ;<br />

f o r j :=0 to n−1<br />

do begin<br />

while choosing [ j ] do no−op<br />

while number [ j ]!=0 and ( number [ j ] , j ) < ( number [ i ] , i ) do no−op ;<br />

end ;<br />

c r i t i c a l s e c t i o n ;<br />

number [ i ] : = 0 ;<br />

remainder s e c t i o n<br />

u n t i l f a l s e ;


• Lösung b)<br />

semaphore mutex ;<br />

semaphore s e r v e ;<br />

semaphore s h a r e j ;<br />

number : array [ 0 . . . n−1] o f i n t e g e r ;<br />

repeat<br />

P( mutex ) ;<br />

number [ i ]:= max( 0 , number [ 1 ] , . . . , number [ n−1])+1;<br />

V( mutex ) ;<br />

P( s h a r e j ) ;<br />

f o r j :=0 to n−1<br />

do begin<br />

while number [ j ]!=0 and number [ j ]


– Wenn ein Philosoph essen will, versucht er die Gabeln <strong>zu</strong> beiden Seiten seines Tellers <strong>zu</strong> bekommen.<br />

Schat er es, kann er für eine Zeit lang essen. Ist er mit Essen fertig, legt er die Gabeln wieder auf<br />

den Tisch <strong>zu</strong>rück und denkt weiter nach.<br />

– Frage: Wie kann ein Programm aussehen, bei dem alle Philosophen immer mal wieder essen können<br />

und keiner am Tisch verhungert.<br />

• Lösungsansatz 1:<br />

Der naheliegendste Versuch ist, einen hungrigen Philosophen <strong>zu</strong>erst nach seiner linken Gabel greifen <strong>zu</strong><br />

lassen. Sobald er die linke Gabel hat, greift er nach der rechten Gabel. Das Problem bei einer solchen<br />

Vorgehensweise ist dass wenn alle Philosophen gleichzeitig ihre linke Gabel schnappen, kommt es <strong>zu</strong> einer<br />

Verklemmung, einem Deadlock, und es geht nicht weiter. Eine modizierte Version dieser Vorgehensweise<br />

ist, dass ein hungriger Philosoph <strong>zu</strong>erst seine linke Gabel nimmt und dann prüft, ob die rechte Gabel<br />

verfügbar ist. Ist dies der Fall, kann er sie nehmen. Wenn nicht, legt er seine linke Gabel wieder <strong>zu</strong>rück<br />

und wiederholt den Vorgang nach einer gewissen Zeit. Auch dieses Vorgehen kann <strong>zu</strong> einem Problem<br />

führen. Wenn alle Philosophen im Gleichtakt vorgehen, kommt es <strong>zu</strong> einem Lifelock.<br />

• Lösungsansatz 2:<br />

Bei einem Lifelock nimmt jeder Philosoph seine linke Gabel, stellt fest, dass die rechte Gabel nicht frei<br />

ist und legt die linke <strong>zu</strong>rück und so weiter. In einer solchen Situation laufen die Prozesse zwar, aber sie<br />

kommen nicht in ihrer Abarbeitung weiter. Man spricht hier auch vom Aushungern. Eine Möglichkeit,<br />

die <strong>zu</strong>mindest meistens funktioniert ist, dass die Philosophen eine nicht eine feste, sondern eine <strong>zu</strong>fällig<br />

lange Zeit warten, bis sie den Vorgang wiederholen. So ist die Möglichkeit eines Lifelock sehr gering, aber<br />

es kann dennoch zeitweise <strong>zu</strong> einem Aushungern kommen. Eine funktionierende Möglichkeit ist, dass man<br />

das Aufnehmen der Gabeln, Essen und Ablegen der Gabeln als kritischen Abschnitt ansehen und unter<br />

gegenseitigem Ausschluss ablaufen lässt. In diesem Fall darf immer nur ein Philosoph essen, obwohl die<br />

Bestecke für zwei gleichzeitig essende Philosophen reichen würden<br />

• Lösungsansatz 3:<br />

Eine Lösung, bei der immer zwei Philosophen essen können und weder Deadlocks noch Lifelocks entstehen<br />

können, ist wie folgt: In einem Feld wird verfolgt, ob ein Philosoph gerade nachdenkt, isst oder hungrig<br />

ist, also versucht die Gabeln <strong>zu</strong> bekommen. Ein Philosoph kann nur in den Zustand essen übergehen,<br />

wenn seine beiden Nachbarn gerade nicht am Essen sind. Es existiert pro Philosoph ein Semaphor, so<br />

dass hungrige Philosophen blockieren können, falls die benötigten Gabeln in Gebrauch sind. Erst gelangt<br />

ein hungriger Philosoph alleine in den kritischen Bereich. Er prüft, ob seine beiden Nachbarn essen. Falls<br />

ja, blockiert er solange. Falls nein, beginnt er <strong>zu</strong> essen und verlässt den kritischen Bereich. Ist er fertig<br />

mit Essen, muss er in den kritischen Bereich kommen, seinen Status auf nachdenken setzen, die Gabeln<br />

freigeben und den kritischen Bereich verlassen.<br />

#d e f i n e N 5 /∗ Number o f p h i l o s p h e r s ∗/<br />

#d e f i n e RIGHT( i ) ( ( ( i )+1) %N)<br />

#d e f i n e LEFT( i ) ( ( ( i )==N) 0 : ( i )+1)<br />

typedef enum { THINKING, HUNGRY, EATING } p h i l s t a t e ;<br />

p h i l s t a t e s t a t e [N ] ;<br />

semaphore mutex =1;<br />

semaphore s [N ] ; /∗ one per philosopher , a l l 0 ∗/<br />

void t e s t ( i n t i ) {<br />

i f ( s t a t e [ i ] == HUNGRY &&<br />

s t a t e [LEFT( i ) ] != EATING &&<br />

s t a t e [RIGHT( i ) ] != EATING ) { s t a t e [ i ] = EATING; V( s [ i ] ) ; }<br />

}


void g e t f o r k s ( i n t i ) {<br />

P( mutex ) ;<br />

s t a t e [ i ] = HUNGRY;<br />

t e s t ( i ) ;<br />

V( mutex ) ;<br />

P( s [ i ] ) ;<br />

}<br />

void p u t f o r k s ( i n t i ) {<br />

P( mutex ) ;<br />

s t a t e [ i ]= THINKING;<br />

t e s t (LEFT( i ) ) ;<br />

t e s t (RIGHT( i ) ) ;<br />

V( mutex ) ;<br />

}<br />

void p h i l o s o p h e r ( i n t p r o c e s s ) {<br />

while ( 1 ) {<br />

think ( ) ;<br />

g e t f o r k s ( p r o c e s s ) ;<br />

eat ( ) ;<br />

p u t f o r k s ( p r o c e s s ) ;<br />

}<br />

}<br />

Aufgabe 4 Gezeitete Ströme<br />

Sei M 1 = {reset}, M 2 = {alarm}, M = {alarm, reset} und n ∈ N + .<br />

(a) Geben Sie einen gezeiteten Strom s über M an, so dass ∀ x ∈ N 0 : (((x>0 ⇒ (s(x) enthält reset))∧<br />

(∀y ∈N + : x < y ≤ x + n ⇒ (s(y) enthält reset nicht))) ⇒ (s(x + n) enthält alarm)).<br />

(b) Geben Sie timeabs(s) an.<br />

(c) Seien I = {r} mit type(r) = M 1 die Eingabekanalmenge, O = {a} mit type(a) = M 2 die Ausgabekanalmenge.<br />

i) Geben Sie eine Funktion f : ⃗ I → ⃗ O, die<br />

i. zeitunabhängig bzw.<br />

ii. nicht zeitunabhängig<br />

ist und die folgende Schnittstellen<strong>zu</strong>sicherung erfüllt:<br />

∀ x ∈ N 0 : (((x > 0 ⇒ (r(x) enthält reset)) ∧ (∀ y ∈ N + : x < y ≤ x + n ⇒<br />

(r(y) enthält reset nicht))) ⇒ (a(x + n) enthält alarm)).<br />

ii) Für eine zeitunabhängige Funktion f wie oben geben Sie die Zeitabstraktion an.<br />

iii) Erfülle eine Funktion g : ⃗ I → ⃗ O nun die folgende Schnittstellen<strong>zu</strong>sicherung:<br />

∀ x ∈ N 0 : (((x > 0 ⇒ (r(x) enthält reset)) ∧ (∀ y ∈ N + : x < y ≤ x + n ⇒<br />

(r(y) enthält reset nicht))) ⇐⇒ (a(x + n) enthält alarm)).<br />

Kann g zeitunabhängig bzw. nicht zeitunabhängig sein und warum<br />

Lösung der Aufgabe 4<br />

(a) Ein trivialer Strom ist s = λx ∈ N + . 〈alarm〉.<br />

Ein weniger trivialer Strom ist s ′ = λx ∈ N + .<br />

{<br />

〈alarm reset〉 , wenn x ≡ 0 mod n ,<br />

ɛ ,<br />

sonst.


(b) timeabs(s) = 〈alarm alarm alarm . . .〉 und timeabs(s ′ ) = 〈alarm reset alarm reset alarm reset . . .〉.<br />

(c) i) • f = λs∈I. ⃗ λa∈O. λx∈N + . 〈alarm〉.<br />

⎧<br />

Diese Funktion ( ist konstant, insbesondere zeitunabhängig. )<br />

⎪⎨<br />

(s(r)(1) enthält reset) ∨<br />

• f = λs∈I. ⃗ 〈alarm〉 , wenn<br />

,<br />

λa∈O. λx∈N + .<br />

(x>n ∧ (s(r)(x − n) enthält reset))<br />

⎪⎩<br />

ɛ , sonst.<br />

ist nicht zeitunabhängig. { Denn betrachte zwei Belegungen von I<br />

〈reset〉 , wenn x=1 ,<br />

s 1 = λr ∈I. λx∈N + .<br />

ɛ , sonst<br />

und<br />

{<br />

〈reset〉 , wenn x=2 ,<br />

s 2 = λr ∈I. λx∈N + .<br />

ɛ , sonst.<br />

Es gilt timeabs(s 1 )(r) = 〈reset〉 = timeabs(s 2 )(r). Aber<br />

f(s 1 ) = λa∈O. λx∈N + . 〈alarm〉 { und<br />

〈alarm〉 , wenn x=n+2 ,<br />

f(s 2 ) = λa∈O. λx∈N + .<br />

ɛ , sonst ,<br />

also timeabs(f(s 1 )(a)) = alarm ∞ ≠ 〈alarm〉 = timeabs(f(s 2 )(a)).<br />

ii) Zum Beispiel λx ∈ M ω . λy ∈N + . 〈alarm〉 oder λx ∈ M ω . λy ∈{1, 2}. 〈alarm〉.<br />

iii) Wir zeigen, dass so ein { g immer nicht zeitunabhängig ist. Seien<br />

〈reset〉 , wenn x ≡ 0 mod (n+1) ,<br />

t 1 = λr ∈I. λx∈N + .<br />

ɛ , sonst.<br />

und<br />

t 2 = λr ∈I. λx∈N + . 〈reset〉.<br />

Dann timeabs(t 1 (r)) = reset ∞ = timeabs(t 2 (r)). Nun gibt es gibt eine Funktion h: N + → N 0 , so<br />

dass<br />

{<br />

〈alarm h(x) 〉 , wenn x ≡ n mod (n + 1) ,<br />

g(t 1 )(a) = λx∈N + .<br />

ɛ ,<br />

sonst,<br />

timeabs(g(t 1 )(a)) = alarm ∞ ,<br />

g(t 2 )(a) = λx∈N + . ɛ und<br />

timeabs(g(t 2 )(a)) = ɛ. Also<br />

timeabs(g(t 1 )(a)) ≠ timeabs(g(t 2 )(a)).<br />

Ein Beispiel einer solchen Abbildung<br />

⎧<br />

ist (<br />

)<br />

⎪⎨<br />

(x=n ∨ (x>n ∧ (s(r)(x−n) enthält reset))) ∧<br />

g = λs∈I. ⃗ 〈alarm〉 , wenn<br />

,<br />

λa∈O. λx∈N + .<br />

(∀y ∈ N + ∩ (x − n, x]: s(r)(y) enthält reset nicht)<br />

⎪⎩<br />

ɛ , sonst.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!