Formele methoden

Formele methoden Formele methoden

12.07.2015 Views

Inhoudsopgave1 Predikaten 31.1 Toestandsruimte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Logische operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 Equivalentie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4 Predikatenrekening . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.5 De regel van Leibniz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.6 Afleidingen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.7 Implicatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.8 Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Operatoren 152.1 Conditionele expressies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.2 De minimumoperator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.3 Geheeltallige deling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Quantoren 253.1 Sommatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253.2 Logische quantificatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283.3 Minima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313.4 Tellende quantificatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 Specificaties 354.1 Hoare-tripels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354.2 Rekenregels voor Hoare-tripels . . . . . . . . . . . . . . . . . . . . . . . . . . . 364.3 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.4 Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384.5 Specificatievariabelen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 Programma’s 415.1 Toekenning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415.2 Sequentiële compositie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495.3 Selectie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525.4 Repetitie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581

Inhoudsopgave1 Predikaten 31.1 Toestandsruimte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Logische operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.3 Equivalentie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4 Predikatenrekening . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.5 De regel van Leibniz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.6 Afleidingen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.7 Implicatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.8 Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Operatoren 152.1 Conditionele expressies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.2 De minimumoperator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.3 Geheeltallige deling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Quantoren 253.1 Sommatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253.2 Logische quantificatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283.3 Minima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313.4 Tellende quantificatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 Specificaties 354.1 Hoare-tripels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354.2 Rekenregels voor Hoare-tripels . . . . . . . . . . . . . . . . . . . . . . . . . . . 364.3 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.4 Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384.5 Specificatievariabelen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395 Programma’s 415.1 Toekenning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415.2 Sequentiële compositie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495.3 Selectie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525.4 Repetitie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581


4 HOOFDSTUK 1. PREDIKATEN1.2 Logische operatorenVoor predikaten P en Q definiëren we een nieuw predikaat, dat we aangeven met P ∧Q (spreekuit: ‘P en Q’) en de conjunctie van P en Q noemen. De definitie luidt als volgt: P ∧Q heeftde waarde true in elke toestand waarin P en Q beide de waarde true hebben; P ∧ Q heeftde waarde false in alle andere toestanden. In termen van gekarakteriseerde deelverzamelingenvan de toestandsruimte correspondeert de operator ∧ dus met het nemen van de doorsnede.Het predikaat P ∨ Q (spreek uit: ‘P of Q’) heet de disjunctie van P en Q en is als volgtgedefinieerd: P ∨ Q heeft de waarde true in elke toestand waarin ten minste één van beidepredikaten de waarde true heeft; P ∨ Q heeft de waarde false in alle andere toestanden. Intermen van deelverzamelingen komt dit neer op het nemen van de vereniging.Het predikaat ¬P (spreek uit: ‘non P ’) heet de negatie van P en heeft de waarde truewaar P de waarde false heeft en omgekeerd. In termen van deelverzameling komt dit neer ophet complement. De operator ¬ bindt sterker dan ∧ en ∨, dus ¬P ∨ Q betekent (¬P ) ∨ Q.De definities van ∧, ∨ en ¬ zijn in tabelvorm als volgt weer te geven:1.3 EquivalentieP Q P ∧ Q P ∨ Q ¬Ptrue true true true falsetrue false false true falsefalse true false true truefalse false false false trueIn het voorgaande is al opgemerkt dat twee predikaten die in elke toestand dezelfde waardehebben, door ons als gelijk worden beschouwd. De bewering dat predikaten P en Q gelijkzijn, noteren we als P ≡ Q (spreek uit: ‘P is equivalent met Q’). Voor de gelijkheid vanpredikaten gebruiken we niet het gewone gelijkheidsteken, onder andere omdat dat laatstebinnen predikaten veel voorkomt. Zo kunnen we nu zonder haakjes opschrijven a = b ≡a + 1 = b + 1. In de wiskunde wordt om dezelfde reden meestal het symbool ⇐⇒ voorequivalentie gebruikt.Let er goed op dat overal in dit dictaat ≡ wordt gebruikt om een uitspraak te doen overhet verband tussen twee predikaten en niet voor het construeren van een nieuw predikaat,zoals de logische operatoren uit de vorige paragraaf wel doen.1.4 PredikatenrekeningDe predikatenrekening is het geheel van rekenregels voor de logische operatoren. Stellingenuit de predikatenrekening spreken vaak de equivalentie van twee formules uit. Een eenvoudigvoorbeeld is de regel¬false ≡ true ,die zo eenvoudig is dat we er geen naam aan geven en de regel steeds stilzwijgend gebruiken.We geven nu een overzicht van de belangrijkste regels uit de predikatenrekening. In alleregels stellen P , Q en R willekeurige predikaten voor. De juistheid van de regels is gemakkelijkte verifiëren door gevallenonderscheid.


1.4. PREDIKATENREKENING 5• Associativiteit:(P ∧ Q) ∧ R ≡ P ∧ (Q ∧ R) ,(P ∨ Q) ∨ R ≡ P ∨ (Q ∨ R) .Een gevolg van deze regel is dat we zonder haakjes P ∧ Q ∧ R kunnen schrijven en geengevaar lopen dat daardoor een dubbelzinnigheid ontstaat. In bewijzen zullen we datmeestal stilzwijgend doen en niet meer expliciet naar de regel Associativiteit verwijzen.• Symmetrie:P ∧ Q ≡ Q ∧ P ,P ∨ Q ≡ Q ∨ P .Symmetrie is de eigenschap die in de algebra gewoonlijk commutativiteit wordt genoemd.Ook naar de regel Symmetrie zullen we gewoonlijk niet expliciet verwijzen. Voor alle nunog volgende regels doen we dat gewoonlijk wel.• Idempotentie:P ∧ P ≡ P ,P ∨ P ≡ P .• Involutie:¬(¬P ) ≡ P .• Distributie:P ∧ (Q ∨ R) ≡ (P ∧ Q) ∨ (P ∧ R) ,P ∨ (Q ∧ R) ≡ (P ∨ Q) ∧ (P ∨ R) .• Wetten van de Morgan:¬(P ∧ Q) ≡ ¬P ∨ ¬Q ,¬(P ∨ Q) ≡ ¬P ∧ ¬Q .Deze wetten zijn ontdekt door en genoemd naar Augustus de Morgan (1806–1871).• Eenheidselement:P ∧ true ≡ P ,P ∨ false ≡ P .


6 HOOFDSTUK 1. PREDIKATEN• Nulelement:P ∧ false ≡ false ,P ∨ true ≡ true .• Uitgesloten tegenspraak:P ∧ ¬P ≡ false .• Uitgesloten derde:P ∨ ¬P ≡ true .In bewijzen wordt een beroep op een van deze stellingen gewoonlijk genoteerd door tussenaccolades, in een zogenaamde hint, de naam van de gebruikte regel te vermelden. Zo zou eenbewijsstap eruit kunnen zien als≡(X ∨ Y ) ∧ ¬(X ∨ Y ){Uitgesloten tegenspraak}false .Dat de regel wordt toegepast met X ∨ Y in de rol van het (willekeurige) predikaat P , wordtmeestal niet vermeld.1.5 De regel van LeibnizIn deze paragraaf spreken we over functies. Toepassing van een functie f op een argumentx zullen we noteren als f.x, in plaats van de klassieke notatie f(x). Bij functies van tweevariabelen schrijven we f.x.y in plaats van f(x, y). Het geringere aantal haakjes verbetert deleesbaarheid van onze formules.In het bijzonder zullen we functies definiëren op predikaten. Gewoonlijk doet men dat doorgebruik te maken van een voorstelling in formulevorm van de predikaten. We moeten echterrekening houden met de afspraak dat we predikaten als gelijk beschouwen als ze overal dezelfdewaarde hebben, ook al worden ze door verschillende formules weergegeven. Voor predikatendie in deze zin gelijk zijn, moeten de functiewaarden overeenstemmen. Dit wordt uitgedruktin de volgende regel (genoemd naar Gottfried Wilhelm Leibniz, 1646–1716):• Regel van Leibniz: Zij f een functie van predikaten naar predikaten. Voor elk tweetalpredikaten P, Q met P ≡ Q geldt dan f.P ≡ f.Q .Voorbeeld 1.1 Men kan een functie f van formules naar formules definiëren door af tespreken dat f.P gelijk is aan P als het aantal conjunctiesymbolen in P even is, en aan ¬Panders. Deze f kan niet opgevat worden als een functie van predikaten naar predikaten,omdat eenzelfde predikaat zowel kan worden beschreven door middel van een formule meteen even aantal conjunctiesymbolen als door middel van een formule met een oneven aantalconjunctiesymbolen (een voorbeeld wordt geleverd door de wetten van de Morgan). Opvattenvan f als een formule van predikaten naar predikaten kan alleen als f voldoet aan de regelvan Leibniz.□


1.6. AFLEIDINGEN 7Alle functies die zijn gedefinieerd via een expressie opgebouwd met logische operatoren voldoenaan de regel van Leibniz.Een toepassing van de regel van Leibniz is de volgende: in een expressie opgebouwd metlogische operatoren kan elke subformule worden vervangen door een daarmee equivalente. Zogeldt ¬(¬P ) ≡ P volgens de regel Involutie; door Leibniz toe te passen op de functie f ,gedefinieerd door f.X ≡ Q ∧ X , bereiken we de conclusieQ ∧ ¬(¬P ) ≡ Q ∧ P .In een bewijs geven we deze redenering gewoonlijk als volgt weer:≡Q ∧ ¬(¬P ){Involutie}Q ∧ P .Het beroep op de regel van Leibniz wordt daarbij niet expliciet vermeld.1.6 AfleidingenUit de definitie van equivalentie volgt de volgende regel:• Transitiviteit: voor predikaten P, Q, R met P ≡ Q en Q ≡ R geldt tevensP ≡ R.Een gevolg hiervan is dat we kunnen bewijzen dat P ≡ R geldt door afzonderlijk te beargumenterendat P ≡ Q en Q ≡ R gelden, en daarna een beroep te doen op Transitiviteit.Deze redenering zullen we typografisch als volgt weergeven:≡≡PQR .{argument waarom P ≡ Q geldt}{argument waarom Q ≡ R geldt}Het beroep op Transitiviteit geschiedt stilzwijgend. Door herhaaldelijk Transitiviteit te gebruiken,ontstaan bewijzen met meer dan twee stappen waarin een predikaat met behoud vanequivalentie geleidelijk in een ander wordt getransformeerd. Een dergelijk bewijs noemen weeen afleiding.Voorbeeld 1.2 Te bewijzen is de stelling dat voor predikaten P, Q geldtP ∧ Q ≡ P ∧ (¬P ∨ Q) .Door middel van een afleiding transformeren we het rechterlid in het linker:≡≡≡□P ∧ (¬P ∨ Q){Distributie}(P ∧ ¬P ) ∨ (P ∧ Q){Uitgesloten tegenspraak}false ∨ (P ∧ Q){Eenheidselement}P ∧ Q .


8 HOOFDSTUK 1. PREDIKATENOpmerking Bij het ontwerpen van een afleiding is het in het algemeen aan te raden tebeginnen bij die kant van de te bewijzen equivalentie die de ingewikkeldste formule bevat. Gana dat de afleiding in bovenstaand voorbeeld in de tegenovergestelde richting veel moeilijkerte vinden was geweest. Dit komt doordat we bij het vereenvoudigen van een formule mindervrijheid hebben dan bij het compliceren ervan.□Opgave 1.3 Bewijs door middel van een afleiding dat voor willekeurige predikaten P, Q, Rgeldt□(a) P ≡ (P ∧ Q) ∨ (P ∧ ¬Q) ,(b) P ∨ (Q ∨ R) ≡ (P ∨ Q) ∨ (P ∨ R) ,(c) P ∨ (¬P ∧ Q) ≡ P ∨ Q ,(d) P ∨ (P ∧ Q) ≡ P ,(e) P ∧ (P ∨ Q) ≡ P .Opgave 1.4 Bewijs door middel van een afleiding dat voor willekeurige predikaten P, Q, Rgeldt□(a) (¬P ∨ Q) ∧ (P ∨ R) ≡ (P ∧ Q) ∨ (¬P ∧ R) ,(b) (¬P ∨ Q) ∧ (¬Q ∨ R) ∧ P ∧ ¬R ≡ false ,(c) ¬P ∨ Q ∨ ((P ∨ Q) ∧ (¬P ∨ ¬Q)) ≡ true ,(d) (P ∧ Q) ∨ (Q ∧ R) ∨ (R ∧ P ) ≡ (P ∨ Q) ∧ (Q ∨ R) ∧ (R ∨ P ) .1.7 ImplicatieVoor predikaten P en Q geven we met P ⇒ Q (spreek uit: ‘P impliceert Q’) de volgendebewering aan: in elke toestand waarin P de waarde true heeft, heeft ook Q de waarde true.Anders gezegd: de door P gekarakteriseerde deelverzameling van de toestandsruimte is bevatin de door Q gekarakteriseerde deelverzameling van de toestandsruimte. In de door a en bopgespannen toestandsruimte uit §1.1 geldt bijvoorbeeld de implicatiea > b ⇒ a ≥ b .Als P ⇒ Q geldt en P verschilt van Q, zeggen we dat P sterker is dan Q (en dat Q zwakkeris dan P ). Sterke predikaten karakteriseren kleine deelverzamelingen van de toestandsruimte.In plaats van P ⇒ Q kunnen we ook Q ⇐ P schrijven.We behandelen nu een aantal regels uit de predikatenrekening die op implicatie betrekkinghebben. In alle regels stellen P , Q en R willekeurige predikaten voor. De juistheid van deregels is gemakkelijk te verifiëren door gevallenonderscheid.


1.7. IMPLICATIE 9• Transitiviteit: uit P ⇒ Q en Q ⇒ R volgt P ⇒ R.Een gevolg van deze regel is dat we implicaties kunnen bewijzen door middel van eenafleiding, precies zoals we dat met equivalenties in de vorige paragraaf deden. We demonstrerendit in Voorbeeld 1.5 hieronder.• Wederzijdse implicatie:Q ⇒ P gelden.P ≡ Q geldt dan en slechts dan als zowel P ⇒ Q als• Extrema:false ⇒ P ,P ⇒ true .Met andere woorden: false is het sterkste predikaat, en true is het zwakste.• Verzwakking:P ∧ Q ⇒ P ,P ⇒ P ∨ Q .Deze regels geven de mogelijkheid in het bewijs van een implicatie een formule te vereenvoudigendoor weglating van termen.• Monotonie: als P ⇒ Q, danP ∧ R ⇒ Q ∧ R ,P ∨ R ⇒ Q ∨ R .Deze regels worden, net als de regel van Leibniz, gebruikt voor het vervangen vansubformules. Net als bij Leibniz geschiedt het gebruik meestal stilzwijgend. Zie detweede en vijfde bewijsstap in Voorbeeld 1.5 hieronder.• Contrapositie: P ⇒ Q geldt dan en slechts dan als ¬Q ⇒ ¬P geldt.Het gebruik komt overeen met Monotonie, maar leidt tot omkering van het implicatieteken.• Absorptie: P ⇒ Q geldt dan en slechts dan als P ∧ Q ≡ P geldt.Deze regel kan ook worden gezien als een definitie van implicatie in termen van equivalentie.Onder andere stelt hij ons in staat reeds bewezen implicaties te gebruiken in hetbewijs van een equivalentie. Zie Voorbeeld 1.7 hieronder.• Shunting: P ⇒ Q geldt dan en slechts dan als ¬P ∨ Q ≡ true geldt.De naam van de regel stelt ons in staat de term Q naar de andere kant van het relatietekente verhuizen, vandaar de naam. Een toepassing volgt in Voorbeeld 1.9 hieronder.Voorbeeld 1.5 Te bewijzen is de stelling dat voor predikaten P, Q, X, Y geldt(¬P ∨ Q) ∧ (¬X ∨ Y ) ⇒ (¬P ∧ ¬X) ∨ (P ∧ Q) ∨ (X ∧ Y ) .


10 HOOFDSTUK 1. PREDIKATENWe schrijven een afleiding, waarbij we beginnen bij het rechterlid: dat is immers een ingewikkelderformule dan het linkerlid. Met de regels die we nu hebben, is nog slechts eentamelijk ingewikkeld bewijs te geven; een eenvoudiger afleiding zal worden gedemonstreerd inVoorbeeld 1.9 hieronder.≡⇐≡≡⇐≡□(¬P ∧ ¬X) ∨ (P ∧ Q) ∨ (X ∧ Y ){Distributie}((¬P ∨ P ) ∧ (¬P ∨ Q) ∧ (¬X ∨ (P ∧ Q))) ∨ (X ∧ Y ){Uitgesloten derde ‖ Verzwakking}(true ∧ (¬P ∨ Q) ∧ ¬X) ∨ (X ∧ Y ){Eenheidselement}((¬P ∨ Q) ∧ ¬X) ∨ (X ∧ Y ){Distributie}(¬P ∨ Q ∨ (X ∧ Y )) ∧ (¬X ∨ X) ∧ (¬X ∨ Y ){Verzwakking ‖ Uitgesloten derde}(¬P ∨ Q) ∧ true ∧ (¬X ∨ Y ){Eenheidselement}(¬P ∨ Q) ∧ (¬X ∨ Y ) .Opmerking Voor de conclusie hebben we alleen nodig dat elke regel van het bewijs wordtgeïmpliceerd door de eropvolgende. Dat is, dankzij Wederzijdse implicatie, in het bijzonderhet geval als beide regels equivalent zijn. Het is gebruikelijk in dat laatste geval ≡ in plaatsvan ⇐ te schrijven, om zo duidelijk te maken waar in het bewijs de echte versterking optreedt.□Opmerking Het bespaart schrijfwerk als we toestaan dat verschillende niet-overlappendesubformules in dezelfde afleidingsstap worden getransformeerd. In plaats van⇐⇐P ∧ X{argument waarom P ⇐ Q geldt}Q ∧ X{argument waarom X ⇐ Y geldt}Q ∧ Yschrijven we dan⇐P ∧ X{argument waarom P ⇐ Q geldt ‖ argument waarom X ⇐ Y geldt}Q ∧ Y .In bovenstaand voorbeeld zien we twee toepassingen van deze techniek.□Opgave 1.6 Bewijs door middel van een afleiding dat voor willekeurige predikaten P, Q, R, X, Ygeldt(a) (P ∨ Q ∨ R) ∧ (¬P ∨ X) ∧ (¬Q ∨ X) ∧ (¬R ∨ X) ⇒ X ,(b) (¬P ∨ Q) ∧ (¬X ∨ Y ) ⇒ ¬(P ∨ X) ∨ (Q ∨ Y ) ,(c) P ∧ (¬P ∨ Q) ∧ ¬Q ⇒ Q .


14 HOOFDSTUK 1. PREDIKATEN


16 HOOFDSTUK 2. OPERATORENf.X≡ {P }f.(P ? X : Y )]| .Dat de equivalentie ook geldt onder aanname van ¬P , volgt uit overwegingen van symmetrie.□Naar deze stelling zal in afleidingen worden verwezen met de hint ‘Eliminatie van ?’.Voorbeeld 2.2 De absolute waarde |x| van een getal x is gedefinieerd door|x| = (x ≥ 0 ? x : −x) .We bewijzen nu dat voor alle x geldt x ≤ |x|.x ≤ |x|≡ {definitie van absolute waarde}x ≤ (x ≥ 0 ? x : −x)≡ {Eliminatie van ?}(x ≥ 0 ∧ x ≤ x) ∨ (¬(x ≥ 0) ∧ x ≤ −x)≡ {x ≤ x ≡ true ‖ x ≤ −x ≡ x ≤ 0}(x ≥ 0 ∧ true) ∨ (¬(x ≥ 0) ∧ x ≤ 0)≡ {Eenheidselement ‖ Absorptie, met ¬(x ≥ 0) ⇒ x ≤ 0}x ≥ 0 ∨ ¬(x ≥ 0)≡ {Uitgesloten derde}true .□2.2 De minimumoperatorDefinitie 2.3 Het minimum x ↓ y van getallen x en y is gedefinieerd doorx ↓ y = (x ≤ y ? x : y) .□We spreken af dat ↓ sterker bindt dan de rekenkundige operatoren; dus x ∗ y ↓ z betekentx ∗ (y ↓ z) en niet (x ∗ y) ↓ z .Stelling 2.4 Voor alle x, y geldt x ↓ y ≤ x ∧ x ↓ y ≤ y .Bewijsx ↓ y ≤ x ∧ x ↓ y ≤ y≡ {definitie van ↓}(x ≤ y ? x : y) ≤ x ∧ (x ≤ y ? x : y) ≤ y≡ {Eliminatie van ? (toegepast op f.m ≡ m ≤ x ∧ m ≤ y )}


18 HOOFDSTUK 2. OPERATORENBewijsx ↓ y ≤ z≡ {definitie van ↓}(x ≤ y ? x : y) ≤ z≡ {Eliminatie van ?}(x ≤ y ∧ x ≤ z) ∨ (¬(x ≤ y) ∧ y ≤ z)⇒ {Verzwakking}x ≤ z ∨ y ≤ z⇒ {transitiviteit van ≤, met Stelling 2.4}x ↓ y ≤ zenz ≤ x ↓ y≡ {definitie van ↓}z ≤ (x ≤ y ? x : y)≡ {Eliminatie van ?}(x ≤ y ∧ z ≤ x) ∨ (¬(x ≤ y) ∧ z ≤ y)≡ {transitiviteit van ≤, met ¬(x ≤ y) ⇒ y ≤ x}(x ≤ y ∧ z ≤ x ∧ z ≤ y) ∨ (¬(x ≤ y) ∧ z ≤ x ∧ z ≤ y)≡ {Distributie}(x ≤ y ∨ ¬(x ≤ y)) ∧ z ≤ x ∧ z ≤ y≡ {Uitgesloten derde}true ∧ z ≤ x ∧ z ≤ y≡ {Eenheidselement}z ≤ x ∧ z ≤ y .□Opmerking De eerste helft van bovenstaand bewijs heeft een structuur die we symbolischweergeven als⇒⇒PQP .{argument waarom P ⇒ Q geldt}{argument waarom Q ⇒ P geldt}Dankzij Wederzijdse implicatie kunnen we hieruit de conclusie trekken dat P ≡ Q geldt.Om, speciaal wanneer het bewijs van de implicaties veel stappen telt, snel duidelijk te makenwelke conclusie wordt nagestreefd, omkaderen we de formule waarvan we de equivalentiemet de eerste en laatste regel van de afleiding wilden aantonen. Zo’n bewijs wordt wel eenpingpongbewijs genoemd.□Stelling 2.6 geeft informatie over het herschrijven van ongelijkheden waarin ↓ optreedt. Wezouden ook een dergelijke regel voor het herschrijven van gelijkheden kunnen opstellen, maardie zou een aanmerkelijk gecompliceerder rechterlid hebben. In plaats daarvan maken wegebruik van het principe


2.2. DE MINIMUMOPERATOR 19• Indirecte gelijkheid: x = y dan en slechts dan als voor alle m geldtm ≤ x ≡ m ≤ y .(De juistheid van ‘dan’ is in te zien door voor m respectievelijk x en y te kiezen.)We geven nu het bewijs van de commutativiteit van ↓.Stelling 2.7 Voor alle x, y geldtx ↓ y = y ↓ x .Bewijs Voor alle m geldtm ≤ x ↓ y≡ {Stelling 2.6}m ≤ x ∧ m ≤ y .Omdat de laatste regel invariant is onder verwisseling van x en y , is de eerste het ook.□Ook de associativiteit kan op deze wijze eenvoudig worden bewezen:Stelling 2.8 Voor alle x, y, z geldt(x ↓ y) ↓ z = x ↓ (y ↓ z) .Bewijs Voor alle m geldtm ≤ (x ↓ y) ↓ z≡ {Stelling 2.6}m ≤ x ↓ y ∧ m ≤ z≡ {Stelling 2.6}m ≤ x ∧ m ≤ y ∧ m ≤ z .Omdat de laatste regel invariant is onder cyclische verwisseling van x, y, z , is de eerste hetook. Dit levert(x ↓ y) ↓ z = (y ↓ z) ↓ x .De stelling volgt nu uit de al bewezen commutativiteit van ↓.□We tonen vervolgens aan dat optelling distribueert over ↓.Stelling 2.9 Voor alle x, y, z geldt(x + z) ↓ (y + z) = x ↓ y + z .Bewijs Voor alle m geldt


20 HOOFDSTUK 2. OPERATORENm ≤ (x + z) ↓ (y + z)≡ {Stelling 2.6}m ≤ x + z ∧ m ≤ y + z≡ {rekenen}m − z ≤ x ∧ m − z ≤ y≡ {Stelling 2.6}m − z ≤ x ↓ y≡ {rekenen}m ≤ x ↓ y + z .□Opgave 2.10 (a) Bewijs stelling 2.7 rechtstreeks uit de definitie van ↓.(b) Bewijs dat voor alle x, y, z geldtz = x ↓ y ≡ (z = x ∨ z = y) ∧ z ≤ x ∧ z ≤ y .□(c) Bewijs stelling 2.7 met behulp van (b).Naast de in deze paragraaf behandelde minimumoperator ↓ is er ook een maximumoperator↑, gedefinieerd doorx ↑ y = (x ≥ y ? x : y) .Alle hierboven afgeleide eigenschappen van ↓ gelden ook voor ↑, mits daarbij elk ≤-tekendoor ≥ wordt vervangen.Opgave 2.11 (a) Formuleer en bewijs het analogon van Stelling 2.6 voor ↑.(b) Bewijs dat(−x) ↓ (−y) = −(x ↑ y) .□(c) Formuleer en bewijs een formule voor de berekening van (x ↓ y) ∗ z .We zagen in deze paragraaf dat een bepaalde stelling, namelijk Stelling 2.6, beter geschikt isom resultaten over ↓ te bewijzen dan de definitie. In de volgende paragraaf zullen we opnieuwmet dit verschijnsel te maken krijgen.2.3 Geheeltallige delingGegeven zijn natuurlijke getallen x en y met y ≥ 1. Beschouw de functie die aan elk natuurlijkgetal d de waarde x−d∗y toekent. Voor d = 0 heeft deze een niet-negatieve waarde (namelijkx); voor d = x + 1 krijgen we


2.3. GEHEELTALLIGE DELING 21x − (x + 1) ∗ y= {rekenen}x ∗ (1 − y) − y≤ {x ≥ 0 ∧ 1 − y ≤ 0}−y≤ {y ≥ 1}−1 .Er is dus in het gesloten interval [0 . . x] een grootste waarde van d waarvoor geldt x−d∗y ≥ 0.In verband daarmee kunnen we definiëren:Definitie 2.12 Voor x ≥ 0 ∧ y ≥ 1 is x div y het grootste natuurlijke getal d metx − d ∗ y ≥ 0.□Gevolg 2.13 Voor x ≥ 0 ∧ y ≥ 1 is□d = x div y ≡ x − d ∗ y ≥ 0 ∧ x − (d + 1) ∗ y < 0 .Informeel kunnen we zeggen: x div y is het quotiënt bij deling met rest van x door y . Debijbehorende rest geven we aan met x mod y .Definitie 2.14 Voor x ≥ 0 ∧ y ≥ 1 is□x mod y = x − y ∗ (x div y) .De namen div en mod zijn ontleend aan de programmeertaal Pascal. In C schrijft men / voordiv en % voor mod. We hanteren de conventie dat div en mod dezelfde bindingskracht hebbenals ∗.Evenals bij ↓ is ook bij div en mod het eenvoudiger in berekeningen niet de definitie, maareen afgeleide rekenregel te gebruiken. Deze zullen we nu bewijzen.Stelling 2.15 Voor x ≥ 0 ∧ y ≥ 1 en willekeurige d, m isBewijsd = x div y ∧ m = x mod y ≡ x = d ∗ y + m ∧ 0 ≤ m < y .d = x div y ∧ m = x mod y≡ {definitie van mod}d = x div y ∧ m = x − y ∗ (x div y)≡ {substitutie eerste conjunct in tweede}d = x div y ∧ m = x − y ∗ d≡ {Gevolg 2.13}x − d ∗ y ≥ 0 ∧ x − (d + 1) ∗ y < 0 ∧ m = x − y ∗ d≡ {substitutie van derde conjunct in de beide andere}m ≥ 0 ∧ m − y < 0 ∧ m = x − y ∗ d≡ {rekenen}x = d ∗ y + m ∧ 0 ≤ m < y .□


22 HOOFDSTUK 2. OPERATORENWe geven nu een voorbeeld van het gebruik van Stelling 2.15.Voorbeeld 2.16 Gegeven is x ≥ 0 ∧ y ≥ 1. Te bewijzen is dat voor willekeurige z geldtx div y < z ≡ x < z ∗ y .Dit gaat met een pingpongbewijs als volgt:|[ m = x mod y ∧ d = x div y⊲x div y < z≡ {d = x div y }d < z≡ {eigenschap van ≤, namelijk a < b ≡ a ≤ b − 1}d ≤ z − 1≡ {y > 0}d ∗ y + m ≤ (z − 1) ∗ y + m≡ {Stelling 2.15, i.h.b. x = d ∗ y + m}x ≤ (z − 1) ∗ y + m⇒ {Stelling 2.15, i.h.b. m < y }x < z ∗ y≡ {Stelling 2.15, i.h.b. x = d ∗ y + m}d ∗ y + m < z ∗ y⇒ {Stelling 2.15, i.h.b. m ≥ 0}d ∗ y < z ∗ y≡ {y > 0}d < z≡ {d = x div y }x div y < z]| .□Opgave 2.17 Gegeven is x ≥ 0 ∧ y ≥ 1 ∧ z ≥ 0. Bewijs dat:(a) (x mod y) mod y = x mod y ∧ (x mod y) div y = 0 ,(b) (x mod y + z mod y) mod y = (x + z) mod y ,(c) ((x mod y) ∗ (z mod y)) mod y = (x ∗ z) mod y ,(d) y ∗ ((x − x mod y) div y) + x mod y = x .□Opgave 2.18 Voor d ≥ 1 ∧ p ≥ 0 definiëren wed | p ≡ p mod d = 0 .


2.3. GEHEELTALLIGE DELING 23Bewijs dat(a) d | p ≡ p = (p div d) ∗ d ,(b) d | p ≡ d | p + q ∗ d voor q ≥ 0,(c) d | 0 ,(d) d | d ,(e) d | p ∧ p ≥ 1 ⇒ d ≤ p .□


24 HOOFDSTUK 2. OPERATOREN


Hoofdstuk 3Quantoren3.1 SommatieBeschouw een rij getallen x 0 , x 1 , . . . . Zij n een positief geheel getal. De som van de eerste ngetallen wordt traditioneel aangegeven metx 0 + x 1 + · · · + x n−1 ,maar aan deze notatie is een aantal nadelen verbonden: de betekenis van · · · ligt niet eenduidigvast, generalisatie naar n ≥ 0 is niet mogelijk en er zijn geen rekenregels voor het manipulerenvan een dergelijke formule. We kiezen daarom een andere notatie, namelijk〈Σ i : 0 ≤ i < n : x i 〉 .Dit wordt uitgesproken als ‘de som over i met 0 ≤ i < n van x i ’. Het symbool Σ heet desommatiequantor, de letter i heet de gebonden variabele of dummy. Als we voor i een anderenaam kiezen, verandert de waarde van de formule niet; het is echter sterk af te raden eennaam te kiezen die binnen de context waarin de formule wordt gebruikt al betekenis heeft.Gebruiken we een dergelijke formule bij het afleiden van een programma, dan zullen we in hetbijzonder als gebonden variabele geen naam van een programmavariabele gebruiken. Omdat degebonden variabele i slechts een notationeel hulpmiddel is waaraan geen zelfstandige betekenisis toegekend, is het ten allen tijde zinloos naar de waarde van i te vragen. Het is daarom altijdfout als een gebonden variabele, anders dan voorafgegaan door een quantor, in een predikaatoptreedt.Tussen de dubbele punten staat het domein 0 ≤ i < n van de quantificatie; stilzwijgendwordt overeengekomen dat i staat voor de gehele getallen die aan deze ongelijkheid voldoen.Wanneer het domein niet als betrekking hebbend op gehele getallen moet worden gelezen,zullen we dat altijd duidelijk in de omringende tekst vermelden. Als domein laten we ookformules van andere vorm dan 0 ≤ i < n toe, mits die maar voor eindig veel gehele i dewaarde true bezitten. Is het domein een predikaat, dan dient dit in elke toestand aan deze eiste voldoen.25


26 HOOFDSTUK 3. QUANTORENVoor positieve n geldt de• Afsplitsregel:〈Σ i : 0 ≤ i < n + 1 : x i 〉 = 〈Σ i : 0 ≤ i < n : x i 〉 + x n .Om te bereiken dat deze regel ook geldt voor n = 0, spreken we af dat per definitie geldt• Leeg domein:〈Σ i : false : x i 〉 = 0 .We geven nu een overzicht van de voornaamste andere rekenregels voor Σ. Als in een regel hetdomein er niet toe doet, laten we het weg. Het is dan wel de bedoeling dat in alle quantificatiesin de rekenregel hetzelfde domein wordt ingevuld.• Termsplitsing:〈Σ i :: x i + y i 〉 = 〈Σ i :: x i 〉 + 〈Σ i :: y i 〉 .• Domeinsplitsing:〈Σ i : P i ∨ Q i : x i 〉 = 〈Σ i : P i : x i 〉 + 〈Σ i : Q i : x i 〉op voorwaarde dat P i ∧ Q i ≡ false voor elke i.• Distributie:〈Σ i :: c ∗ x i 〉 = c ∗ 〈Σ i :: x i 〉 .• Constante term:〈Σ i : 0 ≤ i < n : c〉 = n ∗ c .• Eenpuntsregel:• Monotonie:〈Σ i : i = n : x i 〉 = x n .〈Σ i : P i : x i 〉 ≤ 〈Σ i : P i : y i 〉op voorwaarde dat P i ⇒ x i ≤ y i voor elke i.• Hernesten:〈Σ i : P i : 〈Σ j : Q j : x i,j 〉〉 = 〈Σ j : Q j : 〈Σ i : P i : x i,j 〉〉 .In plaats van een van beide leden schrijven we ook wel〈Σ i, j : P i ∧ Q j : x i,j 〉 .


3.1. SOMMATIE 27• Dummytransformatie:〈Σ i : P i : x i 〉 = 〈Σ j : P f.j : x f.j 〉als f een bijectieve functie en j een verse naam is.Opgave 3.1 Bereken(a) 〈Σ i : 0 ≤ i < 100 : i〉 ,(b) 〈Σ i : 0 ≤ i < 100 : 2 + 3i〉 ,(c) 〈Σ i : 0 ≤ i < 100 : (−1) i 〉 ,(d) 〈Σ i : 0 ≤ i < 100 ∧ 50 ≤ i < 500 : i〉 ,(e) 〈Σ i : 0 ≤ i < 100 ∨ 50 ≤ i < 500 : i〉 ,(f) 〈Σ i : 0 ≤ i < 100 ∧ i mod 3 = 1 : i〉 .□Opgave 3.2 Het produkt van getallen x 0 , x 1 , . . . x n−1 geven we in plaats van metx 0 ∗ x 1 ∗ · · · ∗ x n−1liever aan met〈Π i : 0 ≤ i < n : x i 〉 .Formuleer de rekenregels voor de produktquantor Π.□Opgave 3.3 Gegeven isx i ≤ y i ⇒ x i = y i − 2 voor alle i ,〈Σ i : P i ∧ x i ≤ y i : 1〉 = 10 ,〈Σ i : P i : y i 〉 = 30 .Bereken〈Σ i : P i : x i ↓ y i 〉 .□Opgave 3.4 (a) Bewijs dat〈Σ i : P i ∧ Q i : x i 〉 = 〈Σ i : P i : (Q i ? x i : 0)〉 .(b) Bewijs dat〈Σ i : 0 ≤ i < n + 1 ∧ Q i : x i 〉 = 〈Σ i : 0 ≤ i < n ∧ Q i : x i 〉 + (Q n ? x n : 0) .□


28 HOOFDSTUK 3. QUANTOREN3.2 Logische quantificatieMet P i en X i geven we predikaten aan. De formule〈∀i : P i : X i 〉heeft de waarde true in precies die toestanden waar elke i die aan P i voldoet tevens aan X ivoldoet. We spreken deze formule uit als ‘voor alle i met P i geldt X i ’. Het symbool ∀ heet deuniversele quantor, i is de gebonden variabele, P i het domein en X i de term. Voor positieven geldt de• Afsplitsregel:〈∀i : 0 ≤ i < n + 1 : X i 〉 ≡ 〈∀i : 0 ≤ i < n : X i 〉 ∧ X n .Teneinde deze regel ook voor n = 0 te laten opgaan, spreken we af dat per definitie geldt• Leeg domein:〈∀i : false : X i 〉 ≡ true .Door herhaaldelijk toepassen van deze beide regels zien we dat〈∀i : 0 ≤ i < n : X i 〉 ≡ X 0 ∧ X 1 ∧ · · · ∧ X n−1 .De universele quantor speelt dus dezelfde rol ten opzichte van de conjunctie als de sommatiequantorten opzichte van de optelling vervult. Merk echter op dat universele quantificatie ookover oneindige domeinen is gedefinieerd: zo geldt bijvoorbeeld〈∀i : i ≥ 0 : x ≤ (i + 3) 2 〉 ≡ x ≤ 9 .We geven nu een overzicht van de rekenregels voor ∀, waarbij we zo veel mogelijk dezelfdevolgorde aanhouden als in de vorige paragraaf.• Termsplitsing:〈∀i :: X i ∧ Y i 〉 ≡ 〈∀i :: X i 〉 ∧ 〈∀i :: Y i 〉 .• Domeinsplitsing:〈∀i : P i ∨ Q i : X i 〉 ≡ 〈∀i : P i : X i 〉 ∧ 〈∀i : Q i : X i 〉 .Danzij de idempotentie van ∧ is hier, anders dan bij sommatie, geen extra voorwaardeop de domeinen nodig.• Distributie:〈∀i :: C ∨ X i 〉 ≡ C ∨ 〈∀i :: X i 〉 .We geven geen regel voor constante term.


3.2. LOGISCHE QUANTIFICATIE 29• Eenpuntsregel:• Monotonie:〈∀i : i = n : X i 〉 ≡ X n .〈∀i : P i : X i 〉 ⇒ 〈∀i : P i : Y i 〉op voorwaarde dat X i ⇒ Y i onder aanname van P i , voor elke i.• Hernesten:〈∀i : P i : 〈∀j : Q j : X i,j 〉〉 ≡ 〈∀j : Q j : 〈∀i : P i : X i,j 〉〉 .• Dummytransformatie:〈∀i : P i : X i 〉 ≡ 〈∀j : P f.j : X f.j 〉als f een surjectieve functie en j een verse naam is.Voor P i en X i als boven heeft de formule〈∃i : P i : X i 〉de waarde true in precies die toestanden waar voor ten minste één waarde van i zowel aan P ials aan X i is voldaan. We spreken deze formule uit als ‘er bestaat een i met P i waarvoor X igeldt’. Het symbool ∃ heet de existentiële quantor. Voor positieve n geldt de• Afsplitsregel:〈∃i : 0 ≤ i < n + 1 : X i 〉 ≡ 〈∃i : 0 ≤ i < n : X i 〉 ∨ X n .Teneinde deze regel ook voor n = 0 te laten opgaan, spreken we af dat per definitie geldt• Leeg domein:〈∃i : false : X i 〉 ≡ false .Door herhaaldelijk toepassen van deze beide regels zien we dat〈∃i : 0 ≤ i < n : X i 〉 ≡ X 0 ∨ X 1 ∨ · · · ∨ X n−1 .Voor eindige domeinen kan existentiële quantificatie dus worden verkregen door herhaaldelijkedisjunctie; merk echter op dat existentiële quantificatie ook over oneindige domeinen isgedefinieerd.Het verband tussen universele en existentiële quantificatie wordt gegeven door de• Wetten van de Morgan:¬〈∀i : P i : X i 〉 ≡ 〈∃i : P i : ¬X i 〉 ,¬〈∃i : P i : X i 〉 ≡ 〈∀i : P i : ¬X i 〉 .


30 HOOFDSTUK 3. QUANTORENDoor van deze wetten gebruik te maken kunnen de eigenschappen van ∃ gemakkelijk uit dievan ∀ worden afgeleid.Opgave 3.5 Formuleer de wetten Termsplitsing, Domeinsplitsing, Distributie, Eenpuntsregel,Monotonie, Hernesten en Dummytransformatie voor ∃.□Opgave 3.6 Bewijs dat〈∀i : P i : C ∧ X i 〉 ≡ C ∧ 〈∀i : P i : X i 〉onder aanname van〈∃i : P i : true〉 .□In het geval van existentiële quantificatie maakt het geen verschil of we een conjunct in hetdomein of in de term opnemen:• Trading:〈∃i : P i ∧ Q i : X i 〉 ≡ 〈∃i : P i : Q i ∧ X i 〉 .Opgave 3.7 (a) Bewijs dat□〈∃i : P i : X i 〉 ≡ 〈∃i : X i : P i 〉 .(b) Herschrijf〈∀i : P i ∧ Q i : X i 〉 .Opgave 3.8 (a) Bewijs dat〈∀i : P i : X i 〉 ⇒ X nonder aanname van P n .(b) Bewijs datX n ⇒ 〈∃i : P i : X i 〉onder aanname van P n .□Opmerking We zullen de formules uit Opgave 3.8 soms gebruiken in bewijzen; de bijbehorendehint luidt dan ‘Instantiatie i = n’.□


3.3. MINIMA 31Opgave 3.9 De geheelwaardige functie f is gedefinieerd op de verzameling van de gehelegetallen i met 0 ≤ i < 1000. Schrijf de volgende beweringen in formulevorm:(a) f is constant;(b) De vergelijking f.x = 0 heeft geen oplossing;(c) f is monotoon stijgend;(d) Geen van de waarden van f is een drievoud;(e) f.x is altijd een macht van x;(f) f neemt in geen tweetal punten dezelfde waarde aan;(g) Voor zekere x is f.x een priemgetal.□Opgave 3.10 Gegeven isx = 〈∃i, j : i > j 2 mod n ∧ j < n : f.i = 2 ∧ f.j = 2〉 ,y = 〈∀i : i > 0 : f.i ≠ 2〉 .Geef een quantorloze formule voor〈∃i, j : i > j 2 mod n ∧ j ≤ n : f.i = 2 ∧ f.j = 2〉 .□3.3 MinimaDefinitie 3.11 Zij V een verzameling van gehele getallen. Een geheel getal m heet eenminimum van V als geldt□m ∈ V ∧ 〈∀v : v ∈ V : m ≤ v〉 .Opgave 3.12 (a) Bewijs dat elke verzameling van gehele getallen ten hoogste één minimumheeft.(b) Geef een voorbeeld van een verzameling van gehele getallen die geen minimum heeft.□Laat voor elke i met P i een predikaat worden aangegeven, en laat x i voor elke i in elketoestand een geheel getal voorstellen. De formule〈↓ i : P i : x i 〉stelt dan in elke toestand het minimum voor van de verzameling bestaande uit de x i die horenbij alle i die aan P i voldoen, voor zover dat minimum bestaat. In het bijzonder bestaat datminimum altijd als de verzameling in kwestie eindig en niet leeg is. Vanaf nu beperken we onstot dit geval. We spreken de formule uit als ‘het minimum, over i met P i , van x i ’.Voor positieve n geldt de


32 HOOFDSTUK 3. QUANTOREN• Afsplitsregel:〈↓ i : 0 ≤ i < n + 1 : x i 〉 = 〈↓ i : 0 ≤ i < n : x i 〉 ↓ x n .Opmerking Als de Afsplitsregel ook zou gelden voor n = 0, zouden we aan〈↓ i : false : x i 〉een zodanige waarde m moeten geven datx = m ↓ xvoor alle x. Volgens Stelling 2.5 is dit equivalent met x ≤ m voor alle x. Een dergelijk getalbestaat niet. Dit is de reden dat we een minimum met domein false ongedefinieerd laten.□We geven nu de overige rekenregels voor ↓, te beginnen met analoga van die voor Σ.• Termsplitsing:〈↓ i :: x i ↓ y i 〉 = 〈↓ i :: x i 〉 ↓ 〈↓ i :: y i 〉 .• Domeinsplitsing:〈↓ i : P i ∨ Q i : x i 〉 = 〈↓ i : P i : x i 〉 ↓ 〈↓ i : Q i : x i 〉 .Danzij de idempotentie van ↓ is geen voorwaarde op de domeinen nodig.• Distributie:〈↓ i : P i : c + x i 〉 = c + 〈↓ i : P i : x i 〉 .• Eenpuntsregel:• Monotonie:〈↓ i : i = n : x i 〉 = x n .〈↓ i : P i : x i 〉 ≤ 〈↓ i : P i : y i 〉op voorwaarde dat P i ⇒ x i ≤ y i voor elke i.• Hernesten:〈↓ i : P i : 〈↓ j : Q j : x i,j 〉〉 = 〈↓ j : Q j : 〈↓ i : P i : x i,j 〉〉 .• Dummytransformatie:〈↓ i : P i : x i 〉 = 〈↓ j : P f.j : x f.j 〉als f een surjectieve functie en j een verse naam is.


3.3. MINIMA 33Herhaald toepassen van de Afsplitsregel en de Eenpuntsregel leidt tot〈↓ i : 0 ≤ i < n : x i 〉 = x 0 ↓ x 1 ↓ · · · ↓ x n−1 ,waarmee het verband tussen de operator ↓ en de quantor ↓ verklaard is.Behalve de regels die analoga van de wetten voor Σ zijn, hebben we ook regels die totstand komen door de stellingen uit §2.2 te generaliseren. Generalisatie van Stelling 2.4 geeftbijvoorbeeldP n ⇒ 〈↓ i : P i : x i 〉 ≤ x n . (3.1)Gebruik van (3.1) in stellingen gaat gepaard met de hint ‘Instantiatie i = n’.Generalisatie van Stelling 2.6 geeft〈↓ i :: x i 〉 ≤ z ≡ 〈∃i :: x i ≤ z〉 , (3.2)z ≤ 〈↓ i :: x i 〉 ≡ 〈∀i :: z ≤ x i 〉 . (3.3)Naast de minimumquantor ↓ is er ook een maximumquantor ↑, waarvan de eigenschappenworden gevonden door in het bovenstaande consequent ≤ door ≥ te vervangen.Opgave 3.13 (a) Formuleer de rekenregels voor ↑.(b) Bewijs dat□〈↑ i :: −x i 〉 = −〈↓ i :: x i 〉 .(c) Formuleer en bewijs een formule voor de berekening van〈↓ i : P i : x i 〉 ∗ c .Opgave 3.14 Bereken(a) 〈↑ i : 0 ≤ i < 1000 : 10i − i 2 + 32〉 ,(b) 〈↓ i : 0 ≤ i < 1000 : 5i − i 2 〉 .□Opgave 3.15 Herschrijf de definities van div en mod uit §2.3 in formulevorm.□Voor het speciale geval dat de term van een minimumquantor gelijk is aan de dummy, hebbenwe de volgende regel:z = 〈↓ i : P i : i〉 ≡ P z ∧ z ≤ 〈↓ i : P i : i〉 . (3.4)Hiervan zal gebruik gemaakt worden in Hoofdstuk 8.


34 HOOFDSTUK 3. QUANTOREN3.4 Tellende quantificatieMet P i en X i geven we predikaten aan. De formule〈#i : P i : X i 〉heeft in elke toestand als waarde het aantal indices i dat aan zowel P i als X i voldoet. Wespreken de formule uit als ‘het aantal i met P i waarvoor X i geldt’. Onmiddellijke gevolgenvan deze definitie zijn de volgende regels:• Somregel:〈#i :: X i 〉 = 〈Σ i :: (X i ? 1 : 0)〉 .• Afsplitsregel:• Trading:〈#i : 0 ≤ i < n + 1 : X i 〉 = 〈#i : 0 ≤ i < n : X i 〉 + (X n ? 1 : 0) .〈#i : P i ∧ Q i : X i 〉 = 〈#i : P i : Q i ∧ X i 〉 .Verdere eigenschappen kunnen worden gevonden door vertaling van die voor Σ met behulpvan de Somregel.Opgave 3.16 Formuleer en bewijs de regels Termsplitsing, Domeinsplitsing, Eenpuntsregel,Monotonie, Hernesten en Dummytransformatie.□Het verband met logische quantificatie wordt gegeven door〈∃i :: X i 〉 ≡ 〈#i :: X i 〉 ≠ 0 , (3.5)〈∀i :: X i 〉 ≡ 〈#i :: ¬X i 〉 = 0 . (3.6)Opgave 3.17 Bereken□(a) 〈#i : 0 ≤ i < 100 : i 2 ≥ 50〉 ,(b) 〈#i : 0 ≤ i < 100 : i mod 3 = 1〉 ,(c) 〈#i : 0 ≤ i < 100 ∨ 50 ≤ i < 500 : i mod 3 = 1〉 .Opgave 3.18 De geheelwaardige functie f is gedefinieerd op de verzameling van de gehelegetallen i met 0 ≤ i < 1000. Schrijf de volgende beweringen in formulevorm:(a) f heeft ten hoogste vier nulpunten;(b) Het maximum van f wordt precies 1 maal aangenomen;(c) Het maximum van f wordt vaker aangenomen dan het minimum;(d) Voor elke x heeft f.x ten hoogste 24 positieve delers;(e) Voor zekere x is f.x een priemgetal (vergelijk Opgave 3.9(g));(f) f neemt in precies 18 punten een even waarde aan;(g) f neemt precies 18 verschillende even waarden aan.□


Hoofdstuk 4Specificaties4.1 Hoare-tripelsDe uitspraken die in dit college over de werking van programma’s worden gedaan, zullen allede volgende vorm hebben:{Q} S {R} ,waarin Q en R predikaten zijn en S een rij opdrachten is. Een dergelijke formule heet eenHoare-tripel. Het predikaat Q heet de preconditie, R heet de postconditie. De betekenis vandeze uitspraak is de volgende:Als met de uitvoering van S wordt begonnen in een toestand die aan Q voldoet,dan zal na een eindige spanne tijds de uitvoering van S zijn voltooid en wel in eentoestand die aan R voldoet.Een dergelijk Hoare-tripel beschrijft het netto effect van S , dat wil zeggen het verband tussenbegin- en eindtoestand, in het midden latend langs welke weg dit effect is bereikt. Programmafragmentendie dezelfde pre- en postcondities toelaten, beschouwen wij als functioneelequivalent.Voorbeeld 4.1 In een programma met geheelwaardige variabele a is een rij opdrachten Snodig die a de waarde 5 geeft. We weten dat S zal worden uitgevoerd in een toestand waara de waarde 3 heeft. Gezocht wordt dus een S die voldoet aan het Hoare-tripel{a = 3} S {a = 5} .Oplossingen zijn bijvoorbeeldS0 : a := 5 ,S1 : a := 2 ∗ a; a := a − 1 ,S2 : a := a + 1; a := a + 1 ,S3 : a := a ∗ a − 4 .In de gegeven begintoestand heeft uitvoering van elk van deze fragmenten hetzelfde nettoeffect op de waarde van a. De keuze is irrelevant vanuit een oogpunt van correctheid en kangeheel op basis van efficiëntie-overwegingen geschieden.□35


36 HOOFDSTUK 4. SPECIFICATIESVan Hoare-tripels zullen we op twee manieren gebruik maken. Enerzijds kan programmerenworden opgevat als het construeren van een rij opdrachten S die aan een Hoare-tripel met gegevenpre- en postconditie voldoet; het bovenstaande voorbeeld laat een triviaal geval hiervanzien. We zullen Hoare-tripels in §4.3 dan ook gebruiken voor het specificeren van programma’s.Anderzijds kan de werking van een gegeven programmeertaalconstructie worden beschrevendoor de verzameling van alle Hoare-tripels waarin deze optreedt te karakteriseren. InHoofdstuk 5 worden Hoare-tripels gebruikt om de semantiek van de programmanotatie GCLvast te leggen.4.2 Rekenregels voor Hoare-tripelsWanneer we in een gegeven Hoare-tripel de preconditie versterken, wordt de collectie begintoestandenwaarover we een uitspraak doen beperkt. Er ontstaat dus een zwakkere bewering.Wanneer we de postconditie verzwakken, ontstaat eveneens een zwakkere bewering. De volgenderegel geldt dus:• Verzwakking van Hoare-tripels: Veronderstel dat voor predikaten Q, R, X, Y enrij opdrachten S geldtX ⇒ Q ,{Q} S {R} ,R ⇒ Y .Dan geldt ook{X } S {Y } .Willen we uitspreken dat {X } S {Y } geldt en tevens op een compacte manier duidelijkmaken dat dit volgt door toepassing van bovenstaande rekenregel, dan schrijven we{X } {Q} S {R} {Y } .Voorbeeld 4.2 Voor een geheelwaardige variabele a geldt{0 < a < 2} {a = 1} a := a + 1 {a = 2} {a ≠ 3} .Dit betekent: het Hoare-tripel{0 < a < 2} a := a + 1 {a ≠ 3}geldt, en wel wegens□0 < a < 2 ⇒ a = 1 ,{a = 1} a := a + 1 {a = 2} ,a = 2 ⇒ a ≠ 3 .


4.3. PARAMETERS 37Een tweede eigenschap van Hoare-tripels die we soms gebruiken, is de volgende:• Conjunctie van Hoare-tripels: Als geldten{Q} S {R}{X } S {Y } ,dan geldt ook{Q ∧ X } S {R ∧ Y } .We zullen deze regel vooral gebruiken om bij het verifiëren van Hoare-tripels de verschillendeconjuncten in de postconditie afzonderlijk te behandelen.4.3 ParametersEen Hoare-tripel legt de werking van een programmafragment niet in alle gevallen voldoendenauwkeurig vast. Beschouw bijvoorbeeld een rij opdrachten S die moet werken op tweegeheeltallige variabelen a en b en voldoen aan het Hoare-tripel{a > 0} S {b = 2 a } . (4.1)Bedoeld wordt vermoedelijk dat S de waarde van a ongemoeid moet laten en b een bij degegeven a passende waarde moet geven, maar deze voorwaarde wordt door het Hoare-tripelniet uitgedrukt. Ooka := 1; b := 2is een correcte oplossing van (4.1).Teneinde ondubbelzinnig vast te leggen welke variabelen door een programmafragmentmogen worden gewijzigd en van welke variabelen de waarde mag worden gebruikt, voeren weeen nieuwe notatie in. Deze legt tevens vast wat het type van de te gebruiken variabele isen maakt het vooraf in woorden vastleggen van de toestandsruimte daarmee overbodig. Deformule|[ con int a {a > 0}; var int b⊲ S {b = 2 a }]|legt vast dat S voldoet aan het Hoare-tripel (4.1), de waarde van a mogelijk gebruikt maarzeker niet verandert (dit wordt aangegeven door het woord con, voor constant) en de waardevan b mogelijk verandert (dit wordt aangegeven door het woord var, voor variabel). Eendergelijke formule heet een specificatie van S ; men noemt a en b de parameters van dezespecificatie. De preconditie van de specificatie is de conjunctie van alle asserties die voor het⊲-teken staan, de postconditie die van alle asserties erna.Vullen we voor S een rij opdrachten in die aan al deze eisen voldoet, dan ontstaat eengespecificeerd subprogramma dat we te zijner tijd ongewijzigd als procedure kunnen gebruiken.


38 HOOFDSTUK 4. SPECIFICATIES4.4 TypenHet voorbeeld in de vorige paragraaf bevatte twee maal het woord int. Daarmee werd aangegevendat de parameters geheelwaardig waren. De programmeertaal die we in het volgendehoofdstuk introduceren kent twee primitieve typen, namelijk int en bool. De waardenverzamelingvan int bestaat uit (een voldoend groot segment van) de gehele getallen; op int zijnde rekenkundige operatoren+ − ∗ div mod ↑ ↓en de relationele operatoren= ≠ ≤ < ≥ >gedefinieerd. De waardenverzameling van bool bestaat uit de boolse waarden true en false;op bool zijn de logische operatoren∧ ∨ ¬en de relationele operatoren= ≠gedefinieerd. Ook zullen we in programma’s de conditionele expressies (B ? X : Y ) uit §2.1toelaten: hierin is B een expressie van type bool, terwijl X en Y beide int of beide boolzijn.Daarnaast kunnen we werken met arrays. Een declaratieint a[0 . . 10)legt vast dat a.0, a.1, . . . , a.9 tien variabelen van het type int zijn. Voor elke expressie E vanhet type int kunnen we met a.E een van deze variabelen aanduiden mits 0 ≤ E < 10 geldt.Voorbeeld 4.3 Gegeven is een natuurlijk getal N en een array a[0 . . N). Gevraagd wordtaan de variabele r de som van alle termen van het array die een oneven waarde hebben toete kennen. Een specificatie van dit probleem ziet er als volgt uit:□|[ con int N {N ≥ 0}; con int a[0 . . N); var int r⊲ S {r = 〈Σ i : 0 ≤ i < N ∧ a.i mod 2 = 1 : a.i〉}]| .Opgave 4.4 Gegeven zijn geheelwaardige variabelen x en y . Geef een specificatie van eenrij opdrachten S die x en y niet verandert en verder aan onderstaande eisen voldoet.(a) S berekent de som van x en y .(b) S stelt vast of x kleiner is dan y .(c) S bepaalt de grootste van x en y .(d) S berekent het gemiddelde van x en y .(e) S berekent het teken van x 2 − y 3 .(f) S berekent x!.(g) S onderzoekt of onder x en y een 0 voorkomt.□


4.5. SPECIFICATIEVARIABELEN 39Opgave 4.5 Gegeven zijn een geheelwaardige variabele x en een array a[0 . . 100). Geefeen specificatie van een rij opdrachten S die deze variabelen niet verandert en verder aanonderstaande eisen voldoet.(a) S onderzoekt of x in a voorkomt.(b) S berekent de som van a.(c) S berekent het gemiddelde van a.(d) S onderzoekt of x ten minste twee maal in a voorkomt.(e) S berekent het maximum van a.(f) S berekent een index van het maximum van a.(g) S berekent hoe vaak x in a voorkomt.(h) S onderzoekt hoeveel verschillende waarden in a voorkomen.(i) S onderzoekt of alle termen van a verschillen.(j) S onderzoekt of in a een kwadraat voorkomt.(k) S bepaalt de meest rechtse even term in a, gegeven dat er ten minste een even waardein a voorkomt.(l) S berekent de op een na grootste term van a.□4.5 SpecificatievariabelenVeronderstel dat we een programmafragment S willen specificeren dat de waarde van eenvariabele x kwadrateert. Zo’n S moet voldoen aan het Hoare-tripel{x = 3} S {x = 9} ,maar ook aanen aan{x = 10} S {x = 100}{x = −2} S {x = 4} .Zo kunnen we nog wel meer voorbeelden geven, maar volledig wordt de werking van S alleenbeschreven door te eisen dat S voor elk geheel getal α voldoet aan{x = α} S {x = α 2 } .In feite staat hier een oneindige collectie Hoare-tripels, een voor elke keuze van α.specificatie van S ziet er nu als volgt uit:Een|[ var int x {x = α}⊲ S {x = α 2 }]| .Merk op dat α niet wordt gedeclareerd en daarom niet in de programmatekst van S magvoorkomen. Een dergelijke α heet een specificatievariabele. Specificatievariabelen wordenvooral gebruikt om relaties tussen de begin- en eindwaarde van variabelen vast te leggen. Omhet onderscheid met de parameters van de specificatie te benadrukken, zullen we in dit collegespecificatievariabelen steeds met Griekse letters aanduiden.


40 HOOFDSTUK 4. SPECIFICATIESVoorbeeld 4.6 We dienen een programmafragment S te specificeren dat de waarden vanvariabelen x en y verwisselt. Een specificatie van S ziet er als volgt uit:□|[ var int x, y {x = α ∧ y = β }⊲ S {x = β ∧ y = α}]| .Opgave 4.7 Gegeven zijn geheelwaardige variabelen x en y . Geef een specificatie van eenrij opdrachten S die aan de volgende eisen voldoet:(a) S ordent x en y naar grootte.(b) S vervangt x en y door hun som.(c) S deelt x door y ; veronderstel dat y > 0.(d) S vervangt x en y door hun maximum.□


Hoofdstuk 5Programma’s5.1 ToekenningVoordat we een antwoord kunnen geven op de vraag, hoe een programmafragment kan wordengeconstrueerd dat aan een gegeven specificatie voldoet, dienen we ons bezig te houden methet omgekeerde probleem aan welke specificaties de opdrachten van onze programmeertaalvoldoen. De taal GCL (Guarded Command Language) die in dit college wordt gebruikt is eenvariant op een taal die door E.W. Dijkstra speciaal voor het formeel afleiden van programma’sis ontworpen.We beginnen met de toekenningsopdracht (assignment)x := X .Hierin is x een programmavariabele van type int of bool, en X een expressie van hetzelfdetype als x. (Toekenningen aan array-componenten laten we nog even buiten beschouwing.)Voorlopig nemen we aan dat de expressie X in elke toestand gedefinieerd is. De betekenis vandeze opdracht is dat de waarde van de expressie X moet worden berekend en aan de variabelex toegekend. De toekenning voldoet dus aan het Hoare-tripel{X = α} x := X {x = α} . (5.1)Merk op dat het niet correct is als postconditie x = X te schrijven, aangezien x in X kanvoorkomen: de toekenning x := x + 1 zal als postconditie zeker niet x = x + 1 hebben.Voor gebruik bij de constructie van programma’s is (5.1) niet algemeen genoeg: we willenweten hoe we willekeurige postcondities tot stand kunnen brengen, niet alleen maar eenpostconditie van de vorm x = α. Om de regel die hiervoor geldt goed te kunnen formuleren,voeren we een speciale notatie in.Definitie 5.1 Is P een predikaat, x een programmavariabele en X een expressie, dan is(x ← X).P het predikaat dat ontstaat door alle vrije voorkomens van de naam x in P door(X) te vervangen.□Het woord vrije voorkomens beduidt dat een eventueel voorkomen van x als gebonden variabeleniet wordt vervangen; maar we hadden eerder al beloofd geen naam van een programmavariabelete gebruiken als gebonden variabele. De haakjes in (X) zijn bedoeld om problemen41


42 HOOFDSTUK 5. PROGRAMMA’Smet prioriteit van operatoren te voorkomen; ze mogen worden weggelaten als dat de betekenisvan het resultaat niet verandert.Voorbeeld 5.2 Het effect van de haakjes wordt duidelijk in≡≡(y ← x + y).(x − y < 10){substitutie}x − (x + y) < 10{rekenen}y > −10 .□Soms voeren we verschillende substituties na elkaar uit. Met(x ← X; y ← Y ).Pwordt(x ← X).((y ← Y ).P )bedoeld.Voorbeeld 5.3≡≡≡(y ← x + y; x ← x − y).(x + y < 10){substitutie}(y ← x + y).(x − y + y < 10){rekenen}(y ← x + y).(x < 10){substitutie}x < 10 .□Voorbeeld 5.4 Merk op dat de volgorde waarin de substituties worden uitgevoerd van cruciaalbelang is. Enerzijds geldt≡≡≡(n ← n + 1; x ← n).〈∀i : 0 ≤ i < n : i < x〉{substitutie}(n ← n + 1).〈∀i : 0 ≤ i < n : i < n〉{term volgt uit domein}(n ← n + 1).true{substitutie}trueen anderzijds


5.1. TOEKENNING 43|[ n ≥ 0⊲(x ← n; n ← n + 1).〈∀i : 0 ≤ i < n : i < x〉≡ {substitutie}≡(x ← n).〈∀i : 0 ≤ i < n + 1 : i < x〉{substitutie}〈∀i : 0 ≤ i < n + 1 : i < n〉⇒ {instantiatie i := n, gebruik n ≥ 0}n < n≡ {}false]| .□Ook komt het voor dat we in een enkele substitutie meer dan een variabele vervangen. Met(x, y ← X, Y ).Pgeven we het predikaat aan dat ontstaat door alle vrije voorkomens van de naam x in P door(X) en die van de naam y in P door (Y ) te vervangen.Opgave 5.5 Bereken□(a) (x, y ← y, x).(x = α ∧ y = β) ,(b) (x ← y; y ← x).(x = α ∧ y = β) ,(c) (z ← x; x ← y; y ← z).(x = α ∧ y = β) ,(d) (x ← x + y; y ← x − y; x ← x − y).(x = α ∧ y = β) .Het blijkt dat de bewijsregel voor de toekenning een eenvoudige vorm krijgt als we uitgaanvan de postconditie en proberen daarbij een passende preconditie te vinden, dus als we bijgegeven R een Q zoeken met{Q} x := X {R} . (5.2)De volgende regel kan hiervoor worden gebruikt:• Bewijsregel voor de toekenning: Is R een predikaat, x een programmavariabeleen X een (in elke toestand gedefinieerde) expressie van het type van x, dan geldt{Q} x := X{R}dan en slechts dan alsQ ⇒ (x ← X).R .Passen we deze regel toe met voor R het predikaat x = α, dan krijgen we (5.1) terug.


44 HOOFDSTUK 5. PROGRAMMA’SVoorbeeld 5.6 Gevraagd wordt een (zo zwak mogelijke) preconditie Q zó datEr geldt{Q} x := x ∗ x − 1 {x > 0} . (5.3)≡≡(x ← x ∗ x − 1).(x > 0){substitutie}x ∗ x − 1 > 0{rekenen}x < −1 ∨ x > 1 ,dus (5.3) geldt als en alleen alsQ ⇒ x < −1 ∨ x > 1 .De zwakste Q die aan deze eis voldoet is□x < −1 ∨ x > 1 .Is de expressie X niet in alle toestanden gedefinieerd, dan moet aan de preconditie vanx := X allereerst de eis gesteld worden dat daaraan alleen toestanden voldoen waarin X welis gedefinieerd. Alleen in zulke toestanden kan de toekenning immers worden uitgevoerd. Intoestanden waarin X gedefinieerd is en bovendien (x ← X).R geldt, leidt uitvoering vanx := X tot een toestand die aan R voldoet. Voor expressies X die niet overal gedefinieerdzijn, is{Q} x := X{R}derhalve equivalent metQ ⇒ def .X ∧ (x ← X).R ,waarin def .X het predikaat is dat het definitiegebied van X beschrijft. Zo geldt bijvoorbeelddef .(X mod Y ) ≡ def .X ∧ X ≥ 0 ∧ def .Y ∧ Y ≥ 1 ,en, voor een array a[0 . . N),def .(a.E) ≡ def .E ∧ 0 ≤ E < N .Voorbeeld 5.7 Gegeven zijn s en a[0 . . N) van het type int. Gevraagd wordt een (zo zwakmogelijke) preconditie Q zó datEr geldten{Q} s := s + a.n {s = 〈Σ i : 0 ≤ i < N : a.i〉} .def .(s + a.n) ≡ 0 ≤ n < N


5.1. TOEKENNING 45|[ 0 ≤ n < N⊲(s ← s + a.n)(s = 〈Σ i : 0 ≤ i < N : a.i〉)≡ {substitutie}s + a.n = 〈Σ i : 0 ≤ i < N : a.i〉≡ {Domeinsplitsing, gebruik 0 ≤ n < N }s + a.n = 〈Σ i : 0 ≤ i < N ∧ i ≠ n : a.i〉 + 〈Σ i : i = n : a.i〉≡ {Eenpuntsregel}s + a.n = 〈Σ i : 0 ≤ i < N ∧ i ≠ n : a.i〉 + a.n≡ {rekenen}s = 〈Σ i : 0 ≤ i < N ∧ i ≠ n : a.i〉]| .De zwakste Q die voldoet is dus□0 ≤ n < N ∧ s = 〈Σ i : 0 ≤ i < N ∧ i ≠ n : a.i〉 .Opgave 5.8 Gegeven zijn x en y van type int. Bepaal een zo zwak mogelijke Q met(a) {Q} x := x + 1 {x = 3} ,(b) {Q} x := x + 2 {0 ≤ x < 10} ,(c) {Q} x := 2 ∗ x + y {x = 2 ∗ x + y} ,(d) {Q} x := 3 {x = 3 ∧ y = 4} ,(e) {Q} x := x + y {y ≥ 0 ∧ x = 〈Σ i : 0 ≤ i < y + 1 : i〉} .□We voeren ook een meervoudige toekenning x, y := X, Y in, met (voor in alle toestandengedefinieerde X, Y ) als bewijsregel:{Q} x, y := X, Y{R}dan en slechts dan alsQ ⇒ (x, y ← X, Y ).R .Opgave 5.9 Gegeven zijn x en y van type int. Bepaal een zo zwak mogelijke Q met(a) {Q} x, y := x + 1, y − 1 {x + y > 0} ,(b) {Q} x, y := y + 1, x − 1 {x > 0} ,(c) {Q} x, y := y ∗ x, x ∗ y {x + y > 0} .□


46 HOOFDSTUK 5. PROGRAMMA’SWe geven nu een aantal voorbeelden om te demonstreren hoe we een toekenning kunnenuitrekenen die aan een gegeven specificatie voldoet.Voorbeeld 5.10 Gevraagd wordt een expressie X die voldoet aanEr geldt|[ con int m, n, N {0 ≤ m ≤ n < N }; con int a[0 . . N); var int x {x = 〈Σ i : m ≤ i < n : a.i〉}⊲ x := X {x = 〈Σ i : m + 1 ≤ i < n + 1 : a.i〉}]| .|[ 0 ≤ m ≤ n < N ∧ x = 〈Σ i : m ≤ i < n : a.i〉⊲(x ← X).(x = 〈Σ i : m + 1 ≤ i < n + 1 : a.i〉)≡ {substitutie}X = 〈Σ i : m + 1 ≤ i < n + 1 : a.i〉≡ {Domeinsplitsing, gebruik m ≤ n}X = 〈Σ i : m ≤ i < n : a.i〉 + a.n − a.m≡ {x = 〈Σ i : m ≤ i < n : a.i〉}X = x + a.n − a.m]| .Voor X kiezen we de expressie x + a.n − a.m.□Opmerking In een berekening als de bovenstaande beginnen alle regels, behalve de eerste,met ‘X =’. Ter besparing van schrijfwerk is het gebruikelijk in zo’n geval de eerste regel ende vermeldingen van X weg te laten en de berekening op te schrijven als|[ 0 ≤ m ≤ n < N ∧ x = 〈Σ i : m ≤ i < n : a.i〉⊲〈Σ i : m + 1 ≤ i < n + 1 : a.i〉= {Domeinsplitsing, gebruik m ≤ n}〈Σ i : m ≤ i < n : a.i〉 + a.n − a.m= {x = 〈Σ i : m ≤ i < n : a.i〉}x + a.n − a.m]| .We zullen dat in het vervolg meestal ook doen. Men dient zich er echter rekenschap van tegeven waar deze berekening vandaan komt.□Voorbeeld 5.11 Gezocht wordt een expressie X die voldoet aan|[ con int a, b, c {a ∗ c = b 2 }; var int x, y {a ∗ x = b ∗ y }⊲ x, y := X, y + b {a ∗ x = b ∗ y }]| .


5.1. TOEKENNING 47Er geldt|[ a ∗ c = b 2 ∧ a ∗ x = b ∗ y⊲(x, y ← X, y + b).(a ∗ x = b ∗ y)≡ {substitutie}≡a ∗ X = b ∗ (y + b){rekenen}a ∗ X = b ∗ y + b 2≡ {b ∗ y = a ∗ x ‖ b 2 = a ∗ c}a ∗ X = a ∗ x + a ∗ c⇐ {vermenigvuldig met a}X = x + c]| .Voor X kiezen we de expressie x + c.□Voorbeeld 5.12 Gevraagd wordt een expressie X die voldoet aanEr geldt|[ con int n, N {0 ≤ n < N }; con bool a[0 . . N); var int x {x = 〈#i : 0 ≤ i < n : a.i〉}⊲ x := X {x = 〈#i : 0 ≤ i < n + 1 : a.i〉}]| .|[ 0 ≤ n < N ∧ x = 〈#i : 0 ≤ i < n : a.i〉⊲〈#i : 0 ≤ i < n + 1 : a.i〉= {Afsplitsregel, gebruik n ≥ 0}〈#i : 0 ≤ i < n : a.i〉 + (a.n ? 1 : 0)= {x = 〈#i : 0 ≤ i < n : a.i〉}x + (a.n ? 1 : 0)]| .Voor X kiezen we dus de expressie x + (a.n ? 1 : 0).□Opgave 5.13 De functie f is gedefinieerd op de gehele getallen. Bereken een expressie Xmet□(a) {true} x, n := X, 0 {x = 〈Σ i : 0 ≤ i < n : f.i〉} ,(b) {true} x, n := X, 1 {x = 〈Σ i : 0 ≤ i < n : f.i〉} .


48 HOOFDSTUK 5. PROGRAMMA’SOpgave 5.14 Bereken een expressie X met{P ∧ n ≥ 0} x, n := X, n + 1 {P } ,waarin P het volgende predikaat is:□(a) x = 〈Σ i : 0 ≤ i < n : i〉 ,(b) x = 2 n ,(c) x = n 2 ,(d) x = 〈∃i : 0 ≤ i < n : (100 − n + i) mod 1000 < 100〉 ,(e) x = 〈Π i : n ≤ i < 2n : i 2 div 10〉 ,(f) x = 12n + 5 ,(g) x = n! ,( ) 12 + n(h) x =n(i) x = 〈Σ i : 0 ≤ i < n : (−1) i ∗ i 2 〉 ,(j) 〈∃i : i ≥ n : x = i 3 〉 ,(k) x = 〈↑ i : −n ≤ i ≤ n : |i + 3| mod 25〉 ,(l) x ≥ n ∨ x ≤ −n .,Opgave 5.15 Implementeer de specificatie|[ con int n, N {1 ≤ n < N }; con int a[0 . . N); var int x {P }⊲ S {(n ← n + 1).P }]| ,waarin P wordt gegeven door□(a) x = 〈Σ i : 0 ≤ i < n ∧ a.i > 0 : a.i〉 ,(b) x = 〈↑ i : 0 ≤ i < n : a.i〉 ,(c) x = 〈↑ i : 0 ≤ i < n ∧ a.i > 0 : i〉 ,(d) 0 ≤ x < n ∧ a.x = 〈↑ i : 0 ≤ i < n : a.i〉 ,(e) x = 〈Σ i : 0 ≤ i < n : |a.i|〉 ,(f) x = 〈#i : 0 ≤ i < n : a.i < i〉 .Opmerking Voor elke variabele x geldt{Q} x := x {R}


5.2. SEQUENTIËLE COMPOSITIE 49dan en slechts dan als Q ⇒ R. In het bijzonder is dit onafhankelijk van de keuze van variabelex. We hebben voor x := x daarom graag een naam die x niet bevat. Hiervoor kiezen we skip.De opdracht skip eindigt altijd; na afloop gelden dezelfde predikaten als vooraf. Niets doen isdaarom een goede implementatie van skip.□5.2 Sequentiële compositieEen GCL-programma bestaat uit een rij opdrachten met daartussen puntkomma’s. De opdrachtenmoeten in de gegeven tekstuele volgorde worden uitgevoerd, dusS; Tbetekent: voer S uit, en daarna T . Merk op dat de puntkomma gebruikt wordt voor hetverbinden van opdrachten en niet voor het beëindigen ervan: na de laatste opdracht van hetprogramma staat geen puntkomma. In overeenstemming met deze rol zullen we de puntkomma’sgewoonlijk in de linkerkantlijn schrijven.In deze paragraaf gaan we na hoe het effect van een rij opdrachten kan worden berekenduit de effecten van de afzonderlijke opdrachten in die rij. De volgende regel geeft het antwoord:• Bewijsregel voor sequentiële compositie: Zijn S en T opdrachten en P, Q, Rpredikaten, zó, dat voldaan is aanen{Q} S {P }{P } T {R} ,dan geldt ook{Q} S; T {R} .Deze regel is niet moeilijk te begrijpen. Immers, wordt aan de uitvoering van S begonnenin een toestand waar Q geldt, dan zal die uitvoering eindigen, en wel in een toestand waarP geldt – dat garandeert het Hoare-tripel voor S . Wordt in die laatste toestand vervolgensbegonnen met de uitvoering van T , dan zal die ook eindigen, en wel in een toestand waar Rgeldt – dat garandeert het Hoare-tripel voor T .Willen we uitspreken dat {Q} S; T {R} geldt en tevens op een compacte wijze duidelijkmaken dat dit volgt door toepassing van bovenstaande bewijsregel, dan schrijven we{Q}S{P }; T{R} .


50 HOOFDSTUK 5. PROGRAMMA’SAnalyse van de werking van een programma vereist dat we in principe in staat zijn tussenelk tweetal opeenvolgende opdrachten een predikaat tussen accolades te plaatsen dat danenerzijds dienst doet als postconditie van de voorafgaande opdracht, anderzijds als preconditievan de erop volgende. Zo’n in een programma geplaatst predikaat heet een assertie; eenprogramma voorzien van asserties heet het annoteren van dat programma. De speciale vormvan de bewijsregel voor de toekenning maakt het nodig bij het annoteren van een programmaachteraan te beginnen, steeds uit een gegeven postconditie de bijbehorende preconditieberekenend.Voorbeeld 5.16 Gevraagd wordt een (zo zwak mogelijke) preconditie Q zó datEr geldt{Q} x := x ∗ x − 1; x := x ∗ x − 9 {x > 0} .≡≡(x ← x ∗ x − 9).(x > 0){substitutie}x ∗ x − 9 > 0{rekenen}x < −3 ∨ x > 3 ,zodatVerder{x < −3 ∨ x > 3} x := x ∗ x − 9 {x > 0} .≡≡≡(x ← x ∗ x − 1).(x < −3 ∨ x > 3){substitutie}x ∗ x − 1 < −3 ∨ x ∗ x − 1 > 3{rekenen}false ∨ x < −2 ∨ x > 2{Eenheidselement}x < −2 ∨ x > 2 .Toepassing van bovenstaande bewijsregel (met voor P het predikaat x < −3 ∨ x > 3) geeft{x < −2 ∨ x > 2}x := x ∗ x − 1 {x < −3 ∨ x > 3}; x := x ∗ x − 9 {x > 0} .Voor Q kiezen we dus het predikaat x < −2 ∨ x > 2.□Combinatie van de twee behandelde bewijsregels leidt tot een bewijsregel voor de sequentiëlecompositie van toekenningen. Zij x een programmavariabele en X een expressie van hettype van x; zij y een programmavariabele en Y een expressie van het type van y . Verondersteldat X en Y in elke toestand gedefinieerd zijn. Voor elk predikaat R geldt dan{(x ← X; y ← Y ).R} x := X; y := Y {R} .


5.2. SEQUENTIËLE COMPOSITIE 51Voorbeeld 5.17 Beschouw nogmaals de in het vorige voorbeeld gestelde vraag naar een (zozwak mogelijke) Q metEr geldt{Q} x := x ∗ x − 1; x := x ∗ x − 9 {x > 0} .≡≡≡≡≡(x ← x ∗ x − 1; x ← x ∗ x − 9).(x > 0){substitutie}(x ← x ∗ x − 1).(x ∗ x − 9 > 0){rekenen}(x ← x ∗ x − 1).(x < −3 ∨ x > 3){substitutie}x ∗ x − 1 < −3 ∨ x ∗ x − 1 > 3{rekenen}false ∨ x < −2 ∨ x > 2{Eenheidselement}x < −2 ∨ x > 2 .□Opgave 5.18 (a) Bewijs dat voor x, y, z van type int of bool geldt□{x = α ∧ y = β }z := x; x := y; y := z{x = β ∧ y = α} .(b) Bewijs dat voor x, y van type int geldt{x = α ∧ y = β }x := x + y; y := x − y; x := x − y{x = β ∧ y = α} .Opgave 5.19 Gegeven zijn x, y van type int. Bepaal een zo zwak mogelijke Q met(a) {Q} x := 2 ∗ x; y := y + 1 {x = 2 y } ,(b) {Q} x := 2 ∗ y + x + 1; y := y + 1 {x = y 2 } ,(c) {Q} x := x ∗ x; x := x + 1 {x > 0} .□


52 HOOFDSTUK 5. PROGRAMMA’SOpgave 5.20 Bereken een expressie X zodanig dat(a) {x ∗ d + r = α} x := X; r := r − d {x ∗ d + r = α} ,(b) {true} x := X; y := y div 2 {x = 2 ∗ y} ,(c) {n ≥ 0 ∧ x = n!} x := X; n := n + 1 {n ≥ 0 ∧ x = n!} .□Opgave 5.21 Geef een rij opdrachten S die voldoet aan|[ var int n {n = α ≥ 1}; var int x, y, z {P }⊲ S {(n ← n + 1).P ∧ n = α}; n := n + 1 {P ∧ n = α + 1}]| ,waar P wordt gegeven door□(a) x = (−1) n ∧ y = 〈Σ i : 0 ≤ i < n : (−1) i ∗ i 2 〉 ,(b) x = 2 n ∧ y = 3 n ∧ z = 2 n + 3 n ,(c) x = n! ∧ y = (n − 1)! ∗ (n − 1) .5.3 SelectieDe selectie biedt de mogelijkheid om, afhankelijk van zeker kenmerk van de begintoestand,uit een aantal opdrachten er één te laten uitvoeren. Als eenvoudig geval beschouwen we deopdrachtif B → SC → Tfi .Hierin zijn B en C expressies van het type bool en zijn S en T rijen opdrachten. Voorlopignemen we aan dat B en C in elke toestand gedefinieerd zijn. De combinatie B → S heeteen guarded command met guard B ; aan deze guarded commands heeft de taal GCL zijnnaam te danken.Operationeel komt uitvoering van bovenstaande opdracht neer op het volgende. Ingevalzowel B als C de waarde false hebben, eindigt uitvoering niet 1 . Ingeval ten minste één vande guards B, C de waarde true heeft, wordt nondeterministisch een guard met waarde truegeselecteerd en de bijbehorende opdracht (S of T ) uitgevoerd. Let op: ook als beide guardsde waarde true hebben, wordt toch slechts een van beide opdrachten uitgevoerd.1 Althans niet in een punt van de toestandsruimte. Een mogelijke implementatie is de uitvoering te latenduren totdat iemand met de hand de machine uitschakelt of zich een mechanische storing voordoet, een anderemogelijke implementatie is dat uitvoering van het programma wordt afgebroken met een foutmelding.


5.3. SELECTIE 53Om te bereiken dat de selectie een postconditie R bewerkstelligt, dienen we allereerst teeisen dat in de begintoestand B ∨ C geldt. (Dit noemen we wel de eindigingseis.) Bovendienmoet in gevallen waar B geldt uitvoering van S tot R leiden; in gevallen waar C geldt, moetuitvoering van T tot R leiden.• Bewijsregel voor de selectie: Zijn Q en R predikaten, S en T rijen opdrachtenen B, C (in elke toestand gedefinieerde) expressies van type bool, dan geldt{Q}if B → SC → Tfi{R} .als voldaan is aanen{Q ∧ B} S {R}{Q ∧ C} T {R}en de eindigingseisQ ⇒ B ∨ C .Ingeval voorafgaand aan de selectie B en C beide de waarde true hebben, geschiedt de keuzetussen B en C nondeterministisch. Dat wil zeggen dat het ons niet is toegestaan bij hetschrijven van programma’s veronderstellingen te maken omtrent de wijze waarop het systeemde keuze uitvoert. De reden voor het opnemen van een dergelijke constructie is tweevoudig.Enerzijds is de programmeur nu niet gedwongen van meet af aan een keuze tussen twee opdrachtente forceren indien zij beide voldoen, waardoor de mogelijkheid open blijft in eenlater stadium de keuze van efficiëntie-overwegingen te laten afhangen. Anderzijds stelt dezeconstructie ons in staat de symmetrie tussen de beide guarded commands te handhaven en inhet bewijs te exploiteren.Voorbeeld 5.22 Gevraagd wordt een zo zwak mogelijke Q met{Q}if x ≤ y → p, y := p + q ∗ (y div x), y mod xx ≥ y → q, x := q + p ∗ (x div y), x mod yfi{p ∗ x + q ∗ y = α} .Aan de eindigingseisQ ⇒ x ≤ y ∨ x ≥ y


54 HOOFDSTUK 5. PROGRAMMA’Sis voor elke Q voldaan. We onderzoeken nu eerst de eerste guarded command; deze legt aanQ als eis op{Q ∧ x ≤ y} p, y := p + q ∗ (y div x), y mod x {p ∗ x + q ∗ y = α} .Merk eerst op datdef .(y mod x) ≡ x ≥ 1 ∧ y ≥ 0 ,dus Q ∧ x ≤ y moet in elk geval x ≥ 1 ∧ y ≥ 0 impliceren. Verder|[ 1 ≤ x ≤ y⊲(p, y ← p + q ∗ (y div x), y mod x).(p ∗ x + q ∗ y = α)≡ {substitutie}≡(p + q ∗ (y div x)) ∗ x + q ∗ (y mod x) = α{rekenen}p ∗ x + q ∗ ((y div x) ∗ x + y mod x) = α≡ {Definitie 2.14}p ∗ x + q ∗ y = α]| .De eerste guarded command legt aan Q dus de eisQ ∧ x ≤ y ⇒ x ≥ 1 ∧ y ≥ 0 ∧ p ∗ x + q ∗ y = αop. Omdat het probleem symmetrisch in p, y en q, x is, zien we meteen dat de tweede guardedcommandQ ∧ x ≥ y ⇒ x ≥ 0 ∧ y ≥ 1 ∧ p ∗ x + q ∗ y = αoplevert. Als oplossing voor Q kiezen we□x ≥ 1 ∧ y ≥ 1 ∧ p ∗ x + q ∗ y = α .Opgave 5.23 Bereken een zo zwak mogelijke Q met(a) {Q} if x ≤ y → m := x x ≥ y → m := y fi {m = x ↓ y} ,(b) {Q} if x ≤ y → m := x x ≥ y → m := y fi {m = x ↑ y} ,(c) {Q} if x < y → skip x > y → skip fi {true} ,(d) {Q} if true → x := 0 true → x := 1 fi {x = 1} ,(e) {Q} if true → x := 0 true → x := 1 fi {x ≤ 1} ,(f) {Q} if x ≤ 1 → x := x − 1 x ≥ 1 → x := x + 1 fi {x ≠ 1} .□


5.3. SELECTIE 55Opgave 5.24 Bewijs dat uit{Q} x := (B ? X : Y ) {R}volgt{Q} if B → x := X ¬B → x := Y fi {R} .□Voorbeeld 5.25 Gevraagd wordt expressies B en C van type bool te berekenen, zodanigdat{x > 0 ∧ y = µ > 0}if B → y := y − xC → y := y − y mod xfi{0 ≤ y < µ} .Volgens de bewijsregel voor de selectie moeten B en C voldoen aan{x > 0 ∧ y = µ > 0 ∧ B} y := y − x {0 ≤ y < µ} , (5.4){x > 0 ∧ y = µ > 0 ∧ C} y := y − y mod x {0 ≤ y < µ} , (5.5)x > 0 ∧ y > 0 ⇒ B ∨ C . (5.6)Met betrekking tot (5.4) merken we op|[ x > 0 ∧ y = µ > 0⊲(y ← y − x).(0 ≤ y < µ)≡{substitutie}0 ≤ y − x < µ≡ {y = µ}0 ≤ y − x < y≡ {x > 0}x ≤ y]| .Aan (5.4) is dus voldaan als we voor B kiezen x ≤ y .De berekening van C gaat als volgt:|[ x > 0 ∧ y = µ > 0⊲≡(y ← y − y mod x).(0 ≤ y < µ){substitutie}0 ≤ y − y mod x < µ≡ {y = µ}0 < y mod x ≤ y⇐ {y > 0}


56 HOOFDSTUK 5. PROGRAMMA’Sy mod x = y⇐ {Verzwakking}y mod x = y ∧ y div x = 0≡ {Stelling 2.15}0 ≤ y < x≡ {y > 0}y < x]| .Aan (5.5) is dus voldaan als we voor C kiezen y < x.Bij deze keuze van B en C geldt B ∨ C ≡ true , zodat ook aan (5.6) is voldaan.□Opgave 5.26 Bereken expressies B en C van type bool met(a) {x > 0 ∧ y > 0 ∧ x ≠ y }if B → x := x − yC → y := y − xfi{x > 0 ∧ y > 0}(b) {x = α ∧ y = β }if B → z := xC → z := yfi{z = α ↑ β }(c) {x = α}if B → x := −xC → skipfi{x = |α|}(d) {y = 2x ∨ y = −2x + 1}if B → x := x − yC → x := x + yfi; y := y + 1{y = 2x ∨ y = −2x + 1}(e) {x > 0 ∧ y > 0}if B → x, y := y, xC → x := x − yfi{x > 0 ∧ y > 0}(f) {x y ∗ z = α ∧ x ≥ 1 ∧ y ≥ 1}if B → x, y := x ∗ x, y div 2


5.3. SELECTIE 57□C → x, y, z := x ∗ x, (y − 1) div 2, z ∗ xfi{x y ∗ z = α ∧ x ≥ 1 ∧ y ≥ 0}(g) {x + y ∗ z = α}if B → x := x + yC → skipfi; y, z := 2 ∗ y, z div 2{x + y ∗ z = α}(h) {n ≥ 1 ∧ p + q ∗ 〈Σ i : 0 ≤ i < n : x i 〉 = α}if B → q := q ∗ (1 + x)C → p, q := p + q, q ∗ x ∗ (1 + x)fi{p + q ∗ 〈Σ i : 0 ≤ i < n div 2 : x 2i 〉 = α}(i) {y > 0 ∧ x mod y = 0}if B → x := x + 2 ∗ yC → x := x + yfi; y := 2 ∗ y{y > 0 ∧ x mod y = 0} .Opmerking Ingeval de expressies B en C niet in elke toestand gedefinieerd zijn, moet debewijsverplichtingQ ⇒ B ∨ Cworden vervangen door□Q ⇒ def .B ∧ def .C ∧ (B ∨ C) .Opmerking In een geannoteerd programma kunnen we verwijzingen opnemen naar de afzonderlijkeafleidingen die bij de constructie een rol hebben gespeeld. Bij een selectie wordendie verwijzingen als volgt geplaatst:{Q}if B → {Q ∧ B} S {R, Bewijs 1}C → {Q ∧ C} T {R, Bewijs 2}fi{R, Bewijs 3} .Hierin is Bewijs 1 het bewijs van {Q ∧ B} S {R}, Bewijs 2 het bewijs van {Q ∧ C} T {R}en Bewijs 3 het bewijs van Q ⇒ B ∨ C .□


58 HOOFDSTUK 5. PROGRAMMA’SOpmerking Selecties met meer dan twee guarded commands worden geheel analoog gedefinieerd.Voor{Q}if B → SC → TD → Ufi{R}zijn de bewijsverplichtingen□{Q ∧ B} S {R} ,{Q ∧ C} T {R} ,{Q ∧ D} U {R} ,Q ⇒ B ∨ C ∨ D .Opgave 5.27 Bereken expressies B, C, D van type bool met□{true}if B → u := u − 1C → u, v := −u + 2, −v + 3D → u, v := |u|, |v|fi{u + v > 2} .5.4 RepetitieDe repetitie biedt de mogelijkheid een opdracht meer dan eens te laten uitvoeren; bij gebruikvan repetities is het dus mogelijk dat een korte programmatekst de machine toch veelbewerkingen laat uitvoeren. De eenvoudigste vorm die een repetitie in GCL kan aannemen, isdo B → Sodmet B een expressie van type bool en S een rij opdrachten. Voorlopig nemen we even aandat B in elke toestand gedefinieerd is.Wordt deze repetitie gestart in een toestand waar B de waarde false heeft, dan is deuitvoering meteen beëindigd zonder wijziging van de toestand: het effect komt dan overeenmet skip. Wordt de repetitie echter gestart in een toestand waar B de waarde true heeft, danwordt S uitgevoerd, waarna met de uitvoering van de repetitie opnieuw wordt begonnen. Ditproces eindigt niet in alle gevallen. Het is de taak van de programmeur ervoor te zorgen datzijn programma’s alleen eindigende repetities bevatten; we zullen hieronder bespreken hoe hijdat kan bereiken.


5.4. REPETITIE 59Omdat de herhaling van S wordt voortgezet zolang B de waarde true heeft, zal na afloopvan de repetitie B zeker de waarde false hebben. Met andere woorden: er geldt{true} do B → S od {¬B} ,mits de repetitie eindigt. Voor sommige toepassingen is die wetenschap voldoende: beschouwbijvoorbeeld de specificatie|[ var int x⊲ S {x 3 + 3x 2 + x > 2000}]| .Na afloop vanx := 0; do x ∗ (1 + x ∗ (3 + x))


60 HOOFDSTUK 5. PROGRAMMA’S≡≡≡(n, x ← 0, 0).P{substitutie}0 ≤ 0 ≤ 100 ∧ 0 = 〈Σ i : 0 ≤ i < 0 : i 3 〉{rekenen ‖ Leeg domein}true ∧ 0 = 0{Eenheidselement ‖ rekenen}true .Voor (ii) volgt het uit|[ P ∧ n ≠ 100⊲(x ← x + n ∗ n ∗ n; n ← n + 1).P≡ {substitutie}0 ≤ n + 1 ≤ 100 ∧ x + n ∗ n ∗ n = 〈Σ i : 0 ≤ i < n + 1 : i 3 〉≡ {rekenen ‖ splits af i = n, gebruik n ≥ 0 wegens P }−1 ≤ n < 100 ∧ x + n 3 = 〈Σ i : 0 ≤ i < n : i 3 〉 + n 3⇐{rekenen}0 ≤ n < 100 ∧ x = 〈Σ i : 0 ≤ i < n : i 3 〉≡ {P ∧ n ≠ 100}true]| .We concluderen dat P ook na afloop van de repetitie geldt. Omdat dan ook n = 100, is naafloop dusx = 〈Σ i : 0 ≤ i < 100 : i 3 〉 .Formuleren we de in het bovenstaande gebruikte methode in algemene termen, dan verkrijgenwe:• Bewijsregel voor de repetitie: Laten P, Q, R predikaten, B een expressie vantype bool en I, S rijen opdrachten zijn. Het Hoaretripel{Q} I; do B → S od {R}geldt als voldaan is aan{Q} I {P } , (5.7){P ∧ B} S {P } , (5.8)P ∧ ¬B ⇒ R (5.9)en de repetitie eindigt.Het predikaat P heet een invariant van de repetitie. Opdrachtenrij I heet de initialisatie en Sde body van de repetitie; expressie B heet de guard. Ingeval de guard niet in alle toestandenis gedefinieerd, dienen we aan de invariant nog de extra eisP ⇒ def .Bop te leggen.Verwijzing naar de verschillende bewijzen die voor het toepassen van bovenstaande regelnodig zijn, geschiedt in een geannoteerd programma als volgt:


5.4. REPETITIE 61{Q}I{inv P , Bewijs 1}; do B → {P ∧ B} S {P , Bewijs 2} od{P ∧ ¬B , Bewijs 3}{R, Bewijs 4} .Hierin is Bewijs 1 het bewijs van (5.7), Bewijs 2 het bewijs van (5.8), Bewijs 4 het bewijs van(5.9) en Bewijs 3 het bewijs van de eindiging.Voorbeeld 5.28 Gevraagd worden expressies E en F , zó, datP : 0 ≤ n ≤ N ∧ f = n!invariant is van de repetitie{N ≥ 0}n, f := 0, E; do n ≠ N → f := F; n := n + 1od .De berekening van E gaat als volgt:|[ N ≥ 0⊲(n, f ← 0, E).P≡ {substitutie}0 ≤ 0 ≤ N ∧ E = 0!≡ {N ≥ 0 ‖ 0! = 1}true ∧ E = 1≡ {Eenheidselement}E = 1]| .Voor E kiezen we dus de expressie 1.De berekening van F gaat als volgt:|[ P ∧ B⊲(f ← F ; n ← n + 1).P≡ {substitutie}0 ≤ n + 1 ≤ N ∧ F = (n + 1)!≡ {rekenen ‖ (n + 1)! = n! ∗ (n + 1)}⇐−1 ≤ n < N ∧ F = n! ∗ (n + 1){rekenen}0 ≤ n < N ∧ F = n! ∗ (n + 1)≡ {P ∧ B }true ∧ F = f ∗ (n + 1)


62 HOOFDSTUK 5. PROGRAMMA’S≡]| .{Eenheidselement}F = f ∗ (n + 1)Voor F kiezen we dus de expressie f ∗ (n + 1).□Opgave 5.29 (a) Implementeer de specificatie|[ con int a[0 . . 100); var int n, x {P ∧ n = α < 100}⊲ S {(n ← n + 1).P ∧ n = α}; n := n + 1 {P ∧ n = α + 1}]| ,waarin predikaat P is gegeven doorP : x = 〈Σ i : 0 ≤ i < n ∧ a.i > 0 : a.i〉 .□(b) Schrijf een repetitie die (n ← 100).P bewerkstelligt.Opgave 5.30 Dezelfde vragen voor P gegeven door□P : x = 〈↑ i : −1 ≤ i < n ∧ (i = −1 ∨ a.i > 0) : i〉 .Opgave 5.31 Bepaal expressies X en Z , zó, dat□{x = α ∧ y = β ≥ 0}z := 0{inv P : y ≥ 0 ∧ z + x ∗ y = α ∗ β }; do y ≠ 0 → if y mod 2 = 0 → x := X; y := y div 2y mod 2 = 1 → z := Z; y := y − 1fiod{P ∧ y = 0}{z = α ∗ β } .Opgave 5.32 Bepaal expressies X en B , zó, dat□{x = α ≥ 0 ∧ y = β ≥ 1}z := 0{inv x ≥ 0 ∧ y ≥ 1 ∧ z + x div y = α div β }; do B → x := X; z := z + 1 od{z = α div β } .


5.4. REPETITIE 63Opgave 5.33 Bepaal expressies X en Y , zó, dat□n, x := 0, X{inv 0 ≤ n ≤ 100 ∧ x = 〈∃i : 0 ≤ i < n : a.i = 0〉}; do n ≠ 100 → x := Y ; n := n + 1 od{x = 〈∃i : 0 ≤ i < 100 : a.i = 0〉} .Opgave 5.34 Implementeer de specificatie|[ con int a[0 . . 100); var int x⊲ S {x = 〈#i : 1 ≤ i < 100 : a.i > a.(i − 1)〉}]|door middel van een repetitie met invariant□1 ≤ n ≤ 100 ∧ x = 〈#i : 1 ≤ i < n : a.i > a.(i − 1)〉 .Opgave 5.35 Implementeer de specificatie|[ con int N {N ≥ 1}; var int x⊲ S {x = 〈↓ i : 2 i ≥ N : i〉}]|door middel van een repetitie met invariant□0 ≤ x ≤ 〈↓ i : 2 i ≥ N : i〉 .Opgave 5.36 Implementeer de specificatie|[ con int a[0 . . 100); var int x⊲ S {x = 〈↑ i : 0 ≤ i < 100 : a.i〉}]|door middel van een repetitie met invariant□1 ≤ n ≤ 100 ∧ x = 〈↑ i : 0 ≤ i < n : a.i〉 .


64 HOOFDSTUK 5. PROGRAMMA’SHet eindigen van de uitvoering van repetities bewijzen we door een bovengrens aan tegeven voor het aantal repetitieslagen. We beschouwen een repetitie met guard B , body S eninvariant P . Zij V een formule in de programmavariabelen die in elke toestand een geheelgetal voorstelt. Aan V zullen we twee eisen stellen:(i) Aan het begin van elke repetitieslag is de waarde van V ten minste 0. Hiervoor kunnenwe zorgen door te eisen datP ∧ B ⇒ V ≥ 0 .(ii) In elke repetitieslag neemt de waarde van V af. Dat wil zeggen: als de waarde van Vaan het begin van de repetitieslag α is, is die na afloop van de repetitieslag ten hoogsteα − 1. Hiervoor kunnen we zorgen door te eisen{P ∧ B ∧ V = α} S {V < α} .Als aan (i) en (ii) is voldaan, is bij elke evaluatie van de guard de waarde van V + 1 eenbovengrens voor het aantal repetitieslagen dat nog volgt. We noemen V een variante functievan de repetitie. De variante functie wordt in een geannoteerd programma samen met deinvariant vermeld, in een commentaar van de vorm{inv P ; vf V } .Toevoegen van de eisen voor de variante functie aan de bewijsregel geeft• Bewijsregel voor de repetitie: Laten P, Q, R predikaten, B een expressie vantype bool, V een geheelwaardige formule en I, S rijen opdrachten zijn. Het Hoaretripel{Q} I; do B → S od {R}geldt als voldaan is aan{Q} I {P } ,{P ∧ B} S {P } ,P ∧ ¬B ⇒ Ren de eindigingseisenP ∧ B ⇒ V ≥ 0 ,{P ∧ B ∧ V = α} S {V < α} .Voorbeeld 5.37 Beschouw de repetitie{N ≥ 0}n, f := 0, 1{inv P : 0 ≤ n ≤ N ∧ f = n!}; do n ≠ N → f := f ∗ (n + 1); n := n + 1od


5.4. REPETITIE 65die in Voorbeeld 5.28 is geconstrueerd. Het valt ons op dat in elke repetitieslag een toekenningn := n + 1 voorkomt. Als we een variante functie kiezen van de vorm C − n, met C eenconstante, is aan eis (ii) voldaan. Voor eis (i) moeten we C zó kiezen dat uit invariant enguard volgt n ≥ C ; inspectie van P leert dat C = N een goede keuze is. Als variante functiekiezen we dusV : N − n .Uitwerken van de bewijsverplichtingen geeft nu voor (i)|[ P ∧ n ≠ N⊲V ≥ 0≡ {definitie V }N − n ≥ 0≡{rekenen}n ≤ N≡ {P }true]| .Voor (ii) krijgen we|[ P ∧ n ≠ N ∧ V = α⊲(f ← f ∗ (n + 1); n ← n + 1).(V < α)≡ {definitie V }(f ← f ∗ (n + 1); n ← n + 1).(N − n < α)≡{substitutie}N − (n + 1) < α≡ {V = α}N − (n + 1) < V≡ {definitie V }true]| .□Er valt op dat de specificatievariabele α na voltooiing van de substitutie onmiddellijk doorV wordt vervangen. Exploiteren van dit inzicht kan leiden tot kortere berekeningen, zoalsonderstaand lemma laat zien.Lemma 5.38 Zij X een expressie met def .X ≡ true . Het Hoaretripelvolgt uit{P ∧ B ∧ V = α} x := X {V < α} (5.10)P ∧ B ⇒ (x ← X).V < V . (5.11)


66 HOOFDSTUK 5. PROGRAMMA’SBewijs Wegens de bewijsregel voor toekenning is (5.10) equivalent metP ∧ B ∧ V = α ⇒ (x ← X).(V < α) .Veronderstel dat (5.11) geldt. Dan|[ P ∧ B ∧ V = α⊲(x ← X).(V < α)≡{substitutie}(x ← X).V < α≡ {V = α}(x ← X).V < V⇐ {(5.11)}P ∧ B≡ {P ∧ B }true]| .□Gebruik van Lemma 5.38 geeft gewoonlijk compacter berekeningen dan rechtstreeks gebruikvan de formule met α uit de bewijsregel.Voorbeeld 5.39 Het bewijs van (ii) uit Voorbeeld 5.37 kunnen we nu als volgt opschrijven:|[ P ∧ n ≠ N⊲(f ← f ∗ (n + 1); n ← n + 1).V < V≡ {definitie V ; substitutie}N − (n + 1) < N − n≡ {rekenen}true]| .□Opgave 5.40 Bewijs de eindiging van de repetitie in(a) Opgave 5.31;(b) Opgave 5.32;(c) Opgave 5.35.□Opgave 5.41 Bewijs de eindiging van{x ≥ 0 ∧ y ≥ 0}do x > y → if x mod 2 = 0 ∨ y mod 2 = 0 → x, y := x − 1, y + 1x mod 2 = 1 ∨ y mod 2 = 1 → x, y := x + x mod 2, y + y mod 2fiod{x ≤ y } .


5.4. REPETITIE 67□Opgave 5.42 Bewijs de eindiging van□{x > 0 ∧ y > 0 ∧ p ≥ 0 ∧ N = x ∗ y + p ∧ (p mod x = 0 ∨ p mod y = 0)}do p ≠ 0 → if p mod x = 0 → y, p := y + 1, p − xp mod y = 0 → x, p := x + 1, p − yfiod{N = x ∗ y } .We zullen ook repetities met meer dan één guarded command beschouwen. Zo isdo B → SC → Todeen afkorting voordo B ∨ C → if B → SC → Tfiod .Opgave 5.43 Schrijf de bewijsregels voor een repetitie met twee en drie guarded commandsvolledig uit.□Opgave 5.44 Bereken expressies B en C van type bool met□{p ≥ 1 ∧ q ≥ 1 ∧ r ≥ 1 ∧ 〈∀i : 1 ≤ i < r : i mod p ≠ 0 ∨ i mod q ≠ 0〉}do B → r := r + p − r mod pC → r := r + q − r mod qod{r = 〈↓ i : i ≥ 1 ∧ i mod p = 0 ∧ i mod q = 0 : i〉} .Opgave 5.45 Bewijs dat{true }do x < y → x, y := y, x{z ≤ y ≤ x} .□y < z → y, z := z, y odOpgave 5.46 Bewijs dat{a ≥ 1 ∧ b ≥ 1 ∧ u ≥ 0 ∧ v ≥ 0 ∧ x = u ∗ a − v ∗ b}do x > 0 → x, u := x − a, u − 1 x < 0 → x, v := x + b, v − 1 od{x = 0} .□


68 HOOFDSTUK 5. PROGRAMMA’S


Hoofdstuk 6Variatie van constante6.1 Recurrente betrekkingenIn het vorige hoofdstuk hebben we geleerd hoe we, uitgaande van een gegeven invariant,repetities kunnen construeren. Dit hoofdstuk en het volgende gaan over de vraag hoe we aande invariant komen.In eerste instantie beschouwen we een specifiek, maar veel voorkomend geval. Zij eensf een functie op de natuurlijke getallen, gedefinieerd door een recurrente betrekking van devormf.0 = A ,f.(n + 1) = G.n.(f.n) voor n ≥ 0 ,waarin A een expressie is en G.E.F een expressie is als E en F dat zijn. De specificatie vanhet te construeren programma is|[ con int N {N ≥ 0}; var int r⊲ S {r = f.N }]| .Voor de oplossing van dit programmeerprobleem vervangen we de constante N die in depostconditie voorkomt door een verse programmavariabele, zeg n. (Daar komt de naam‘Variatie van constante’ vandaan.) Introductie van een verse programmavariabele gaat in detaal GCL als volgt: voor S kiezen we een binnenblok, dat is een opdracht van de vorm|[ int n⊲ S1]| ,waarin S1 moet voldoen aan dezelfde specificatie als S , maar nu mag werken op de toestandsruimtedie behalve de coördinaten r en N ook de coördinaat n heeft. Merk op dat dedeclaraties van lokale variabelen in binnenblokken niet worden voorafgegaan door var of con.Vervangen van N in de postconditie door n betekent dat we voor S1 een repetitie metinitialisatie kiezen die als invariant de conjunctie van69


70 HOOFDSTUK 6. VARIATIE VAN CONSTANTEP 0: 0 ≤ n ≤ N ,P 1: r = f.nheeft. Er geldt P 1 ∧ n = N ⇒ r = f.N , dus de repetitie moet worden voortgezet zolangn ≠ N . Als we ervoor zorgen dat n in elke repetitieslag met 1 wordt verhoogd, zal de repetitiezeker eindigen. (De details van het eindigingsbewijs zijn uitgeschreven in Voorbeeld 5.37 en5.39, die van de invariantie van P 0 in Voorbeeld 5.28. Bewijzen die zo eenvoudig zijn zullenwe in het vervolg niet meer opschrijven.)Ons ontwerp heeft nu dus de volgende vorm:{N ≥ 0}|[ int n⊲ I{inv P 0..1, Bewijs 1; vf N − n}; do n ≠ N → {P 0..1 ∧ n ≠ N }T {(n ← n+1).P 1, Bewijs 2}; n := n + 1{P 0..1}od{P 0..1 ∧ n = N }]|{r = f.N } .(We hebben hier P 0..1 geschreven als afkorting voor P 0 ∧ P 1. Dat zullen we vaker doen.)In de bewijzen 1 en 2 construeren we een initialisatie I respectievelijk een body T diebovenstaande annotatie correct maken.Bewijs 1 In de definitie van f wordt het punt 0 afzonderlijk behandeld. Omdat de preconditieN ≥ 0 is, is 0 tevens de enige constante waarde die we voor n kunnen invullen opdatP 0 geldt. Deze beide overwegingen doen ons voor I een toekenning r, n := R, 0 proberen.Dit geeft|[ N ≥ 0⊲≡(r, n ← R, 0).P 0..1{substitutie}0 ≤ 0 ≤ N ∧ R = f.0≡ {N ≥ 0 ‖ definitie van f }R = A]| .Voor I kiezen we dus n, r := 0, A.□Bewijs 2 In verband met het eindigingsargument dient T de waarde van n niet te wijzigen.Voor T proberen we dus een toekenning aan r. We beperken ons in de berekening tot hetrechterlid van P 1.


6.1. RECURRENTE BETREKKINGEN 71|[ P 0..1 ∧ n ≠ N⊲(n ← n + 1).(f.n)= {substitutie}f.(n + 1)= {definitie van f ; gebruik n ≥ 0 wegens P 0}G.n.(f.n)= {P 1}G.n.r]| .Voor T kiezen we dus de toekenning r := G.n.r.□Hiermee is de volgende stelling bewezen:Stelling 6.1 Zij f een functie op de natuurlijke getallen die voldoet aan de recurrente betrekkingf.0 = A ,f.(n + 1) = G.n.(f.n) voor n ≥ 0 ,waarin A een expressie is en G.E.F een expressie is als E en F dat zijn. Dan geldt□{N ≥ 0}|[ int n⊲ n, r := 0, A{inv 0 ≤ n ≤ N ∧ r = f.n; vf N − n}; do n ≠ N → r := G.n.r; n := n + 1od]|{r = f.N } .Bij het toepassen van deze stelling geven we f, A en G gewoonlijk niet expliciet een naam:het is eenvoudiger te rekenen met expressies, zoals in het onderstaande voorbeeld.Voorbeeld 6.2 Beschouw de specificatie|[ con int N, X {N ≥ 0}; con int a[0 . . N); var int r⊲ S {r = 〈Σ i : 0 ≤ i < N : a.i ∗ X N−1−i 〉}]| .We vervangen beide voorkomens van N in de postconditie door een verse variabele n enkrijgen zo als invariant


72 HOOFDSTUK 6. VARIATIE VAN CONSTANTEP 0 : 0 ≤ n ≤ N ,P 1 : r = 〈Σ i : 0 ≤ i < n : a.i ∗ X n−1−i 〉 .Als initialisatie kiezen we een toekenning n, r := 0, R; die bewerkstelligt in elk geval P 0. Deberekening van R gaat als volgt:Bewijs 1(n ← 0).〈Σ i : 0 ≤ i < n : a.i ∗ X n−1−i 〉= {substitutie}〈Σ i : 0 ≤ i < 0 : a.i ∗ X −1−i 〉= {Leeg domein}0 .□Voor de body leiden we afBewijs 2|[ P 0..1 ∧ n ≠ N⊲(n ← n + 1).〈Σ i : 0 ≤ i < n : a.i ∗ X n−1−i 〉= {substitutie}〈Σ i : 0 ≤ i < n + 1 : a.i ∗ X n−i 〉= {Splits af i = n, gebruik n ≥ 0 wegens P 0}〈Σ i : 0 ≤ i < n : a.i ∗ X n−i 〉 + a.n= {Distributie van ∗ over Σ}X ∗ 〈Σ i : 0 ≤ i < n : a.i ∗ X n−1−i 〉 + a.n= {P 1}X ∗ r + a.n]| .□Hiermee hebben we als oplossing afgeleid{N ≥ 0}|[ int n⊲ n, r := 0, 0{inv P 0..1, Bewijs 1; vf N − n}; do n ≠ N → {P 0..1 ∧ n ≠ N }r := X ∗ r + a.n {(n ← n+1).P 1, Bewijs 2}; n := n + 1{P 0..1}od]|{r = 〈Σ i : 0 ≤ i < N : a.i ∗ X N−1−i 〉} .Dit programmafragment staat bekend als Horner’s schema en dateert uit 1819.□


6.2. VROEGTIJDIGE BEËINDIGING 73Opgave 6.3 Implementeer de specificatie|[ con int N {N ≥ 1}; con int a[0 . . N); var int r⊲ S {R}]| ,waarin R het volgende predikaat is:□(a) r = 〈Σ i : 0 ≤ i < N : a.i mod 10〉 ,(b) r = 〈#i : 0 ≤ i < N : a.i = 10〉 ,(c) r = 〈Σ i : 0 ≤ i < N ∧ a.i = a.(N−1−i) : i〉 ,(d) r = 〈↑ i : 0 ≤ i < N : |a.i|〉 ,(e) 0 ≤ r < N ∧ |a.r| = 〈↑ i : 0 ≤ i < N : |a.i|〉 .Opgave 6.4 Dezelfde vraag voor(a) r = 〈↑ i : i ≥ 0 ∧ i 2 < N : a.(i 2 )〉 ,(b) 2r = 〈Σ i : 0 ≤ i < N ∧ a.i mod 2 = 0 : a.i〉 ,(c) r = 〈↓ i : (0 ≤ i < N ∧ a.i = 7) ∨ i = N : i〉 .□6.2 Vroegtijdige beëindigingBeschouw de volgende specificatie:|[ con int N {N ≥ 0}; con bool a[0 . . N); var bool r⊲ S {r = 〈∀i : 0 ≤ i < N : a.i〉}]| .Gebruik makend van de techniek uit de vorige paragraaf introduceren we een verse variabelen en kiezen we als invariantP 0 : 0 ≤ n ≤ N ,P 1 : r = 〈∀i : 0 ≤ i < n : a.i〉 .Voor de initialisatie proberen we een toekenning van de vorm n, r := 0, R. Die bewerkstelligtin elk geval P 0; de berekening van R gaat als volgt:


74 HOOFDSTUK 6. VARIATIE VAN CONSTANTEBewijs 1〈∀i : 0 ≤ i < 0 : a.i〉= {Leeg domein}true .□Voor de body geldtBewijs 2|[ P 0..1 ∧ n ≠ N⊲〈∀i : 0 ≤ i < n + 1 : a.i〉= {Splits af i = n, gebruik n ≥ 0 wegens P 0}〈∀i : 0 ≤ i < n : a.i〉 ∧ a.n= {P 1}r ∧ a.n]| .□Hiermee is het volgende programma afgeleid:{N ≥ 0}|[ int n⊲ n, r := 0, true{inv P 0..1, Bewijs 1; vf N − n}; do n ≠ N → {P 0..1 ∧ n ≠ N }r := r ∧ a.n {(n ← n+1).P 1, Bewijs 2}; n := n + 1{P 0..1}od{P 0..1 ∧ n = N }]|{r = 〈∀i : 0 ≤ i < N : a.i〉} .Bij nader inzien heeft dit programma echter een belangrijk nadeel: het inspecteert altijd hethele array a, ook als onderweg een waarde false in a is aangetroffen en daarom duidelijk isdat de repetitie gegarandeerd met de waarde false voor r zal eindigen. Om dit nadeel teondervangen, dient de berekening van de guard n ≠ N als volgt te worden verscherpt.Bewijs 3|[ P 0..1⊲r = 〈∀i : 0 ≤ i < N : a.i〉≡ {Domeinsplitsing, gebruik P 0}r = (〈∀i : 0 ≤ i < n : a.i〉 ∧ 〈∀i : n ≤ i < N : a.i〉)


6.2. VROEGTIJDIGE BEËINDIGING 75≡ {P 1}r = (r ∧ 〈∀i : n ≤ i < N : a.i〉)⇐ {Nulelement ‖ Eenheidselement}r = false ∨ 〈∀i : n ≤ i < N〉 = true⇐ {Leeg domein}r = false ∨ n = N≡ {de Morgan}¬(r = true ∧ n ≠ N)]| .□Als guard hebben we nu het predikaat r = true ∧ n ≠ N gevonden. Kortheidshalve zullen wedit als r ∧ n ≠ N noteren. Met gebruikmaking van deze guard kan de body ook nog wordenvereenvoudigd:Bewijs 4|[ P 0..1 ∧ r ∧ n ≠ N⊲〈∀i : 0 ≤ i < n + 1 : a.i〉= {Bewijs 2, gebruik P 0..1}r ∧ a.n= {r}a.n]| .□Als verbeterd programma vinden we zo{N ≥ 0}|[ int n⊲ n, r := 0, true{inv P 0..1, Bewijs 1; vf N − n}; do r ∧ n ≠ N → {P 0..1 ∧ r ∧ n ≠ N }r := a.n {(n ← n+1).P 1, Bewijs 4}; n := n + 1{P 0..1}od{P 0..1 ∧ ¬(r ∧ n ≠ N)}]|{r = 〈∀i : 0 ≤ i < N : a.i〉, Bewijs 3} .Dit programma heeft het voordeel dat de repetitie stopt zodra het eerste array-element metde waarde false is aangetroffen.Opgave 6.5 Implementeer de volgende specificatie:


76 HOOFDSTUK 6. VARIATIE VAN CONSTANTE□|[ con int N {N ≥ 1}; con int a[0 . . N); var bool r⊲ S {r = 〈∃i : 0 ≤ i < N : a.i ≠ a.0〉}]| .Opgave 6.6 Schrijf een programmafragment dat onderzoekt of een gegeven N een priemgetalis. Een formele specificatie is□|[ con int N {N ≥ 2}; var bool r⊲ S {r = 〈∀i : i ≥ 2 ∧ i 2 ≤ N : N mod i ≠ 0〉}]| .Opgave 6.7 Implementeer de specificatie|[ con int N {N ≥ 1}; con int a[0 . . N); var bool r⊲ S {R}]| ,waarin R het volgende predikaat is:□(a) r = 〈∀i : 0 < i < N : a.(i − 1) < a.i〉 ,(b) r = 〈∀i, j : 0 ≤ i < N ∧ 0 ≤ j < N : a.i − a.j ≤ 1〉 ,(c) r = 〈∃C : true : 〈∀i : 0 ≤ i < N : a.i = C〉〉 .6.3 Versterking van de invariantWanneer we de techniek van variatie van constante toepassen voor het berekenen van eenfunctiewaarde f.N , komt het regelmatig voor dat het uitdrukken van f.(n + 1) in n en f.nalleen lukt onder aanname van een extra predikaat Q dat niet uit de invariant of de guardvolgt. De berekening krijgt dan de vorm|[ P 0..1 ∧ n ≠ N⊲(n ← n + 1).(f.n)= {substitutie}f.(n + 1)= {• Q}G.n.(f.n)]| .


6.3. VERSTERKING VAN DE INVARIANT 77Hierin betekent de hint {• Q} dat de stap in kwestie alleen geldig is onder aanname van Q.De conclusie die we uit deze berekening kunnen trekken, is dusP 0..1 ∧ n ≠ N ∧ Q ⇒ (n ← n + 1).(f.n) = G.n.(f.n)en we hadden Q dus net zo goed in de context al kunnen vermelden, ware het niet dat denoodzaak tot invoeren van Q pas tijdens de berekening is gebleken.Het is nu de vraag op welke manier we het gebruik van Q op deze plaats legaal en zinvolkunnen maken. We zouden in de repetitiebody een extra berekening met postconditie Qkunnen opnemen, maar die methode leidt gewoonlijk tot inefficiënte programma’s. Een beteremethode is het versterken van de invariant met het predikaat Q. De initialisatie moet dan zoworden uitgebreid dat die ook Q bewerkstelligt en ook de body van de repetitie moet wordenaangepast om voor invariantie van Q te zorgen.Voorbeeld 6.8 De rij van Fibonacci is gedefinieerd doorfib.0 = 0 ,fib.1 = 1 ,fib.(n + 2) = fib.n + fib.(n + 1) voor n ≥ 0 .Beschouw het volgende programmeerprobleem:|[ con int N {N ≥ 0}; var int r⊲ S {r = fib.N }]| .Variatie van constante geeft aanleiding tot een verse variabele n en de invariantenP 0 : 0 ≤ n ≤ N ,P 1 : r = fib.n .Voor de initialisatie hebben weBewijs 1(n ← 0).(fib.n)= {substitutie}fib.0= {definitie van fib}0 .□Voor de body van de repetitie rekenen we als volgt:


78 HOOFDSTUK 6. VARIATIE VAN CONSTANTEBewijs 2|[ P 0..1 ∧ n ≠ N⊲(n ← n + 1).(fib.n)= {substitutie}fib.(n + 1)= {• s = fib.(n + 1)}s]| .□In verband met de extra aanname in Bewijs 2, die nodig was omdat we fib.(n + 1) nietgemakkelijk kunnen uitdrukken met behulp van alleen P 0..1 ∧ n ≠ N , versterken we deinvariant metP 2 : s = fib.(n + 1) .Er geldt dan{P 0..2 ∧ n ≠ N } r := s {(n ← n + 1).P 1, Bewijs 2} .We dienen nu echter de initialisatie zodanig aan te passen dat die ook P 2 bewerkstelligt ende body zo dat die ook P 2 invariant houdt. Voor de initialisatie hebben weBewijs 3(n ← 0).(fib.(n + 1))= {substitutie}fib.1= {definitie van fib}1 .□Voor de body hebben weBewijs 4|[ P 0..2 ∧ n ≠ N⊲(n ← n + 1).(fib.(n + 1))= {substitutie}fib.(n + 2)= {definitie van fib, gebruik n ≥ 0 wegens P 0}fib.n + fib.(n + 1)= {P 1 ‖ P 2}r + s]| .□


6.3. VERSTERKING VAN DE INVARIANT 79Hiermee is bewezen dat{P 0..2 ∧ n ≠ N } s := r + s {(n ← n+1).P 2, Bewijs 4} .De toekenningen aan r en s vereisen beide dezelfde preconditie, namelijk P 0..2 ∧ n ≠ N .We combineren ze daarom tot een meervoudige toekenning, namelijk{P 0..2 ∧ n ≠ N } r, s := s, r + s {(n ← n+1).P 1..2, Bewijs 2, 4} .Daarmee is het volgende programma afgeleid:□{N ≥ 0}|[ int r, s⊲ n, r, s := 0, 0, 1{inv P 0..2, Bewijs 1, 3; vf N − n}; do n ≠ N → {P 0..2 ∧ n ≠ N }r, s := s, r + s {(n ← n+1).P 1..2, Bewijs 2, 4}; n := n + 1{P 0..2}od]|{r = fib.N } .Voorbeeld 6.9 Beschouw de volgende specificatie:|[ con int N {N ≥ 0}; con int a[0 . . N); var int r⊲ S {r = 〈↑ p, q : 0 ≤ p ≤ q ≤ N : 〈Σ i : p ≤ i < q : a.i〉〉}]| .Voor 0 ≤ p ≤ q ≤ N noemen we a[p . . q) een segment van a[0 . . N). Dit programmeerprobleemstaat dan ook bekend als het bepalen van de maximale segmentsom. Ter vereenvoudigingvan de nu volgende berekening voeren we, als afkorting, voor 0 ≤ p ≤ q ≤ N denotatiesom.p.q = 〈Σ i : p ≤ i < q : a.i〉in.Variatie van constante geeftP 0 : 0 ≤ n ≤ N ,P 1 : r = 〈↑ p, q : 0 ≤ p ≤ q ≤ n : som.p.q〉 .Voor de initialisatie hebben we


80 HOOFDSTUK 6. VARIATIE VAN CONSTANTEBewijs 1(n ← 0).〈↑ p, q : 0 ≤ p ≤ q ≤ n : som.p.q〉= {substitutie}〈↑ p, q : 0 ≤ p ≤ q ≤ 0 : som.p.q〉= {Eenpuntsregel}som.0.0= {Bewijs 2}0 .□Hierin is gebruik gemaakt van de volgende eigenschap van de functie som:Bewijs 2|[ 0 ≤ p ≤ N⊲som.p.p= {definitie van som}〈Σ i : p ≤ i < p : a.i〉= {Leeg domein}0]| .□Nu onderzoeken we de toekenning aan r in de body van de repetitie.Bewijs 3|[ P 0..1 ∧ n ≠ N⊲(n ← n + 1).〈↑ p, q : 0 ≤ p ≤ q ≤ n : som.p.q〉= {substitutie}〈↑ p, q : 0 ≤ p ≤ q ≤ n + 1 : som.p.q〉= {splits af q = n + 1}〈↑ p, q : 0 ≤ p ≤ q ≤ n : som.p.q〉 ↑ 〈↑ p : 0 ≤ p ≤ n + 1; som.p.(n + 1)〉= {P 1}r ↑ 〈↑ p : 0 ≤ p ≤ n + 1 : som.p.(n + 1)〉= {• s = 〈↑ p : 0 ≤ p ≤ n + 1 : som.p.(n + 1)〉}r ↑ s]| .□De toegevoegde veronderstelling in de met • gemarkeerde regel kan niet worden gerealiseerddoor s = 〈↑ p : 0 ≤ p ≤ n + 1 : som.p.(n + 1)〉 invariant te houden. Dit predikaat is namelijk


6.3. VERSTERKING VAN DE INVARIANT 81alleen gedefinieerd voor 0 ≤ n < N , terwijl het de bedoeling is dat de invariant ook geldt als,na afloop van de repetitie, n = N geldt. We breiden daarom de invariant uit metP 2 : s = 〈↑ p : 0 ≤ p ≤ n : som.p.n〉 .Er geldt dan{P 0..1 ∧ (n ← n+1).P 2 ∧ n ≠ N } r := r ↑ s {(n ← n+1).P 1, Bewijs 3} .Dit leidt tot een ontwerp van de vorm{N ≥ 0}|[ int n, s⊲ n, r, s := 0, 0, E{inv P 0..2, Bewijs 1, 4; vf N − n}; do n ≠ N → {P 0..2 ∧ n ≠ N }s := F {(n ← n+1).P 2, Bewijs 5}; r := r ↑ s {(n ← n+1).P 1, Bewijs 3}; n := n + 1{P 0..1}od{P 0..2 ∧ n = N }]|{r = 〈↑ p, q : 0 ≤ p ≤ q ≤ N : som.p.q〉} .Merk op dat de toekenning r := r ↑ s uit Bewijs 3 moet worden voorafgegaan door eentoekenning s := F die (n ← n+1).P 2 bewerkstelligt. Die laatste berekenen we in Bewijs 5;we onderzoeken nu eerst de initialisatie van P 2.Bewijs 4(n ← 0).〈↑ p : 0 ≤ p ≤ n : som.p.n〉= {substitutie}〈↑ p : 0 ≤ p ≤ 0 : som.p.0〉= {Eenpuntsregel}som.0.0= {Bewijs 2, gebruik N ≥ 0}0 .□Bewijs 5|[ P 0..2 ∧ n ≠ N⊲(n ← n + 1).〈↑ p : 0 ≤ p ≤ n : som.p.n〉= {substitutie}〈↑ p : 0 ≤ p ≤ n + 1 : som.p.(n + 1)〉


82 HOOFDSTUK 6. VARIATIE VAN CONSTANTE= {splits af p = n + 1, gebruik n ≥ 0 wegens P 0}〈↑ p : 0 ≤ p ≤ n : som.p.(n + 1)〉 ↑ som.(n + 1).(n + 1)= {(Bewijs 6 ‖ Bewijs 2), gebruik P 0 ∧ n ≠ N }〈↑ p : 0 ≤ p ≤ n : som.p.n + a.n〉 ↑ 0= {Distributie van + over ↑}(〈↑ p : 0 ≤ p ≤ n : som.p.n〉 + a.n) ↑ 0= {P 2}(s + a.n) ↑ 0]| .□Hier is gebruik gemaakt van de volgende eigenschap van som:Bewijs 6|[ 0 ≤ p ≤ n⊲som.p.(n + 1)= {definitie van som}〈Σ i : p ≤ i < n + 1 : a.i〉= {splits af i = n, gebruik p ≤ n}〈Σ i : p ≤ i < n : a.i〉 + a.n= {definitie van som}som.p.n + a.n]| .□Uit het bovenstaande kunnen we concluderen{P 0..2 ∧ n ≠ N } s := (s + a.n) ↑ 0 {(n ← n+1).P 2, Bewijs 5} .Omdat de toekenning aan s geen invloed heeft op n of r, gelden na afloop ook P 0..1 ∧ n ≠ Nnog, zodat de preconditie voor de toekenning aan r uit Bewijs 3 is bereikt. Hiermee is hetvolgende programma voor de berekening van de minimale segmentsom verkregen:□{N ≥ 0}|[ int n, s⊲ n, r, s := 0, 0, 0{inv P 0..2, Bewijs 1, 4; vf N − n}; do n ≠ N → {P 0..2 ∧ n ≠ N }s := (s + a.n) ↑ 0 {(n ← n+1).P 2, Bewijs 5}; r := r ↑ s {(n ← n+1).P 1, Bewijs 3}; n := n + 1{P 0..2}od]|{r = 〈↑ p, q : 0 ≤ p ≤ q ≤ N : som.p.q〉} .


6.3. VERSTERKING VAN DE INVARIANT 83Opgave 6.10 Implementeer de specificatie|[ con int N {N ≥ 1}; con int a[0 . . N); var int r⊲ S {R}]| ,waarin R wordt gegeven door□(a) r = 〈Σ i, j : 0 ≤ i < j < N : a.i + a.j〉 ,(b) r = 〈↓ i, j : 0 ≤ i ≤ j < N : a.i − a.j〉 ,(c) r = 〈#i : 0 ≤ i < N : 〈∀j : 0 ≤ j < i : a.j < a.i〉〉 ,(d) r = 〈#i, j : 0 ≤ i < j < N : a.i ∗ a.j ≥ 0〉 ,(e) r = 〈#i : 0 ≤ i < N : 〈∀j : i ≤ j < N : a.j > 0〉〉 ,(f) r = 〈#i : 1 ≤ i < N : a.i = 〈↑ j : 0 ≤ j < i : a.j + 1〉〉 ,(g) r = 〈↑ i, j : 0 ≤ i ≤ j ≤ N ∧ 〈∀k : i ≤ k < j : a.k > 0〉 : j − i〉 ,(h) r = 〈↑ i, j : 0 ≤ i ≤ j < N : 〈#k : i ≤ k < j : a.k > 0〉〉 .Opgave 6.11 Implementeer de specificatie|[ con int N {N ≥ 1}; con int a[0 . . N); var bool r⊲ S {R}]| ,waarin R wordt gegeven door□(a) r = 〈∃i : 0 ≤ i ≤ N : 〈∀j : 0 ≤ j < i : a.j = 2〉 ∧ 〈∀j : i ≤ j < N : a.j = 5〉〉 ,(b) r = 〈∃i, j : 0 ≤ i < j < N : a.i − a.j > 10〉 ,(c) r = 〈∀i, j : 0 ≤ i ≤ j ≤ N : a.i ∗ a.j ≥ 0〉 .Opgave 6.12 Implementeer de specificatie□|[ con int N {N ≥ 2}; con int a[0 . . N); var int r, s⊲ S{0 ≤ r < s < N ∧ a.r ∗ a.s = 〈↓ i, j : 0 ≤ i < j < N : a.i ∗ a.j〉}]| .


84 HOOFDSTUK 6. VARIATIE VAN CONSTANTEOpgave 6.13 Implementeer de specificatiewaarin□|[ con int N {N ≥ 2}; con int a[0 . . N) {a.0 ≠ a.1}; var int r⊲ S{r = 〈#i : 1 ≤ i < N : a.i = a.(L.i) + 1〉}]| ,L.i = 〈↑ j : 0 ≤ j < i ∧ a.j ≠ a.i : j〉 .


Hoofdstuk 7Staartinvariantie7.1 Homogene staartinvariantieIn het vorige hoofdstuk bestudeerden we recurrente betrekkingen van de vormf.0 = A ,f.(n + 1) = G.n.(f.n) voor n ≥ 0 .In dit hoofdstuk gaat het om gevallen waar het argument van f in het rechterlid van derecurrente betrekking een meer algemene vorm heeft.Zij f een functie van en naar de gehele getallen die voldoet aan een recurrente betrekkingvan de vormf.n = (B ? A : f.C) .Hierin zijn A, B en C expressies die van n mogen afhangen maar waarin f niet wordtgenoemd. Het type van A en C is int, het type van B is bool. We eisen niet dat f door derecurrente betrekking volledig wordt vastgelegd.De specificatie van het te construeren programma is|[ con int N; var int r⊲ S {r = f.N }]| .We lossen dit probleem niet op met variatie van constante. In plaats daarvan kiezen we alsinvariant 1P : f.n = f.N .De initialisatie van P is zeer eenvoudig te bereiken met de toekenning n := N . In eersteinstantie is echter niet duidelijk dat een repetitie met deze invariant het probleem kan oplossen:behalve r ≠ f.n, wat geen toegelaten expressie is, kunnen we geen guard bedenken waarvande ontkenning samen met P de gewenste postconditie impliceert. De situatie wordt echteranders als we bereid zijn de repetitie nog te laten volgen door een toekenning aan r, metandere woorden als we zoeken naar een oplossing van de vorm1 We gaan ervan uit dat f overal gedefinieerd is. Als f een partiële functie met domein D is, wordt deinvariant n ∈ D ∧ f.n = f.N .85


86 HOOFDSTUK 7. STAARTINVARIANTIE|[ int n⊲ n := N{inv P }; do G → {P ∧ G} T {P , Bewijs 2} od{P ∧ ¬G}; r := R{r = f.N , Bewijs 1}]| .De berekening van guard G en expressie R gaat gelijktijdig, als volgt:Bewijs 1|[ P⊲≡(r ← R).(r = f.N){substitutie}R = f.N≡ {P }R = f.n≡ {recurrente betrekking van f , gebruik • B }R = A]| .□Voor R kiezen we dus de expressie A. De gemaakte veronderstelling B is in Bewijs 1 legaalals we als guard van de repetitie ¬B kiezen. Voor de body T proberen we een toekenningn := E .Bewijs 2|[ P ∧ ¬B⊲(n ← E).P≡{substitutie}f.E = f.N≡ {P }f.E = f.n≡ {recurrente betrekking van f , gebruik ¬B }f.E = f.C⇐]| .□{functie-applicatie}E = CHiermee is de volgende stelling bewezen:


7.1. HOMOGENE STAARTINVARIANTIE 87Stelling 7.1 Zij f een functie op de gehele getallen die voldoet aan de recurrente betrekkingf.n = (B ? A : f.C) ,waarin A, B, C van n mogen afhangen maar f niet noemen. Dan geldt{true}|[ int n⊲ n := N{inv f.n = f.N }; do ¬B → n := C od; r := A]|{r = f.N } ,mits de repetitie eindigt.□Voorbeeld 7.2 Voor d ≥ 1 ∧ p ≥ 0 definiëren wed | p ≡ p mod d = 0 .We spreken d | p uit als ‘d deelt p’. Enige eigenschappen van deze relatie zijnd | p ≡ p = (p div d) ∗ d , (7.1)d | p ≡ d | p + q ∗ d voor q ≥ 0, (7.2)d | 0 , (7.3)d | d , (7.4)d | p ∧ p ≥ 1 ⇒ d ≤ p . (7.5)(Vergelijk Opgave 2.18.) Voor natuurlijke getallen a en b, niet beide 0, definiëren we nu degrootste gemene deler van a en b alsa ggd b = 〈↑ d : d ≥ 1 ∧ d | a ∧ d | b : d〉 .We schrijven een programma ter berekening van de grootste gemene deler van twee gegevengetallen; een formele specificatie luidt:|[ con int A, B {A ↓ B ≥ 0 ∧ A ↑ B ≥ 1}; var int r⊲ S {r = A ggd B }]| .Merk op dat de preconditie volgens Stelling 2.6 een korte schrijfwijze is voorA ≥ 0 ∧ B ≥ 0 ∧ (A ≥ 1 ∨ B ≥ 1) .We leiden een recurrente betrekking voor ggd af.


88 HOOFDSTUK 7. STAARTINVARIANTIEBewijs 1|[ a ↓ b ≥ 0 ∧ a ↑ b ≥ 1⊲a ggd b= {definitie van ggd}〈↑ d : d ≥ 1 ∧ d | a ∧ d | b : d〉= {Definitie 2.14, gebruik • b ≠ 0}〈↑ d : d ≥ 1 ∧ d | (a div b) ∗ b + a mod b ∧ d | b : d〉= {(7.1), gebruik d | b}〈↑ d : d ≥ 1 ∧ d | (a div b) ∗ (b div d) ∗ d + a mod b ∧ d | b : d〉= {(7.2)}〈↑ d : d ≥ 1 ∧ d | a mod b ∧ d | b : d〉= {definitie van ggd}b ggd (a mod b)]| .□(Omdat de operator ggd symmetrisch is, hadden we net zo goed (a mod b) ggd b kunnenschrijven. We hebben gekozen voor de andere volgorde omdat we ernaar streven b als variantefunctie te kiezen.) Dankzij a mod b ≥ 0 en b ≥ 1 horen de nieuwe argumenten van ggd weertot het domein van die functie.In Bewijs 1 is het geval b ≠ 0 afgehandeld. Als b = 0, levert de voorwaarde a ↑ b ≥ 1 uithet definitiegebied van ggd ons dat a ≥ 1.Bewijs 2|[ a ≥ 1⊲a ggd 0= {definitie van ggd}〈↑ d : d ≥ 1 ∧ d | a ∧ d | 0 : d〉= {(7.3)}〈↑ d : d ≥ 1 ∧ d | a : d〉= {(7.5), gebruik a ≥ 1}〈↑ d : 1 ≤ d ≤ a ∧ d | a : d〉= {(7.4)}a]| .□Voor ggd is hiermee de volgende recurrente betrekking afgeleid:a ggd b = (b = 0 ? a : b ggd (a mod b)) .Toepassing van Stelling 7.1, of, preciezer gezegd, het analogon van die stelling voor functiesvan twee veranderlijken, leidt nu tot het programma


7.1. HOMOGENE STAARTINVARIANTIE 89{A ↓ B ≥ 0 ∧ A ↑ B ≥ 1}|[ int a, b⊲ a, b := A, B{inv a ↓ b ≥ 0 ∧ a ↑ b ≥ 1 ∧ a ggd b = A ggd B ; vf b}; do b ≠ 0 → a, b := b, a mod b {Bewijs 1} od; r := a {Bewijs 2}]|{r = A ggd B , Staartinvariantie} .Merk op dat de bewijsverplichting voor eindiging, dankzij de keuze van b als variante functie,neerkomt op enerzijds b ≥ 0, anderzijds a mod b < b. Hieraan is voldaan dankzij respectievelijkde invariant en de definitie van mod.□Aan dit voorbeeld zien we duidelijk dat bij deze methode al het werk zit in de afleiding vaneen geschikte recurrente betrekking.Opgave 7.3 (a) Bewijs dat onder aanname van a ≥ b ≥ 1 geldt a mod b ≤ a/2.(b) Bewijs dat onder aanname van a ≥ b ≥ 1 geldt b + a mod b ≤ 3(a + b)/4.(c) Laat zien dat het aantal malen dat de body van de repetitie in bovenstaand voorbeeldwordt uitgevoerd begrensd is door een constante maal log(A + B).□Opgave 7.4 (a) Bewijs dat onder aanname van a > b ≥ 0 geldt a ggd b = (a − b) ggd b.(b) Schrijf een programma voor de berekening van A ggd B dat op deze betrekking isgebaseerd.(c) Wat is er te zeggen over het aantal malen dat de body van de repetitie wordt uitgevoerd?□Opgave 7.5 Gegeven is een array a[0 . . N]. Definieer, voor 0 ≤ p ≤ q ≤ N ,max.p.q = 〈↑ i : p ≤ i ≤ q : a.i〉 .(a) Bewijs datp = q ⇒ max.p.q = a.p ,p < q ∧ a.p ≤ a.q ⇒ max.p.q = max.(p + 1).q ,p < q ∧ a.p ≥ a.q ⇒ max.p.q = max.p.(q − 1) .□(b) Schrijf een programma voor de berekening van max.0.N .Opgave 7.6 Gegeven is een array a[0 . . N]. Definieer, voor 0 ≤ p ≤ q ≤ N ,□maxi.p.q = 〈↓ i : p ≤ i ≤ q ∧ a.i = 〈↑ j : p ≤ j ≤ q : a.j〉 : i〉 .(a) Leid een recurrente betrekking voor maxi af.(b) Schrijf een programma voor de berekening van maxi.0.N .


90 HOOFDSTUK 7. STAARTINVARIANTIE7.2 Inhomogene staartinvariantieIn deze paragraaf beschouwen we een generalisatie van de recurrente betrekking die het onderwerpvan de vorige was, namelijkf.n = (B ? A : f.C w D) ,waarin w een associatieve operator met rechtereenheidselement, zeg e, is. (Dat laatste betekentdat x w e = x voor elke x.) Met A, B, C, D bedoelen we weer expressies die van n mogenafhangen.Deze recurrente betrekking is inderdaad een generalisatie van de vorige, want die kunnenwe terugkrijgen door w te definiëren door x w y = x voor alle x, y . Ga na dat deze winderdaad associatief is en dat elke y rechtereenheidselement is.De specificatie van het te construeren programma is wederom|[ con int N; var int r⊲ S {r = f.N }]| .We lossen dit probleem op door te definiëreng.x.n = f.n w xen met de methode uit de vorige paragraaf de functie g te behandelen.Allereerst laten we zien dat een programma voor de berekening van waarden van g onsook in staat stelt waarden van f te bepalen.Bewijs 1f.n= {e is rechtereenheidselement van w}f.n w e= {definitie van g }g.e.n .□De oorspronkelijke postconditie kan nu dus worden uitgedrukt als r = g.e.N . We leiden eenrecurrente betrekking voor g af.Bewijs 2g.x.n= {definitie van g }f.n w x= {recurrente betrekking voor f }(B ? A : f.C w D) w x= {distributie van (w x)}


7.2. INHOMOGENE STAARTINVARIANTIE 91(B ? A w x : (f.C w D) w x)= {associativiteit van w}(B ? A w x : f.C w (D w x))= {definitie van g }(B ? A w x : g.(D w x).C) .□Hiermee is voor g de volgende recurrente betrekking afgeleid:g.x.n = (B ? A w x : g.(D w x).C) .Volgens Stelling 7.1, althans het analogon voor twee variabelen, wordt g.e.N dan berekenddoor het volgende programmafragment:{true}|[ int x, n⊲ x, n := e, N{inv g.x.n = g.e.N }; do ¬B → x, n := D w x, C {Bewijs 2} od; r := A w x {Bewijs 2}]|{r = g.e.N , Staartinvariantie} ,mits de repetitie eindigt. Eliminatie van de naam g en identificatie van de variabelen x en rleidt dan tot de volgende stelling:Stelling 7.7 Zij f een functie op de gehele getallen die voldoet aan de recurrente betrekkingf.n = (B ? A : f.C w D)waarin A, B, C, D van n mogen afhangen maar f niet bevatten en waarin w een associatieveoperator met rechtereenheidselement e is. Dan geldt{true}|[ int n⊲ r, n := e, N{inv f.n w r = f.N }; do ¬B → r, n := D w r, C od; r := A w r]|{r = f.N } ,mits de repetitie eindigt.□Voorbeeld 7.8 Beschouw de specificatie|[ con int A, B {B ≥ 0}; var int r⊲ S {r = A B }]| .


92 HOOFDSTUK 7. STAARTINVARIANTIEWe beschouwen a b als een partiële functie van twee gehele variabelen, gedefinieerd voor b ≥ 0;in het bijzonder nemen we aan dat 0 0 gedefinieerd is en de waarde 1 heeft. Voor deze functieleiden we een recurrente betrekking af.Bewijs 1|[ b ≥ 0⊲a b= {Definitie 2.14}a2(b div 2)+b mod 2= {rekenen}(a 2 ) b div 2 ∗ a b mod 2= {• d = a b mod 2 }(a 2 ) b div 2 ∗ d]| .□Deze gelijkheid geldt voor willekeurige a, b.Ons eindigingsargument zal echter gebaseerd zijnop de variante functie b; merk op dat b div 2 < b geldt als b ≥ 1. Om die reden geven we nogeen aparte berekening voor het geval b = 0.Bewijs 2a 0= {per definitie}1 .□Uit Bewijs 1 en 2 destilleren we de volgende recurrente betrekking voor a b :b = 0 ⇒ a b = 1 ,b > 0 ⇒ a b = (a 2 ) b div 2 ∗ d ,waarin d = a b mod 2 .Merk op dat berekening van de juiste waarde van d eenvoudig kan plaatsvinden door de beidegevallen b mod 2 = 0 en b mod 2 = 1 te onderscheiden: er geldta b mod 2 = (b mod 2 = 0 ? 1 : a) .Toepassen van (het analogon voor twee variabelen van) Stelling 7.7, waarin de rol van deassociatieve operator w wordt gespeeld door de vermenigvuldiging, geeft het programma{B ≥ 0}|[ int a, b⊲ r, a, b := 1, A, B{inv b ≥ 0 ∧ a b ∗ r = A B ; vf b}; do b ≠ 0 → |[ int d


7.2. INHOMOGENE STAARTINVARIANTIE 93⊲ d := (b mod 2 = 0 ? 1 : a); r, a, b := d ∗ r, a ∗ a, b div 2 {Bewijs 1}]|od; r := 1 ∗ r {Bewijs 2}]|{r = A B , Staartinvariantie} .Uiteraard kan de laatste toekenning r := 1 ∗ r uit het programma worden weggelaten. Merkop dat b per repetitieslag met een factor afneemt die kleiner dan of gelijk aan 1/2 is, zodatde body ten hoogste een constant aantal malen log B wordt uitgevoerd.□Behalve door rechtstreekse toepassing is Stelling 7.7 ook nuttig doordat we in concrete situatieshet bewijs ervan kunnen imiteren. We noemen dit het homogeniseren van een recurrentebetrekking. Dit heeft veelal ook succes in situaties waar Stelling 7.7 zelf niet toepasbaar is.Voorbeeld 7.9 De functie f is op de natuurlijke getallen gedefinieerd door de recurrentebetrekkingn = 0 ⇒ f.n = 1 , (7.6)n > 0 ∧ n mod 2 = 0 ⇒ f.n = 2 ∗ f.(n div 2) , (7.7)n > 0 ∧ n mod 2 = 1 ⇒ f.n = 3 + f.(n − 1) . (7.8)Gevraagd wordt voor gegeven natuurlijk getal N de waarde van f.N te berekenen. Eenassociatieve operator waarmee Stelling 7.7 kan worden toegepast, is hier niet te bekennen. Inplaats daarvan homogeniseren we de recurrente betrekking voor f . We beschouwen daartoede expressier + x ∗ f.nals functie van drie variabelen r, x, n. Voor deze functie leiden we een recurrente betrekkingaf waarop Stelling 7.1 van toepassing is. De drie gevallen uit de betrekking voor f behandelenwe apart.Bewijs 1|[ n = 0⊲r + x ∗ f.n= {(7.6), gebruik n = 0}r + x ∗ 1= {rekenen}r + x]| .□


94 HOOFDSTUK 7. STAARTINVARIANTIEBewijs 2|[ n > 0 ∧ n mod 2 = 0⊲r + x ∗ f.n= {(7.7), gebruik n > 0 ∧ n mod 2 = 0}r + x ∗ (2 ∗ f.(n div 2))= {rekenen}r + (2x) ∗ f.(n div 2)]| .□Bewijs 3|[ n > 0 ∧ n mod 2 = 1⊲r + x ∗ f.n= {(7.8), gebruik n > 0 ∧ n mod 2 = 1}r + x ∗ (3 + f.(n − 1))= {rekenen}(r + 3x) + x ∗ f.(n − 1)]| .□Voor r + x ∗ f.n hebben we daarmee de volgende recurrente betrekking afgeleid:n = 0 ⇒ r + x ∗ f.n = r + x ,n > 0 ∧ n mod 2 = 0 ⇒ r + x ∗ f.n = r + (2x) ∗ f.(n div 2) ,n > 0 ∧ n mod 2 = 1 ⇒ r + x ∗ f.n = (r + 3x) + x ∗ f.(n − 1) .Toepassing van homogene staartinvariantie, dat wil zeggen het analogon van Stelling 7.1, geeftnu□{N ≥ 0}|[ int x, n⊲ r, x, n := 0, 1, N{inv n ≥ 0 ∧ r + x ∗ f.n = f.N ; vf n}; do n ≠ 0 → if n mod 2 = 0 → x, n := 2 ∗ x, n div 2 {Bewijs 2}n mod 2 = 1 → r, n := r + 3 ∗ x, n − 1 {Bewijs 3}fiod; r := r + x {Bewijs 1}]|{r = f.N , Staartinvariantie} .


7.2. INHOMOGENE STAARTINVARIANTIE 95Opgave 7.10 Implementeer de specificatie|[ con int N {N ≥ 0}; var int r⊲ S {r = f.N }]| ,waarin f wordt gedefinieerd door de recurrente betrekking(a) f.0 = 5 ,f.1 = 10 ,f.2n = 3 ∗ f.n voor n ≥ 1 ,f.(2n + 1) = 4 ∗ f.n − f.(n + 1) voor n ≥ 0 .(b) f.0 = 1 ,f.2n = 2 + f.n voor n ≥ 1 ,f.(2n + 1) = n ∗ f.2n voor n ≥ 0 .□Opgave 7.11 Schrijf een programma dat in logaritmische tijd het produkt van twee natuurlijkegetallen A en B berekent. In het programma is alleen vermenigvuldigen met en delendoor 2 toegestaan.□Opgave 7.12 Schrijf een programma dat, bij gegeven natuurlijk getal N en geheel getal X ,in logaritmische tijd de waarde vanberekent.□〈Σ i : 0 ≤ i < N : X i 〉Opgave 7.13 Implementeer de specificatie□|[ con int N {N ≥ 1}; var int r⊲ S {r = 〈#i : i ≥ 1 : N mod 3 i = 0〉}]| .


96 HOOFDSTUK 7. STAARTINVARIANTIE


Hoofdstuk 8Zoekalgoritmen8.1 Linear searchZij B een functie van de gehele getallen naar de boolse waarden, zodanig dat in elke toestandgeldt〈∃i : B.i : true〉 , (8.1)〈∀i : B.i : i ≥ 0〉 . (8.2)In dat geval is 〈↓ i : B.i : i〉 gedefinieerd. Omdat deze grootheid in het onderstaande vaakzal voorkomen, voeren we voor deze formule een afkorting in:min = 〈↓ i : B.i : i〉 . (8.3)Het volgende programmeerprobleem is nu dus goed gespecificeerd:|[ var int r⊲ S {r = min }]| .Dit probleem staat bekend als dat van de linear search. We veronderstellen hier dat B.E eenexpressie is als E dat is, zodat aanroepen van B in het programma mogen voorkomen.Toepassing van (3.4) geeft de equivalentier = min ≡ B.r ∧ r ≤ min . (8.4)Dit brengt ons op de gedachte de postconditie r = min te bewerkstelligen door middel vaneen repetitie met invariantP :r ≤ minen guard ¬B.r. Zo n repetitie zal, zo zij eindigt, dankzij (8.4) de gewenste postconditierealiseren. Als variante functie kiezen weV : min − r .Dan volgt V ≥ 0 uit P ; afname van V zullen we bereiken door in elke repetitieslag r teverhogen. We beschouwen nu achtereenvolgens de initialisatie en de invariantie van P .97


98 HOOFDSTUK 8. ZOEKALGORITMENBewijs 1(r ← 0).P≡ {substitutie}0 ≤ min⇐ {(8.2)}B.min≡ {(8.4)}true□Bewijs 2|[ P ∧ ¬B.r⊲(r ← r + 1).P≡ {substitutie}r + 1 ≤ min≡ {P }r ≠ min≡ {(8.4), gebruik ¬B.r}true]| .□Hiermee hebben we de volgende stelling bewezen, die wel de Linear Search Theorem wordtgenoemd:Stelling 8.1 Onder aanname vangeldt□〈∃i : B.i : true〉 ,〈∀i : B.i : i ≥ 0〉 ,min = 〈↓ i : B.i : i〉{true}r := 0{inv r ≤ min ; vf min − r}; do ¬B.r → r := r + 1 od{r = min } .


8.1. LINEAR SEARCH 99Opmerking Hoewel we daarvan in het bewijs van de stelling geen gebruik hebben gemaakt,is ook r ≥ 0 een invariant van de repetitie. Deze wetenschap kan in voorkomende gevallenworden gebruikt om de guard ¬B.r te vereenvoudigen.□Voorbeeld 8.2 Gevraagd wordt een programma dat aan de volgende specificatie voldoet:|[ con int N {N ≥ 0}; var int r⊲ S {r = 〈↓ i : i ≥ 0 ∧ 2 i ≥ N : i〉}]| .We kunnen zeggen dat zo’n programma de logaritme (met grondtal 2) uit N berekent, naarboven afgerond tot een gehele waarde. Pas nu de Linear Search Theorem toe op de functieB , gedefinieerd doorB.i ≡ i ≥ 0 ∧ 2 i ≥ N .Aan (8.2) is dan vanzelfsprekend voldaan. De controle van (8.1) komt neer op het volgendebewijsje.Bewijs 1|[ N ≥ 0⊲〈∃i : i ≥ 0 ∧ 2 i ≥ N : true〉≡ {Trading}〈∃i : i ≥ 0 : 2 i ≥ N〉⇐ {instantiatie i = N , gebruik N ≥ 0}2 N ≥ N≡ {wiskunde}true]| .□Toepassing van de Linear Search Theorem (inclusief de opmerking over vereenvoudiging vande guard) geeft nu als oplossing{N ≥ 0}{〈∃i : i ≥ 0 ∧ 2 i ≥ N : true〉, Bewijs 1}r := 0{inv P 0 : 0 ≤ r ≤ min ; vf min − r}; do 2 r < N → r := r + 1 od{r = min , Linear Search} ,waarin min is gedefinieerd door (8.3). Dit programma is nog niet acceptabel, omdat 2 r nietals expressie is toegelaten. We versterken daarom de invariant metP 1 : s = 2 r .Onder aanname van P 1 kan de guard worden geformuleerd als s < N . Voor de invariantievan P 1 hebben we


100 HOOFDSTUK 8. ZOEKALGORITMENBewijs 2|[ P 0..1 ∧ s < N⊲2 r+1= {rekenen}2 ∗ 2 r= {P 1}2 ∗ s]| .□Dit geeft het volgende programma:□{N ≥ 0}{〈∃i : i ≥ 0 ∧ 2 i ≥ N : true〉, Bewijs 1}r, s := 0, 1{inv P 0..1; vf min − r}; do s < N → s := 2 ∗ s {(r ← r + 1).P 1, Bewijs 2}; r := r + 1od{r = min , Linear Search} .De speciale rol die in (8.2) gespeeld schijnt te worden door het getal 0 vormt geen essentiëlebeperking. Als we voor zeker geheel getal A in plaats van (8.2) gegeven hebbengeldt〈∀i : B.i : i ≥ A〉 ,{true}r := A{inv A ≤ r ≤ min ; vf min − r}; do ¬B.r → r := r + 1 od{r = min } .Dit wordt analoog bewezen aan Stelling 8.1 of daaruit afgeleid door B.(r − A) als boolsefunctie van r te beschouwen.Als we voor zeker geheel getal A in plaats van (8.2) gegeven hebben〈∀i : B.i : i ≤ A〉 ,is min niet noodzakelijk gedefinieerd. Wel bestaatmax = 〈↑ i : B.i : i〉 ;we kunnen max berekenen door


8.1. LINEAR SEARCH 101{true}r := A{inv max ≤ r ≤ A; vf r − max }; do ¬B.r → r := r − 1 od{r = max } .Dit wordt analoog bewezen aan Stelling 8.1 of daaruit afgeleid door B.(A − r) als boolsefunctie van r te beschouwen.Opgave 8.3 Bewerkstellig voor natuurlijke N :□(a) r = 〈↑ i : i ≥ 0 ∧ 3 i ≤ N : i〉 ,(b) r = 〈↓ i : i 3 − 6i 2 + 9i ≥ N : i〉 ,(c) r = 〈↑ i : i 3 − 6i 2 + 9i ≤ N : i〉 ,(d) r = 〈↓ i : i > N ∧ 〈∃j : true : i = j 2 + j〉 : i〉 .Opgave 8.4 Veronderstel dat (8.1) gegeven is maar niet (8.2). Bereken□〈↓ i : B.i : |i|〉 .Opmerking Het is niet zo dat de aanwezigheid van de quantor ↓ of ↑ in de postconditiedicteert of we in stijgende of dalende richting moeten zoeken. Zo kan, voor natuurlijke N , denaar beneden tot een geheel getal afgeronde waarde van √ N worden beschreven door〈↑ i : i ≥ 0 ∧ i 2 ≤ N : i〉maar ook door〈↓ i : i ≥ 0 ∧ (i + 1) 2 > N : i〉 .We kunnen Linear Search dus in twee richtingen toepassen; de hieruit resulterende programma’sverschillen in rekentijd 1 . Het kan dus de moeite waard zijn, voorafgaande aan het toepassenvan de Linear Search Theorem, de gegeven postconditie te herschrijven.□Opgave 8.5 Implementeer de specificatie□|[ con int N {N ≥ 2}; con int a[0 . . N) {〈∃i, j : 0 ≤ i < j < N : a.i − a.j ≤ 2〉}; var int r⊲ S {r = 〈↑ i : 0 < i < N ∧ a.(i − 1) − a.i ≤ 2 : i〉}]| .1 In de volgende paragraaf laten we zien hoe dit probleem op een essentieel snellere manier kan wordenopgelost


102 HOOFDSTUK 8. ZOEKALGORITMENOpgave 8.6 Implementeer de specificatie□|[ con int N {N ≥ 1}; con int a[0 . . N], b[0 . . N] {a.0 < b.0 ∧ a.N ≥ b.N }; var int r⊲ S {r = 〈↑ i : 0 ≤ i < N ∧ a.i < b.i ∧ a.(i + 1) ≥ b.(i + 1) : i〉}]| .Voorbeeld 8.7 Gegeven is een array a met boolse waarden ter lengte N . Als ook gegeven isdat ten minste één van de componenten van a de waarde true heeft, kunnen we Linear Searchtoepassen ter berekening van de index van de meest linkse component met die eigenschap, datwil zeggen〈↓ i : 0 ≤ i < N ∧ a.i : i〉 .Veronderstel echter dat we niets weten over de waarden van de a.i. Dan wordt hier mogelijknaar het minimum van een lege verzameling gevraagd. Om dit uit te sluiten, spreken we afdat ons programma de waarde N moet opleveren als geen enkele a.i de waarde true heeft.Despecificatie wordt dus|[ con int N {N ≥ 0}; con bool a[0 . . N); var int r⊲ S {r = 〈↓ i : (0 ≤ i < N ∧ a.i) ∨ i = N : i〉}]| .Het rechterlid van de postconditie zullen we weer aangeven met min.worden toegepast op B , gedefinieerd doorStelling 8.1 kan nuB.i ≡ (0 ≤ i < N ∧ a.i) ∨ i = N .Aan (8.2) is dan voldaan omdat N ≥ 0, aan (8.1) omdat B.N geldt.programmaWe krijgen zo het{N ≥ 0}r := 0{inv 0 ≤ r ≤ min ; vf min − r}; do ¬((r < N ∧ a.r) ∨ r = N) → r := r + 1 od{r = min , Linear Search} .Er is met dit programma echter een probleem. De regels voor correctheid van repetitieszeggen dat voor invariant P en guard B moet gelden P ⇒ def .B . Nu is, ingeval r = N , desubexpressie a.r niet gedefinieerd. Het ligt nu aan de precieze conventies inzake de operator∧ van het type bool of de hele guard in dat geval wel een gedefinieerde expressie is. Eenmogelijke conventie isdef .(B ∧ C) ≡ def .B ∧ def .C , (8.5)


8.2. BINARY SEARCH 103en in dat geval is bovenstaand programma fout. Een andere mogelijkheid isdef .(B ∧ C) ≡ def .B ∧ (B ? def .C : true) , (8.6)en in dat geval is bovenstaand programma wel correct.In de praktijk hanteren verschillende programmeertalen verschillende afspraken voor ditprobleem. Zo wordt in C, C++, Modula-2 en Oberon conventie (8.6) gebruikt, in Pascalconventie (8.5) en heeft Ada twee verschillende conjunctie-operatoren. In aansluiting bij demeeste moderne talen zullen we in dit college voor GCL conventie (8.6) aanhouden, zodat detoepassing van Linear Search ook bij deze toepassing een correct programma levert 2 .□Opgave 8.8 Implementeer de volgende specificatie:□|[ con int N {N ≥ 0}; con int a[0 . . N); var int r⊲ S {r = 〈↑ i : i = 0 ∨ (0 < i < N ∧ a.i = a.(i − 1)) : i〉}]| .8.2 Binary searchZij B weer een functie van de gehele getallen naar de boolse waarden. De specificatie van hetprogrammeerprobleem in deze paragraaf luidt|[ con int x, y {x < y ∧ B.x ∧ ¬B.y }; var int r⊲ S {x ≤ r < y ∧ B.r ∧ ¬B.(r + 1)}]| .We veronderstellen weer dat B.E een expressie is als E dat is, zodat de functie B explicietin het programma mag voorkomen.Opgave 8.9 Bewijs dat het predikaatr = 〈↓ i : x ≤ i < y ∧ B.i ∧ ¬B.(i + 1) : i〉een versterking van de geëiste postconditie is. Los nu het programmeerprobleem op met LinearSearch.□2 Het probleem een programma te vinden dat ook bij conventie (8.5) goed werkt, staat bekend als de BoundedLinear Search. Zie hiervoor bijvoorbeeld §10.8 van E. Cohen, Programming in the 1990s. Springer, New York,1990.


104 HOOFDSTUK 8. ZOEKALGORITMENIn de vorige paragraaf werd de gezochte waarde van beneden af benaderd. In deze paragraafkiezen we voor een benadering van twee kanten. Dat wil zeggen: we introduceren naast r eentweede variabele s en kiezen als invariantenP 0 : x ≤ r < s ≤ y ,P 1 : B.r ∧ ¬B.s .Dankzij de gegeven preconditie kan P 0..1 worden geïnitialiseerd door r, s := x, y . De postconditieis bereikt zodra s = r +1; de guard van de repetitie wordt dus s ≠ r +1. Als variantefunctie kiezen weV : s − r .Uit P 0 volgt V ≥ 0. We dienen de body van de repetitie nu zo te ontwerpen dat deze Vverlaagt.Als eerste kandidaat voor de body kiezen we een toekenning aan r, zeg r := m. Weinventariseren de eisen die aan m zijn gesteld. Ten eerste dient r := m de waarde van V teverlagen. Dit geeftBewijs 1|[ P 0..1 ∧ s ≠ r + 1⊲(r ← m).V < V≡ {substitutie}s − m < s − r≡ {rekenen}m > r]| .□De eerste eis aan m leidt dus tot de voorwaarde m > r. De tweede eis is dat r := m leidt totinvariantie van P 0. Dit geeftBewijs 2|[ P 0..1 ∧ s ≠ r + 1 ∧ m > r⊲(r ← m).P 0≡{substitutie}x ≤ m < s ≤ y≡ {P 0 ∧ m > r ‖ P 0}m < s]| .□De tweede eis heeft dus geleid tot m < s. De derde eis is dat r := m leidt tot invariantie vanP 1. Dit geeft


8.2. BINARY SEARCH 105Bewijs 3|[ P 0..1 ∧ s ≠ r + 1 ∧ r < m < s⊲(r ← m).P 1≡{substitutie}B.m ∧ ¬B.s≡ {P 1}B.m]| .□De conclusie luidt dat r := m voldoet aan de specificatie van de repetitiebody als m zó isgekozen datr < m < s ∧ B.m .Uit overwegingen van symmetrie volgt dat s := m voldoet aan de specificatie van de repetitiebodyals m voldoet aanr < m < s ∧ ¬B.m .Voor de body van de repetitie vinden we zo{P 0..1 ∧ s ≠ r + 1}|[ int m⊲ T {r < m < s}; if B.m → r := m {P 0, Bewijs 2; P 1, Bewijs 3}¬B.m → s := m {P 0..1, symmetrie}fi]| .We moeten nu nog de opdracht T kiezen die r < m < s bewerkstelligt. Uit overwegingen vanefficiëntie kiezen we hiervoor m := (r + s) div 2. In dat geval wordt V in elke repetitieslagvrijwel gehalveerd, in elk geval vermenigvuldigd met een factor die ten hoogste 0,75 bedraagt.Er volgt dat het aantal uitgevoerde repetitieslagen wordt begrensd door een constante maallog(y − x).We hebben nu de volgende stelling bewezen, die bekend staat als de Binary Search Theorem:Stelling 8.10 Er geldt{x < y ∧ B.x ∧ ¬B.y }|[ int s⊲ r, s := x, y{inv x ≤ r < s ≤ y ∧ B.r ∧ ¬B.s; vf s − r}; do s ≠ r + 1 → |[ int m⊲ m := (r + s) div 2; if B.m → r := m


106 HOOFDSTUK 8. ZOEKALGORITMEN¬B.m → s := mfi]|od]|{x ≤ r < y ∧ B.r ∧ ¬B.(r + 1)} .Het aantal repetitieslagen is begrensd door een constante maal log(y − x).□Opmerking De functie B wordt uitsluitend geëvalueerd in punten m die voldoen aan x N ; vf s − r}; do s ≠ r + 1 → |[ int m⊲ m := (r + s) div 2; if m ∗ m ≤ N → r := mm ∗ m > N → s := mfi]|od]|{r 2 ≤ N < (r + 1) 2 , Binary Search} .Merk op dat hier verder geen bewijzen meer bij nodig zijn. De looptijd van dit programma isvan de orde log N .□


8.3. ZOEKEN IN EEN STIJGENDE RIJ 107Opgave 8.12 Implementeer de volgende specificatie:□|[ con int N {N ≥ 0}; var bool r⊲ S {r = 〈∃i : i ≥ 0 : N = i 3 〉}]| .Opgave 8.13 Implementeer de volgende specificatie:□|[ con int N {N ≥ 1}; con int a[0 . . N] {a.0 < a.N }; var int r⊲ S {0 ≤ r < N ∧ a.r < a.(r + 1)}]| .8.3 Zoeken in een stijgende rijDefinitie 8.14 Een array a[0 . . N) heet stijgend (ascending) alsgeldt.□〈∀i, j : 0 ≤ i ≤ j < N : a.i ≤ a.j〉De uitspraak dat een array a[0 . . N) stijgend is, zullen we noteren als asc.a[0 . . N).behandelen nu de volgende specificatie:|[ con int N, Z {N ≥ 0}; con int a[0 . . N) {asc.a[0 . . N)}; var bool b⊲ S {b = 〈∃i : 0 ≤ i < N : a.i = Z〉}]| .Gevraagd wordt dus vast te stellen of het getal Z voorkomt in a[0 . . N). Dit is eenvoudig opte lossen met variatie van constante (zie §6.2), maar die oplossing vergt rekentijd evenredigaan N . In plaats daarvan passen we de Binary Search Theorem toe om vast te stellen bijwelke index, zo aanwezig, het array van waarden kleiner dan of gelijk aan Z overgaat naarwaarden groter dan Z . We beschouwen hiertoe de functie B gedefinieerd doorEr geldtB.(−1) ≡ true ,B.i ≡ a.i ≤ Z voor 0 ≤ i < N ,B.N ≡ false .−1 < N ∧ B.(−1) ∧ ¬B.N ,dus aan de preconditie van de Binary Search is voldaan. We vinden zoWe


108 HOOFDSTUK 8. ZOEKALGORITMEN{N ≥ 0 ∧ asc.a[0 . . N)}|[ int s⊲ r, s := −1, N{inv −1 ≤ r < s ≤ N ∧ B.r ∧ ¬B.s; vf s − r}; do s ≠ r + 1 → |[ int m⊲ m := (r + s) div 2{0 ≤ m < N , dus B.m = (a.m ≤ Z)}; if a.m ≤ Z → r := ma.m > Z → s := mfi]|od]|{−1 ≤ r < N ∧ B.r ∧ ¬B.(r + 1), Binary Search} .In deze postconditie is de gezochte existentiële quantificatie gemakkelijk uit te rekenen. Vanwegede vorm van de definitie van B doen we dat afzonderlijk voor 0 ≤ r < N en voorr = −1.Bewijs 1|[ asc.a[0 . . N) ∧ 0 ≤ r < N ∧ B.r ∧ ¬B.(r + 1)⊲〈∃i : 0 ≤ i < N : a.i = Z〉≡ {Domeinsplitsing, gebruik 0 ≤ r < N }〈∃i : 0 ≤ i ≤ r : a.i = Z〉 ∨ 〈∃i : r + 1 ≤ i < N : a.i = Z〉⇒{asc.a[0 . . r] ‖ asc.a[r + 1 . . N)}a.r ≥ Z ∨ (r + 1 < N ∧ a.(r + 1) ≤ Z)≡ {0 ≤ r < N ∧ B.r, dus a.r ≤ Z }a.r = Z ∨ (r + 1 < N ∧ a.(r + 1) ≤ Z)≡ {r + 1 ≥ 0 ∧ ¬B.(r + 1), dus r + 1 < N ⇒ a.(r + 1) > Z }a.r = Z⇒ {Instantiatie i = r, gebruik 0 ≤ r < N }〈∃i : 0 ≤ i < N : a.i = Z〉]| .Als de postconditie van de repetitie geldt en bovendien 0 ≤ r < N , is de waarde van degezochte existentiële quantificatie dus gelijk aan die van a.r = Z .□Bewijs 2|[ asc.a[0 . . N) ∧ r = −1 ∧ B.r ∧ ¬B.(r + 1)⊲〈∃i : 0 ≤ i < N : a.i = Z〉⇒ {asc.a[0 . . N)}N > 0 ∧ a.0 ≤ Z


8.3. ZOEKEN IN EEN STIJGENDE RIJ 109≡ {definitie van B }N > 0 ∧ B.0≡ {r = −1 ∧ ¬B.(r + 1)}false]| .Als de postconditie van de repetitie geldt en bovendien r = −1, is de waarde van de gezochteexistentiële quantificatie dus false.□Uit het bovenstaande volgt{−1 ≤ r < N ∧ B.r ∧ ¬B.(r + 1)}b := r ≥ 0 ∧ a.r = Z{b = 〈∃i : 0 ≤ i < N : a.i = Z〉, Bewijs 1, 2} .Toevoegen van deze toekenning na afloop van bovenstaand programma geeft dus een oplossingvoor de gegeven specificatie.Opgave 8.15 Implementeer de volgende specificatie:□|[ con int N, Z {N ≥ 1}; con int a[0 . . N) {asc.a[0 . . N) ∧ 〈∃i : 0 ≤ i < N : a.i = Z〉}; var int r⊲ S {0 ≤ r < N ∧ a.r = Z }]| .Opgave 8.16 Implementeer de volgende specificatie:□|[ con int N {N ≥ 0}; con int a[0 . . N) {asc.a[0 . . N)}; var int r⊲ S {r = 〈#i : 0 ≤ i < N : a.i ≤ 12〉}]| .Opgave 8.17 Implementeer de volgende specificatie:□|[ con int N {0 ≤ α ≤ N }; con bool a[0 . . N) {〈∀i : 0 ≤ i < α : a.i〉 ∧ 〈∀i : α ≤ i < N : ¬a.i〉}; var int r⊲ S {r = α}]| .


110 HOOFDSTUK 8. ZOEKALGORITMEN


Hoofdstuk 9Procedures9.1 DeclaratieHet komt vaak voor dat op verschillende plaatsen in een programma een gelijksoortige berekeningmoet worden uitgevoerd. We beginnen met een voorbeeld van dit verschijnsel enbeschouwen daartoe de specificatie|[ con int N, Z {N ≥ 0}; con int a[0 . . N) {asc.a[0 . . N)}; var int x⊲ S {x = 〈#i : 0 ≤ i < N : a.i = Z〉}]| .Deze specificatie lijkt sterk op de problemen die in de vorige paragraaf zijn behandeld. Webeschouwen daarom opnieuw de functie B gedefinieerd doorB.(−1) ≡ true ,B.i ≡ a.i ≤ Z voor 0 ≤ i < N ,B.N ≡ false .Aan de preconditie van de Binary Search is voldaan; toepassen van de Binary Search bewerkstelligtdus de postconditie−1 ≤ r < N ∧ B.r ∧ ¬B.(r + 1) .We laten zien dat in een toestand die aan deze conditie voldoet, het aantal array-elementendat ten hoogste Z is, gemakkelijk kan worden berekend.Bewijs 1|[ N ≥ 0 ∧ asc.a[0 . . N)⊲−1 ≤ r < N ∧ B.r ∧ ¬B.(r + 1)≡ {splits af r = −1 en r = N − 1, gebruik N ≥ 0}(r = −1 ∧ B.(−1) ∧ ¬B.0)∨ (0 ≤ r < N − 1 ∧ B.r ∧ ¬B.(r + 1))111


112 HOOFDSTUK 9. PROCEDURES∨ (r = N − 1 ∧ B.(N − 1) ∧ ¬B.N)≡ {definitie van B }(r = −1 ∧ a.0 > Z)∨ (0 ≤ r < N − 1 ∧ a.r ≤ Z < a.(r + 1))∨ (r = N − 1 ∧ a.(N − 1) ≤ Z)≡ {asc.a[0 . . N)}−1 ≤ r < N ∧ 〈∀i : 0 ≤ i ≤ r : a.i ≤ Z〉 ∧ 〈∀i : r < i < N : a.i > Z〉≡ {verband # en ∀, zie (3.5)}−1 ≤ r < N ∧ 〈#i : 0 ≤ i ≤ r : a.i > Z〉 = 0 ∧ 〈#i : r < i < N : a.i ≤ Z〉 = 0≡ {Termsplitsing; Domeinsplitsing}−1 ≤ r < N ∧ 〈#i : 0 ≤ i < N : a.i ≤ Z〉 = r + 1]| .□Hieruit volgt: als we de Binary Search laten volgen door een toekenning r := r + 1, geldt naafloop daarvanR0 : r = 〈#i : 0 ≤ i < N : a.i ≤ Z〉 .We dienen echter te tellen hoeveel elementen er precies gelijk aan Z zijn. Omdat〈#i :: a.i = Z〉 = 〈#i :: a.i ≤ Z〉 − 〈#i :: a.i ≤ Z − 1〉 ,is dit op te lossen door naast R0 ook de postconditieR1 : s = 〈#i : 0 ≤ i < N : a.i ≤ Z − 1〉te bewerkstelligen, en vervolgens de toekenning x := r − s uit te voeren.Het bewerkstelligen van R1 gaat precies zoals het bewerkstelligen van R0, zij het datoveral in plaats van Z nu Z − 1 moet worden geschreven en r dient te worden vervangendoor s. Uitschrijven van programmatekst en bewijs voor deze tweede Binary Search is danook dubbel werk. Om ons deze moeite te besparen, hebben we behoefte aan een faciliteit diehet ons mogelijk maakt slechts eenmaal op te schrijven hoe een dergelijke taak wordt verricht,om daarnaar op de plaatsen waar dit nodig is te kunnen verwijzen. We breiden daarom detaal GCL uit met een procedure-mechanisme. Declaraties van procedures hebben de vormproc p = Pwaarin p de naam is die we aan de procedure willen geven en P de body van de procedure.Deze body heeft in GCL dezelfde vorm als de specificatie, met daarin op de plaats van deonbekende een implementatie gesubstitueerd. Voor het onderhavige probleem kunnen webijvoorbeeld declarerenproc BinSearch = |[ con int n, z {n ≥ 0}; con int b[0 . . n) {asc.b[0 . . n)}; var int r⊲ |[ int s⊲ r, s := −1, N{inv −1 ≤ r < s ≤ n ∧ B ′ .r ∧ ¬B ′ .s; vf s − r}


9.2. AANROEP 113; do s ≠ r + 1 → |[ int m⊲ m := (r + s) div 2; if b.m ≤ z → r := mb.m > z → s := mfi]|od{−1 ≤ r < n ∧ B ′ .r ∧ ¬B ′ .(r + 1), Binary Search}; r := r + 1{r = 〈#i : 0 ≤ i < n : b.i ≤ Z〉, Bewijs 1}]|]|.Hierin is de functie B ′ gedefinieerd als B , maar met N, Z, a vervangen door n, z, b. Aan despecificatie waarmee we deze paragraaf begonnen, wordt nu voldaan door de aanroepen{N ≥ 0 ∧ asc.a[0 . . N)}BinSearch(N, Z, a, x){x = 〈#i : 0 ≤ i < N : a.i ≤ Z〉}; BinSearch(N, Z − 1, a, y){y = 〈#i : 0 ≤ i < N : a.i ≤ Z − 1〉}; x := x − y{x = 〈#i : 0 ≤ i < N : a.i = Z〉} .Dat deze annotatie correct is, zal volgen uit de bewijsregels in de volgende paragrafen.9.2 AanroepBeschouw een procedure-declaratie van de vormproc p = |[ con T x; var T ′ y⊲ S]| .Hierin is T het type van de formele parameter x en T ′ het type van de formele parameter y .Gemakshalve gaan we ervan uit dat x en y verse namen zijn, die niet al een betekenis hebbenop de plaats waar p wordt aangeroepen. Voor een expressie A van type T en een variabeleb van type T ′ definiëren we dan de procedure-aanroepp(A, b)als het programmafragment|[ T x; T ′ y⊲ x, y := A, b; S; b := y]| .


114 HOOFDSTUK 9. PROCEDURESWe willen deze definitie nu uitbreiden tot procedures met meer dan één parameter van elksoort. Daartoe willen we in het bovenstaande x kunnen lezen als een vector van formeleparameters x 1 , . . . , x n en T als de vector van bijbehorende typen T 1 , . . . , T n ; hetzelfde voory . Bovenstaande definitie blijft dan zinvol als we aan de meervoudige toekenning b := yeen betekenis kunnen geven (voor x, y := A, b is dat steeds het geval). In verband metde restricties op het gebruik van meervoudige toekenningen houdt deze voorwaarde in datde actuele parameters b 1 , . . . , b n onderling verschillende variabelen (geen array-componenten)zijn. Deze veronderstelling zullen we van nu af steeds maken.9.3 AbstractieWil de invoering van procedures nuttig zijn, dan moet het mogelijk zijn het effect van deprocedure-aanroep af te leiden uit de specificatie van de procedure, zonder dat het nodig isde tekst van de procedure-body te kennen. De definitie van procedure-aanroep in de vorigeparagraaf is daarvoor nog niet bruikbaar.Beschouw de declaratieproc p = |[ con T x; var T ′ y {U }⊲ S {V }]| .Dit wil dus zeggen dat S voldoet aan het Hoare-tripel{U } S {V } .We beschouwen een willekeurige postconditie R over de toestandsruimte van de procedureaanroepen zoeken een preconditie Q zodanig dat{Q} p(A, b) {R} . (9.1)We introduceren hiertoe de afkortingenU ′ ≡ (x, y ← A, b).U ,V ′ ≡ (x ← A).V ,R ′ ≡ (b ← y).R .Met µ noteren we de vector van in U voorkomende specificatievariabelen (zoals geïntroduceerdin §4.5). Er geldt dan:• Bewijsregel voor procedure-aanroep: Q is een oplossing van (9.1) als Q voldoetaanenU ′ ∧ V ′ ⇒ (Q ⇒ R ′ ) (9.2)Q ⇒ 〈∃µ :: U ′ 〉 . (9.3)


9.3. ABSTRACTIE 115Verificatie van (9.3) is in de praktijk meestal een trivialiteit: deze voorwaarde zorgt er slechtsvoor dat de argumenten binnen het toepasbaarheidsgebied van de specificatie vallen en isgeheel onafhankelijk van de gewenste postconditie R. De berekening van een Q die aan (9.2)voldoet, kan geschieden in een afleiding van de vorm|[ U ′ ∧ V ′⊲R ′⇐ {U ′ ∧ V ′ }. . .⇐ {U ′ ∧ V ′ }Q]| .We verkrijgen Q dus door R ′ te versterken tot een predikaat over de toestandsruimte van deaanroep, met gebruikmaking van U ′ en V ′ . Deze berekening lijkt erg op het vereenvoudigenvan de preconditie van een toekenning met gebruik van een invariant. Merk op dat, in hetgeval dat U ′ en V ′ uit vele conjuncten bestaan, deze conjuncten in de afleiding een voor eengebruikt kunnen worden. De breedte van de formules wordt alleen bepaald door de omvangvan de gewenste postconditie R.Voorbeeld 9.1 De procedure Wortel heeft een declaratie van de vormproc Wortel = |[ var int y {µ 2 ≤ y < (µ + 1) 2 }⊲ S {y = µ}]| .Het domein van Wortel(b), d.w.z. de consequent van (9.3), is〈∃µ :: µ 2 ≤ b < (µ + 1) 2 〉 ,hetgeen equivalent is met b ≥ 0. Veronderstel nu dat we een preconditie Q zoeken die voldoetaan{Q} Wortel(b) {b < 5} .Volgens bovenstaand rekenschema kunnen we Q als volgt bepalen:|[ µ 2 ≤ b < (µ + 1) 2 ∧ y = µ⊲(b ← y).(b < 5)≡{substitutie}y < 5≡ {y = µ}µ < 5≡ {µ 2 ≤ b < (µ + 1) 2 }b < 25]| .Een geschikte preconditie Q is dus 0 ≤ b < 25.□


116 HOOFDSTUK 9. PROCEDURESVoorbeeld 9.2 Hier is een voorbeeld met twee var-parameters:proc Verwissel = |[ var int y, z {y = α ∧ z = β }⊲ S {y = β ∧ z = α}]| .Het domein van Verwissel(b, c) is〈∃α, β :: b = α ∧ c = β〉 ,en dat is equivalent met true. Gevraagd wordt een preconditie Q die voldoet aan{Q} Verwissel(b, c) {a < b < c} .We berekenen|[ b = α ∧ c = β ∧ y = β ∧ z = α⊲(b, c ← y, z).(a < b < c)≡{substitutie}a < y < z≡ {y = β ‖ z = α}a < β < α≡ {c = β ‖ b = α}a < c < b]| .Een geschikte preconditie voor Q is dus a < c < b.□Voorbeeld 9.3 Uit dit voorbeeld blijkt dat er geen bezwaar tegen is als een var-argumenten een con-argument samenvallen 1 . Beschouw de procedureproc p = |[ con int x; var int y⊲ S {y = x + 1}]| .Er is niet een expliciet een preconditie vermeld: deze notatie betekent dat de preconditie hetpredikaat true is. We zoeken nu een Q met{Q} p(a, a) {a < 5} .Dit gaat als volgt:1 Waarschuwing: bij de meeste regels voor procedure-aanroep in de literatuur is dit niet toegelaten en zulkswordt niet altijd expliciet vermeld.


9.3. ABSTRACTIE 117|[ y = a + 1⊲(a ← y).(a < 5)≡ {substitutie}y < 5≡ {y = a + 1}a + 1 < 5≡ {rekenen}a < 4]| .Een geschikte preconditie is dus a < 4.□Opgave 9.4 Beschouw een procedure□proc Ggd = |[ con int x {x > 0}; var int y {y = α > 0}⊲ S {y = x ggd α}]| .(a) Bepaal een, liefst zwakke, preconditie Q opdat{Q} Ggd(21, a) {a mod 3 = 0} .(b) Bepaal een implementatie S .Opgave 9.5 Beschouw een procedure□proc Pow = |[ con int p, q {p ≥ 0 ∧ q ≥ 0}; var int y⊲ S {y = p q }]| .(a) Bepaal een, liefst zwakke, preconditie Q opdat{Q} Pow(2, a, b); Pow(2, b, a) {a < 1000} .(b) Bepaal een implementatie S .Opgave 9.6 Beschouw een procedure□proc Log = |[ var int y {2 α ≤ y < 2 α+1 }; S {y = α}]| .(a) Bepaal een, liefst zwakke, preconditie Q opdat{Q} Log(n); Log(n) {n = 2} .(b) Bepaal een implementatie S .


118 HOOFDSTUK 9. PROCEDURES9.4 ExportregelEen heel voor de hand liggende wijze om het effect van een procedure-aanroep af te leiden uitde specificatie van de procedure is het vervangen van de formele parameters in de specificatievan de procedure door de overeenkomstige actuele. Deze handelwijze, die we export zullennoemen, leidt echter niet in alle gevallen tot een correct resultaat. We geven nu eerst eenvoorbeeld waaruit dat blijkt, en vervolgens een voorwaarde die aangeeft wanneer we exportwel veilig kunnen toepassen.Voorbeeld 9.7 Beschouw nogmaals de hierboven al behandelde procedureproc p = |[ con int x; var int y⊲ S {y = x + 1}]| .Bij de aanroep p(a, a) zou export de postconditie a = a + 1 geven, wat niet mogelijk is.□We zullen nu bewijzen dat de exportmethode wel veilig toepasbaar is in het speciale geval dat(in de notatie van de vorige paragrafen) de actuele con-parameter A onafhankelijk is van deactuele var-parameter b. Pas dan immers de algemene methode uit de vorige paragraaf toemet de speciale keuzeR ≡ (x, y ← A, b).V .Er geldt danR ′≡ {definitie van R ′ }(b ← y).R≡ {keuze van R}(b ← y; x, y ← A, b).V≡ {A onafhankelijk van b}(x ← A).V≡ {definitie van V ′ }V ′ ,zodat aan voorwaarde (9.2) voor elke Q is voldaan. Er blijft dus slechts (9.3) over, en daaraanis voldaan als we kiezen Q ≡ U ′ . Hiermee is de exportregel bewezen: als A onafhankelijk isvan b, geldt{(x, y ← A, b).U } p(A, b) {(x, y ← A, b).V } .9.5 InvariantieregelEen ander speciaal geval van de regel dat vaak handig in het gebruik is, treedt op als Ronafhankelijk van b is. In dat geval is


9.5. INVARIANTIEREGEL 119R ′≡ {definitie van R ′ }(b ← y).R≡ {R onafhankelijk van b}R ,zodat aan (9.2) is voldaan voor Q ≡ R.onafhankelijk is van b, geldtHiermee is de invariantieregel bewezen: als R{R ∧ 〈∃µ :: U ′ 〉} p(A, b) {R} .Als in een geannoteerd programma de annotatie van een procedure-aanroep kan worden bewezendoor een beroep te doen op de exportregel, de invariantieregel of een combinatie vanbeide, zullen we van die annotatie geen apart bewijs geven. Waar deze regels niet toereikendzijn en de algemene methode van §9.3 nodig is, wordt gewoonlijk wel naar een afzonderlijkbewijs verwezen.Opgave 9.8 Beschouw nogmaals de procedure Pow uit Opgave 9.5. Bewijs, met behulp vanexport- en invariantieregel, dat voor α ≥ 0 geldt□{a = α} Pow(2, a, b); Pow(2, b, c); a := a + b + c {a = α + 2 α + 2 2α } .

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!