/-- **Partial correctness of division**, proved *inside Hoare logic* and then transported to the
semantics by `soundness`:
`{0 ≤ a ∧ 0 < b} divProg {a = q·b + r ∧ 0 ≤ r < b}`.
The only creative step is the invariant `divInv`; the rest is the verification conditions
`pre → I[q:=0][r:=a]`, `I ∧ b ≤ r → I[q:=q+1][r:=r-b]` and `I ∧ ¬(b ≤ r) → post`. -/
theorem div_correct :
Hoare (fun s => 0 ≤ s "a" ∧ 0 < s "b") divProg
(fun t => t "a" = t "q" * t "b" + t "r" ∧ 0 ≤ t "r" ∧ t "r" < t "b") := by
apply soundness
-- the loop body preserves the invariant
have body : Derivable (fun s => divInv s ∧ decide (s "b" ≤ s "r") = true)
(.seq (.assign "r" (fun s => s "r" - s "b")) (.assign "q" (fun s => s "q" + 1))) divInv := by
refine .conseq ?_ (.seq (.assign _ _ _) (.assign divInv _ _)) (fun _ h => h)
intro s ⟨⟨ha, hr, hb⟩, hle⟩
simp only [decide_eq_true_eq] at hle
simp only [divInv, Function.update_apply]
simp only [String.reduceEq, ite_false, ite_true]
refine ⟨by rw [ha]; ring, by linarith, hb⟩
refine .conseq ?_ (.seq (.assign _ _ _) (.seq (.assign _ _ _) (.while body))) ?_
· intro s ⟨ha, hb⟩
simp only [divInv, Function.update_apply]
simp only [String.reduceEq, ite_false, ite_true]
exact ⟨by ring, ha, hb⟩
· intro t ⟨⟨ha, hr, _⟩, hlt⟩
simp only [decide_eq_false_iff_not, not_le] at hlt
exact ⟨ha, hr, hlt⟩