# Pravilnost programov

### Program, ki zamenja `x` in `y`

Program, ki zamenja vrednosti `x` in `y`:

```
{ x = m ∧ y = n }
t := x ;
x := y ;
y := t
{ x = n ∧ y = m }
```

Tudi ta zadošča specifikaciji:

```
{ x = m ∧ y = n }
while true do skip done
{ x = n ∧ y = m }
```

Tudi ta zadošča:
```
{ x = m ∧ y = n }
x := n ;
y := m
{ x = n ∧ y = m }
```

Še enkrat (`c` ne omenja `m` in `n`):
pravimo, da sta `m` in `n` **duhova** (ghost variable)
```
{ x = m ∧ y = n }
c
{ x = n ∧ y = m }
```

### Primer: uredi spremnljivki `x` in `y`

Poskus:
```
{ true }
c
{ x ≤ y }
```

```
{ true }
x := 1 ; y := 7
{ x ≤ y }
```

```
{ x = m ∧ y = n }
c
{ x = min(m, n) ∧ y = max(m, n) }
```
Opomba: `m` in `n` sta duhova.

Rešitev:
```
{ x = m ∧ y = n }
if x > y then 
  t := x ;
  x := y ;
  y := t
else
  skip
end
{ x = min(m, n) ∧ y = max(m, n) }
```

Kaj pa to?

```
{ x = m ∧ y = n }
             -- x = m, y = n
x := x + y ; -- x = m + n, y = n
y := x - y ; -- y = m + n - n = m, x = m + n
x := x - y   -- x = m + n - m = n, y = m
{ x = n ∧ y = m }
```
Opomba: `c` lahko omeni samo `x` in `y`

Bolje:
```
{ x = m ∧ y = n }
x := x + y ;
{ x = m + n ∧ y = n }
y := x - y ;
{ y = m + n - n  ∧ x = m + n }
x := x - y
{ x = m + n - m ∧ y = m } ⇒
{ x = n ∧ y = m }
```

### Naloga

```
{ x ≤ 7 }    ⇒ (prištejemo 3)
{ x + 3 ≤ 10 }
x := x + 3
{ x ≤ 10 }
```

### Naloga:

Zapiši: `c` se ne ustavi (odgovor: `{true} c {false}`)
Zapiši: `c` se ustavi (odgovor: `[ true  ] c [ true ]`)

```
{ true  } c { true  }
-- vedno res, ker ϕ ⇒ true velja


{ true  } c { false }
"true ∧ (c se ustavi) ⇒ false" ⇔
"(c se ustavi) ⇒ false"        ⇔ opomba: ϕ ⇒ false
                                          je ekvivalentno
                                          ¬ ϕ 
"ne (c se ustavi)"
"c se ne ustavi"

{ false } c { true  }  -- vedno res
"false ∧ (c se ustavi) ⇒ true"
"false ⇒ true"
"true"


{ false } c { false }  -- vedno res
"false ∧ (c se ustavi) ⇒ false"
"false ⇒ false"
"true"

[ true  ] c [ true ]
"true ⇒ c se ustavi ∧ true"
"true ⇒ c se ustavi"
"c se ustavi"


[ true  ] c [ false ]  -- nikoli ne velja
"true ⇒ c se ustavi ∧ false"
"true ⇒ false"
"false"

[ false ] c [ true  ]  -- vedno velja
"false ⇒ c se ustavi ∧ true"
"true"

[ false ] c [ false ]  -- vedno velja
"false ⇒ c se ustavi ∧ true"
```

### Naloga

```
{ x ≤ y }                                 ⇒
{ x + x ≤ x + y ≤ y + y }                 ⇒
{ (x + x) / 2 ≤ (x + y) / 2 ≤ (y + y)/2 } ⇒
{ x ≤ (x + y)/2 ≤ y }
s := (x + y)/2
{ x ≤ s ≤ y }
```


### Naloga

```
[ b ≥ 0 ]
i := 0 ;
p := 1 ;
while i < b do
   p := p * a ;
   i := i + 1
done
[ p = a ^ b ]
```

Najprej dokažemo delno pravilnost:

```
{ b ≥ 0 }
i := 0 ;
{ b ≥ 0, i = 0 }
p := 1 ;
{ b ≥ 0, i = 0, p = 1 }
?

{ p = a^i, i ≤ b }
while i < b do
   { p = a^i, i ≤ b, i < b }  ⇒ (malo manj očitno)
   { p · a = a^(i+1), i+1 ≤ b }
   p := p * a ;
   { p = a^(i+1), i+1 ≤ b }
   i := i + 1
   { p = a^i, i ≤ b }
done
{ p = a^i, i ≤ b, i ≥ b }  ⇒
{ p = a^i, i = b }         ⇒
{ p = a^b }
```

Preverimo, da se `b - i` zmanjšuje (`b - i ≥ 0` že vemo)
Telo zanke:

```
  [ b - i = z ]        ⇒
  [ b - i - 1 < z ]    ⇒
  [ b - (i + 1) < z ]
  p := p * a ;
  [ b - (i + 1) < z ]
  i := i + 1
  [ b - i < z ]

```

### Naloga

```
[ x = m ∧ y = n ]
if y < x then
   [ x = m ∧ y = n, y < x ]           => (easy)
   [ y = min(m, n) ∧ x = max(m, n) ]
   [ y = min(m, n) ∧ (x + y) - y = max(m, n) ]
   x := x + y ;
   [ y = min(m, n) ∧ x - y = max(m, n) ]
   [ x - (x - y) = min(m, n) ∧ x - y = max(m, n) ]
   y := x - y ;
   [ x - y = min(m, n) ∧ y = max(m, n) ]
   x := x - y
   [ x = min(m, n) ∧ y = max(m, n) ]
else
   [ x = m ∧ y = n, ¬ (y < x) ]  ⇒
   [ x = m ∧ y = n, x ≤ y ]
   skip
   [ x = m ∧ y = n, x ≤ y ]           ⇒ (easy)
   [ x = min(m, n) ∧ y = max(m, n) ]
end
[ x = min(m, n) ∧ y = max(m, n) ]
```
