---
title: "Lista 6"
---
### Zadanie 1
Przypomnij sobie definicję funkcji map. Następnie pokaż, że dla dowolnych funkcji
f i g oraz listy xs zachodzi (map f (map g xs)) ≡ (map (lambda (x) (f (g x)))
xs). Możesz założyć, że funkcje f i g poprawnie obliczają się do wartości dla
dowolnego argumentu.
``` racket=
(define (map f xs)
(if (empty? xs)
empty
(cons (f (first xs) ) (map f (rest xs)))))
```
Twierdzenie: ∀ f, g (map f (map g xs)) ≡ (map (lambda (x) (f (g x))) xs)
Zasada indukcji wzgledem xs:
*P := (map f (map g xs)) ≡ (map (lambda (x) (f (g x))) xs)*
- P(empty)
- Dla każdej listy xs, jeśli P(xs), to P((cons ? xs))
Wówczas dla dowolnej listy xs zachodzi P(xs)
I. P(empty)
L = (map f (map g empty)) = (map f empty) = empty
P = (map (lambda (f ( g x))) empty) =empty
$L=P$
Krok indukcyjny
Zalozmy, ze zachodzi P(xs) : (map f (map g xs)) ≡ (map (lambda (x) (f (g x))) xs)
Pokazemy, (map f (map g (cons x xs))) = *(map (lambda (x) (f (g x))) (cons x xs))*
L = (map f (map g (cons x xs))) = (map f (cons (g x) (map g xs))) = (cons (f (g x)) (map f (map g xs)))
P = (map (lambda (x) (f (g x))) (cons x xs)) =
(cons ((lambda (x) (f (g x))) x) (map (lambda (x) (f (g x))) xs))= (upraszczajac lambde, i z zal ind)
(cons (f (g x)) (map f (map g xs)) )
$L = P$
*Na mocy zasady indukcji wlasnosc P zostala udowodniona*
### Zadanie 2
Pokaż, że funkcja append zawsze oblicza się do wartości, tzn. pokaż, że dla do-
wolnych list xs i ys istnieje lista zs taka, że (append xs ys) ≡ zs.
```r
(define (append xs ys)
(if (empty? xs)
ys
(cons (first xs) (append (rest xs) ys))))
```
P(xs) = ∀ ys ∃ zs (append xs ys) ≡ zs
Dowod:
- Baza
xs = empty
(append empty ys) = ys
- Krok indukcyjny:
Zal, ze zachodzi P(xs), pokazemy ∀ ys ∃ zs (append (cons x xs) ys) ≡ zs
Wtedy korzystajac z definicji appenda mamy:
(cons x (append xs ys)) = (korzystajc z zalozenia indukcyjnego) = (cons x zs)
Wiec mozna przyjac $zs'$ $=$ $(cons$ $x$ $zs)$
### Zadanie 3
Formuły w negacyjnej postaci normalnej to takie formuły rachunku zdań, w któ-
rych wszystkie negacje znajdują się przy zmiennych zdaniowych. Dokładniej,
formuły w negacyjnej postaci normalnej, składają się z koniunkcji, alternatywy
i literałów, gdzie literały to zanegowane lub niezanegowane zmienne zdaniowe.
Takie formuły można opisać następującym typem danych, sparametryzowanym
typem opisującym zmienne.
( define-type ( NNF 'v)
( nnf-lit [ polarity : Boolean ] [ var : 'v ])
( nnf-conj [l : ( NNF 'v)] [r : ( NNF 'v) ])
( nnf-disj [l : ( NNF 'v)] [r : ( NNF 'v) ]) )
Flaga polarity w konstruktorze literału oznacza, czy zmienna jest zanegowana
(wartość #f), czy nie (wartość #t). Sformułuj zasadę indukcji dla typu NNF.
*Zasada indukcji*
Niech P(x) bedzie wlasnoscia formuly w nnf. Jesli zachodzi:
- Dla kazdego literalu v jest spelnione P(v)
- Dla wszystkich formul ϕ i ψ jesli zachodzi P(ϕ) i P(ψ), to P(ϕ v ψ) i P(ψ ∧ ϕ)
jest rowniez spelnione.
To wlasnosc zachodzi dla wszystkich formul w nnf.
### Zadanie 4.
Zdefiniuj funkcję neg-nnf typu ((NNF 'a) -> (NNF 'a)) negującą formułę w ne-
gacyjnej postaci normalnej. Następnie pokaż, że (neg-nnf (neg-nnf φ)) ≡ φ dla
dowolnej formuły φ.
``` c
(define (neg-nnf f)
(if (nnf-lit? f)
(nnf-lit (not (nnf-polarity f)) (nnf-var f))
(cond
[(nnf-conj? f) (nnf-disj (neg-nnf (nnf-conj-l f)) (neg-nnf (nnf-conj-r f)))] ; z praw de Morgana
[else (nnf-conj (neg-nnf (nnf-disj-l f)) (neg-nnf (nnf-disj-r f)))])))
```
Twierdzenie: P(f) := (neg-nnf (neg-nnf φ)) ≡ φ
Dowod przez indukcje strukturalna: \pfi
Weźmy dowolny literal v, wtedy
Rozpatrzmy przypadki:
* I literal jest zanegowany v = (neg-lit #t (nnf-lit-var v)))
Wtedy z def. neg-nnf
(neg-nnf (neg-nnf v)) = (neg-nnf (neg-nnf (neg-lit #t (nnf-lit-var v))))) =
= (neg-nnf (neg-lit (not #t) (nnf-lit-var v)))) = (neg-nnf (neg-lit #f (nnf-lit-var v)))) =
= (neg-lit (not #f) (nnf-lit-var v)) = (neg-lit #t (nnf-lit-var v))) = v
* II nie jest
Podobnie jak w I przypadku (zamienic wszystkie wystapienia #t na #f)
*Krok indukcyjny*
Zal, że (neg-nnf (neg-nnf s)) ≡ s i (neg-nnf (neg-nnf t)) ≡ t, dla pewnych formul s,t w nnf
Pokazemy, ze zachodzi (neg-nnf (neg-nnf s ∨ t)) ≡ s v t
(neg-nnf (neg-nnf s ∧ t)) ≡ s ∧ t
Dla alternatywy:
(neg-nnf (neg-nnf s ∨ t)) = (neg-nnf (nnf-conj (neg-nnf s) (neg-nnf t))) =
= (nnf-disj (neg-nnf (neg-nnf s)) (neg-nnf (neg-nnf s))) = (z zal ind) =
(nnf-disj s v t) = s v t
Dla ∧ podobnie (wszystkie wystapienia disj zamienic na conj i ∨ na ∧)
### Zadanie 5
Zdefiniuj funkcję eval-nnf typu (('a -> Boolean) (NNF 'a) -> Boolean) interpre-
tującą formułę w negacyjnej postaci normalnej, przy zadanym wartościowa-
niu zmiennych (funkcji typu ('a -> Boolean)). Następnie pokaż, że dla dowol-
nej formuły φ i wartościowania σ zachodzi (eval-nnf σ (neg-nnf φ)) ≡ (not
(eval-nnf σ φ)). Możesz założyć, że funkcja σ zawsze się zatrzymuje.
```racket=
(define (eval-nnf val neg-f)
(if (nnf-lit? neg-f)
[if (equal? (val (nnf-lit-var neg-f)) #t)
(not (val (nnf-lit-var neg-f)))
(val (nnf-lit-var neg-f))]
(cond
[(nnf-conj? neg-f) (and (eval-nnf val (nnf-conj-l neg-f)) (eval-nnf val (nnf-conj-r neg-f)))]
[else (or (eval-nnf val (nnf-disj-l neg-f)) (eval-nnf val (nnf-disj-r neg-f)))])))
```
P(ψ) := Dla dowolnej formuly ψ i wart σ zachodzi (eval-nnf σ (neg-nnf ψ )) ≡ (not (eval-nnf σ ψ ))
Dowod:
*Baza*
Wezmy dowolny literal ψ i wartosciowanie σ:
-Rozpatrzmy przypadki
1. ψ jest zanegowanym literalem, czyli ψ := (neg-lit #t v)
L = (eval-nnf σ (neg-nnf ψ )) = (eval-nnf σ (neg-nnf (neg-lit #t v))) =
(z def. neg-nnf) = (eval-nnf σ (neg-lit (not # t) v)) = (eval-nnf σ (neg-lit #f v)) =
(z def eval-nnf) = (σ v)
P = (not (eval-nnf σ ψ )) = (not (eval-nnf σ (neg-lit #t v)) ) =
= (z def eval-nnf) = (not (not σ v)) = (σ v)
$L=P$
2. ψ jest niezanegowanym literalem, czyli ψ := (neg-lit #f v)
L = (eval-nnf σ (neg-nnf ψ )) = (eval-nnf σ (neg-nnf (neg-lit #f v))) =
= (z def. neg-nnf) = (eval-nnf σ (neg-lit #t v)) = (z def. eval-nnf) =
(not (σ v))
P = (not (eval-nnf σ ψ )) = (not (eval-nnf σ (neg-lit #f v)) ) =
(z def. eval-nnf) = (not (σ v))
$L=P$
*Krok ind.*
Zal, ze dla dowolnej formuly ψ, θ i wart σ zachodzi (eval-nnf σ (neg-nnf ψ )) ≡ (not (eval-nnf σ ψ ))
(eval-nnf σ (neg-nnf θ )) ≡ (not (eval-nnf σ θ ))
Pokazemy:
1. Alternatywa
(eval-nnf σ (neg-nnf (disj ψ θ) )) ≡ (not (eval-nnf σ (disj ψ θ) ))
L = (eval-nnf σ (neg-nnf (disj ψ θ ) )) = (z def neg-nnf) =
= (eval-nnf σ (nnf-conj (neg-nnf ψ ) (neg-nnf θ ))) = (z def eval-nnf) =
= (and (eval-nnf σ (neg-nnf ψ )) (eval-nnf σ (neg-nnf θ ))) = (z zal. ind) =
= (and (not (eval-nnf σ ψ )) (not (eval-nnf σ θ ))) = (z praw de Morgana) =
= (not (eval-nnf σ (disj ψ θ) )) = P
2. Koniunkcja
(eval-nnf σ (neg-nnf (conj ψ θ) )) ≡ (not (eval-nnf σ (conj ψ θ) ))
L = (eval-nnf σ (neg-nnf (conj ψ θ) )) = (z def. neg-nnf) = (eval-nnf σ (disj (nnf-neg ψ) (neg-nnf θ)))
= (z def eval-nnf) = (or (eval-nnf σ (nnf-neg ψ )) (eval-nnf σ (nnf-neg θ)))
= (z zal ind) = (or (not (eval-nnf σ ψ )) (not (eval-nnf σ θ ))) = (z praw de Morgana)=
= (not (and (eval-nnf σ ψ ) (eval-nnf σ θ ))) = (not (eval-nnf σ (conj ψ θ)))
### Zadanie 6.
Formuły rachunku zdań możemy opisać następującym typem.
```racket=
( define-type ( Formula
( var [ var : 'v ])
( neg [ f : ( Formula 'v) 'v) ])
( conj [ l : ( Formula 'v)] [r : ( Formula 'v) ])
( disj [ l : ( Formula 'v)] [r : ( Formula 'v) ]) )
```
Zdefiniuj funkcję to-nnf transformującą formułę do równoważnej formuły w ne-
gacyjnej postaci normalnej. Możesz definiować funkcję pomocnicze, ale wszyst-
kie funkcje (wzajemnie) rekurencyjne powinny używać rekursji strukturalnej.
$Rozwiazanie$
Korzystam z Whitebook'a

W moim przypadku odwzorowanie T: to-nnf, a F: helper-nnf
```racket=
( define-type ( Formula 'v)
( var [ var : 'v ])
( neg [ f : ( Formula 'v)])
( conj [ l : ( Formula 'v)] [r : ( Formula 'v) ])
( disj [ l : ( Formula 'v)] [r : ( Formula 'v) ]))
(define (helper-nnf f)
(cond [(var? f) (nnf-lit #f f)]
[(neg? f) (to-nnf (neg-f f))]
[(conj? f) (nnf-disj (helper-nnf (conj-l f) ) (helper-nnf (conj-r f)))]
[(disj? f) (nnf-conj (helper-nnf (disj-l f) ) (helper-nnf (disj-r f)))]))
(define (to-nnf f)
(cond [(var? f) (nnf-lit #t f)]
[(neg? f) (helper-nnf (neg-f f))]
[(conj? f) (nnf-conj (to-nnf (conj-l f) ) (to-nnf (conj-r f)))]
[(disj? f) (nnf-disj (to-nnf (disj-l f) ) (to-nnf (disj-r f)))]))
```
### Zadanie 7.
Zdefiniuj funkcję eval-formula interpretującą formuły z poprzedniego zadania.
Następnie pokaż, że (eval-nnf σ (to-nnf φ)) ≡ (eval-formula σ φ). Możesz za-
łożyć, że funkcja σ zawsze się zatrzymuje.
```racket=
( define-type ( Formula 'v )
( var [ var : 'v ])
( neg [ f : ( Formula 'v ) ])
( conj [ l : ( Formula 'v ) ] [ r : ( Formula 'v ) ])
( disj [ l : ( Formula 'v ) ] [ r : ( Formula 'v ) ]) )
( define-type ( NNF 'v )
( nnf-lit [ polarity : Boolean ] [ var : 'v ])
( nnf-conj [ l : ( NNF 'v ) ] [ r : ( NNF 'v ) ])
( nnf-disj [ l : ( NNF 'v ) ] [ r : ( NNF 'v ) ]) )
(define (eval-nnf val neg-f)
(if (nnf-lit? neg-f)
[if (equal? (val (nnf-lit-var neg-f)) #t)
(not (val (nnf-lit-var neg-f)))
(val (nnf-lit-var neg-f))]
(cond
[(nnf-conj? neg-f) (or (eval-nnf val (nnf-conj-l neg-f)) (eval-nnf val (nnf-conj-r neg-f)))]
[else (and (eval-nnf val (nnf-disj-l neg-f)) (eval-nnf val (nnf-disj-r neg-f)))])))
(define (helper-nnf f)
(cond [(var? f) (nnf-lit #f f)]
[(neg? f) (to-nnf (neg-f f))]
[(conj? f) (nnf-disj (helper-nnf (conj-l f) ) (helper-nnf (conj-r f)))]
[(disj? f) (nnf-conj (helper-nnf (disj-l f) ) (helper-nnf (disj-r f)))]))
(define (to-nnf f)
(cond [(var? f) (nnf-lit #t f)]
[(neg? f) (helper-nnf (neg-f f))]
[(conj? f) (nnf-conj (to-nnf (conj-l f) ) (to-nnf (conj-r f)))]
[(disj? f) (nnf-disj (to-nnf (disj-l f) ) (to-nnf (disj-r f)))]))
(define (eval-formula σ φ)
(cond [(var? φ)
(σ φ)]
[(neg? φ)
(not (eval-formula σ (neg-f φ)))]
[(conj? φ)
(and (eval-formula σ (conj-l φ))
(eval-formula σ (conj-r φ)))]
[(disj? φ)
(or (eval-formula σ (disj-l φ))
(eval-formula σ (disj-r φ)))]))
```
Twierdzenie: P(ψ) := (eval-nnf σ (to-nnf ψ )) ≡ (eval-formula σ ψ)
Dowod przez indukcje:
Baza:
Wezmy dowolna zmienna zdaniowa p
L = (eval-nnf σ (to-nnf p)) = (z def. to-nnf) =(eval-nnf σ (nnf-lit #f f)) = (σ f)
P = (eval-formula σ p) = (σ p)
$L=P$
*Krok indukcyjny*
Zal, ze P zachodzi dla dowolnych formul ψ, θ
Zalozenie: (eval-nnf σ (to-nnf ψ )) ≡ (eval-formula σ ψ)
(eval-nnf σ (to-nnf θ )) ≡ (eval-formula σ θ )
**Teza**:
* Alternatywa: (eval-nnf σ (to-nnf (disj ψ θ) )) ≡ (eval-formula σ (disj ψ θ ))
L =(eval-nnf σ (to-nnf (disj ψ θ) ))= (z def. to-nnf) =
(eval-nnf σ (nnf-disj (to-nnf ψ ) (to-nnf θ))) = (z def. eval-nnf)=
(or (eval-nnf σ (to-nnf ψ )) (eval-nnf σ (to-nnf θ))) = (z zal ind)=
(or (eval-formula σ ψ) (eval-formula σ θ )) = (z def eval-formula) =
(eval-formula σ (disj ψ θ )) = P
* Koniunkcja: (eval-nnf σ (to-nnf (conj ψ θ) )) ≡ (eval-formula σ (conj ψ θ ))
L = (eval-nnf σ (to-nnf (conj ψ θ) )) =
= (eval-nnf σ (nnf-conj (to-nnf ψ) (to-nnf θ)))
= (and (eval-nnf σ (to-nnf ψ )) (eval-nnf σ (to-nnf θ))) = (z zal ind)=
= (and (eval-formula σ ψ) (eval-formula σ θ )) = (z def eval-formula) =
= (eval-formula σ (conj ψ θ )) = P
* Negacja: (eval-nnf σ (to-nnf (neg ψ) )) ≡ (eval-formula σ (neg ψ))
*Korzystam z lematu:*
(not (eval-nnf σ (to-nnf φ))) ≡ (eval-nnf σ (helper-nnf φ))
(eval-nnf σ (to-nnf (neg φ))) ≡ (eval-formula σ (neg φ))
(not (eval-nnf σ (to-nnf (neg φ)))) ≡ (eval-nnf σ (helper-nnf (neg φ)))
L ≡ (eval-nnf σ (to-nnf (neg φ))) ≡
(eval-nnf σ (helper-nnf φ)) ≡
P ≡ (eval-formula σ (neg φ)) ≡
(not (eval-formula σ φ)) ≡ (z zał. ind)
(not (eval-nnf σ (to-nnf φ))) ≡ (eval-nnf σ (helper-nnf φ)) ≡ L (z lematu)
**Dowod lematu:**
(not (eval-nnf σ (to-nnf φ))) ≡ (eval-nnf σ (helper-nnf φ))
i) Wezmy dowolna zmiennA p
L ≡ (not (eval-nnf σ (to-nnf p))) ≡
(not (eval-nnf σ (nnf-lit #t p)) ≡
(not (σ (nnf-lit-var φ)))
P ≡ (eval-nnf σ (helper-nnf p)) ≡
(eval-nnf σ (nnf-lit #f p)) ≡
(not (σ (nnf-lit-var φ))) ≡ L
*Krok indukcyjny*
Wezmy dowolne formuły ψ, θ
Zalozenia:
(not (eval-nnf σ (to-nnf φ))) ≡ (eval-nnf σ (helper-nnf φ))
(not (eval-nnf σ (to-nnf θ))) ≡ (eval-nnf σ (helper-nnf θ))
Alternatywa: (not (eval-nnf σ (to-nnf (disj φ θ)))) ≡ (eval-nnf σ (helper-nnf (disj φ θ)))
L ≡ (not (eval-nnf σ (to-nnf (disj φ θ)))) ≡
(not (eval-nnf σ (nnf-disj (to-nnf φ) (to-nnf θ)) ≡
(not (or (eval-nnf σ (to-nnf φ)) (eval-nnf σ (to-nnf θ))) ≡
(and (not (eval-nnf σ (to-nnf φ)) (not (eval-nnf σ (to-nnf θ))) ≡
(and (eval-nnf σ (helper-nnf φ)) (eval-nnf σ (helper-nnf θ)))
P ≡ (eval-nnf σ (helper-nnf (disj φ θ))) ≡
(eval-nnf σ (nnf-conj (helper-nnf φ ) (helper-nnf θ)) ≡
(and (eval-nnf σ (helper-nnf φ )) (eval-nnf σ (helper-nnf θ))) ≡ L
Konjunkcja: (not (eval-nnf σ (to-nnf (conj φ θ)))) ≡ (eval-nnf σ (helper-nnf (conj φ θ)))
L ≡ (not (eval-nnf σ (to-nnf (conj φ θ)))) ≡
(not (eval-nnf σ (nnf-conj (to-nnf φ) (to-nnf θ)) ≡
(not (and (eval-nnf σ (to-nnf φ)) (eval-nnf σ (to-nnf θ))) ≡
(or (not (eval-nnf σ (to-nnf φ)) (not (eval-nnf σ (to-nnf θ))) ≡
(or (eval-nnf σ (helper-nnf φ)) (eval-nnf σ (helper-nnf θ)))
P ≡ (eval-nnf σ (helper-nnf (conj φ θ))) ≡
(eval-nnf σ (nnf-disj (helper-nnf φ ) (helper-nnf θ)) ≡
(or (eval-nnf σ (helper-nnf φ )) (eval-nnf σ (helper-nnf θ))) ≡ L
Negacja: (not (eval-nnf σ (to-nnf (neg φ)))) ≡ (eval-nnf σ (helper-nnf (neg φ)))
L ≡ (not (eval-nnf σ (to-nnf (neg φ)))) ≡
(not (eval-nnf σ (to-nnf (neg φ)))) ≡
(not (eval-nnf σ (helper-nnf φ))) ≡ (z zał. ind)
(not (not (eval-nnf σ (to-nnf φ)))) ≡
(eval-nnf σ (to-nnf φ))
P ≡ (eval-nnf σ (helper-nnf (neg φ))) ≡
(eval-nnf σ (to-nnf φ)) ≡ L
**Na mocy zasady indukcji strukturalnej wlasnosc P zostala udowodniona**
### Zadanie 8.
Zdefiniuj predykat sorted? : ((Listof Number) -> Boolean) sprawdzający czy li-
sta jest posortowana oraz funkcję insert : (Number (Listof Number) -> (Listof
Number)) wstawiającą element do listy posortowanej. Następnie udowodnij, że
jeśli (sorted? xs) ≡ #t to (sorted? (insert x xs)) ≡ #t.
```racket=
(define (insert x xs)
(if (empty? xs)
(cons x empty)
(if (< x (first xs))
(cons x xs)
(cons (first xs) (insert x (rest xs))))))
(define (bound x xs)
(if (empty? xs)
#t
(<= x (first xs))))
(define (sorted? xs)
(if (empty? xs)
#t
(and (sorted? (r xs)) (bound? (first x) (rest xs)))))
```
Funkcja *insert* w algorytmie
*insertion-sort* zachowuje fakt, ze lista jest posortowana
*P(xs) := Jesli (sorted? xs) = #t ⟹ (sorted? (insert x xs)) = #t*
Dowód przez indukcje strukturalna względem xs
Baza: xs = empty
P(empty)
L = (sorted? empty) = #t (bo lista pusta jest posortowana)
P = (sorted? (insert x empty)) = (sorted? (cons x empty)) = #t (bo lista jednoelementowa jest posortowana)
Krok indukcyjny:
Zalozenie: (sorted? xs) = #t ⟹ (sorted? (insert y xs)) = #t
Teza: (sorted? (cons x xs)) = #t ⟹ (sorted? (insert y (cons x xs))) = #t
P = (sorted? (insert y (cons x xs)))
Rozpatrzymy przypadki:
x - (first xs)
1. y <= x
(insert y (cons x xs)) =
(cons y (cons x xs)
Wiemy, ze (sorted? (cons x xs)) = #t (z zal) i y <= x, wiec
jezeli wstawimy y do (cons x xs), to (sorted? (cons y (cons x xs))) = #t
2. y > x
(insert y (cons x xs)) =(cons x (insert y xs))
Z zal ind. wiem, ze (sorted? (insert y xs)) = *#t,* i ze
(sorted? xs) = #t (bo xs jest posortowane)
(bound? y xs) = #t (bo każdy element w xs jest mniejszy lub równy $y$)
czyli po wstawieniu $y$ do listy $xs$,
stworzy sie nowa lista posortowana, ale juz z wstawionym $y$. Korzystajac z faktu, że $y>x$
mozemy wywnioskować, że (sorted? (insert y (cons x xs))) = *#t*
Na mocy zasady indukcji strukturalnej wlasnosc P zostala udowodniona.