Skip to content

Commit 0ce3364

Browse files
authored
Add Example from VeHa competition (#26)
1 parent e0f37f6 commit 0ce3364

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import Auto
2+
import Lean
3+
4+
import CaseStudies.Velvet.Std
5+
import CaseStudies.TestingUtil
6+
7+
set_option loom.semantics.termination "total"
8+
set_option loom.semantics.choice "demonic"
9+
set_option loom.solver "cvc5"
10+
set_option loom.solver.smt.timeout 5
11+
12+
--this will ne our answer type
13+
structure SubstringResult where
14+
l : Nat
15+
r : Nat
16+
flag: Bool
17+
deriving Repr, Inhabited
18+
19+
--predicate for substring all characters of which satisfy the predicate
20+
@[loomAbstractionSimp]
21+
def CorrectSubstring (s : Array Char) (p : Char -> Bool) (l r : Nat) : Prop :=
22+
l ≤ r ∧ r < s.size ∧
23+
(∀ i, l ≤ i ∧ i ≤ r → p s[i]!)
24+
25+
--actual method
26+
-- if there are no substrings,
27+
-- flag is false and all characters do not satisfy the predicate
28+
method SubstringSearch (s: Array Char) (p: Char -> Bool) return (res: SubstringResult)
29+
--postconditions, don't need any preconditions.
30+
ensures (res.l ≤ res.r)
31+
ensures 0 < s.size → res.r < s.size
32+
ensures res.flag → CorrectSubstring s p res.l res.r
33+
ensures res.flag →
34+
(∀ l₁ r₁, CorrectSubstring s p l₁ r₁ →
35+
r₁ - l₁ + 1 = res.r - res.l + 1 ∧ res.r ≤ r₁ ∨
36+
r₁ - l₁ + 1 < res.r - res.l + 1)
37+
ensures ¬res.flag → ∀ i < s.size, ¬p s[i]!
38+
do
39+
if s.size = 0 then
40+
--basic case with an empty string
41+
return0, 0, false
42+
let mut cnt := 0
43+
let mut pnt := 0
44+
let mut ans := 0
45+
let mut l_ans := 0
46+
let mut r_ans := 0
47+
while pnt < s.size
48+
--loop invariants
49+
invariant 0 ≤ cnt
50+
invariant cnt ≤ pnt
51+
invariant pnt ≤ s.size
52+
invariant l_ans ≤ r_ans
53+
invariant r_ans < s.size
54+
invariant cnt ≤ ans
55+
invariant r_ans ≤ pnt
56+
invariant ∀ j, pnt - cnt ≤ j ∧ j < pnt → p s[j]!
57+
invariant ans > 0
58+
ans = r_ans - l_ans + 1
59+
CorrectSubstring s p l_ans r_ans
60+
invariant ans = 0 → (∀ i, i < pnt → ¬p s[i]!)
61+
invariant cnt < pnt → ¬p s[pnt - cnt - 1]!
62+
invariant ∀ l₁ r₁,
63+
CorrectSubstring s p l₁ r₁ ∧ r₁ < pnt →
64+
r₁ - l₁ + 1 = ans ∧ r_ans ≤ r₁ ∨ r₁ - l₁ + 1 < ans
65+
--value decreases by 1 with each iteration,
66+
--therefore time complexity is O(size s), as other parts
67+
--take constant time
68+
decreasing s.size - pnt
69+
do
70+
--loop body
71+
if p s[pnt]! then
72+
cnt := cnt + 1
73+
if ans < cnt then
74+
l_ans := pnt + 1 - cnt
75+
r_ans := pnt
76+
ans := cnt
77+
else
78+
cnt := 0
79+
pnt := pnt + 1
80+
return ⟨l_ans, r_ans, ans > 0
81+
82+
prove_correct SubstringSearch by
83+
loom_solve
84+
85+
--prove theorem not about the monadic computation but the actual
86+
--extract result
87+
theorem finalCorrectnessTheorem (s : Array Char) (p : Char → Bool) :
88+
let res := SubstringSearch s p |>.extract
89+
(res.flag = false → ∀ i < s.size, p s[i]! = false) ∧
90+
(res.flag = true
91+
(∀ l₁ r₁, CorrectSubstring s p l₁ r₁ →
92+
r₁ - l₁ + 1 = res.r - res.l + 1 ∧ res.r ≤ r₁ ∨
93+
r₁ - l₁ + 1 < res.r - res.l + 1)) ∧
94+
(res.flag = true → CorrectSubstring s p res.l res.r) ∧
95+
(0 < s.size → res.r < s.size) ∧
96+
(res.l ≤ res.r) := by
97+
grind [VelvetM.extract_spec, SubstringSearch_correct]

0 commit comments

Comments
 (0)