Repository navigation
Expand file tree
/
Copy pathsorting.clj
More file actions
203 lines (167 loc) · 7.83 KB
/
Copy pathsorting.clj
File metadata and controls
203 lines (167 loc) · 7.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
(require '[ansatz.core :as a])
(a/init! "/var/tmp/ansatz-cslib" "cslib")
(println "\n╔═══════════════════════════════════════════════════════════╗")
(println "║ Kernel-Verified Sorting — Merge Sort on Lists ║")
(println "║ Inspired by CSLib (Lean 4 Computer Science Library) ║")
(println "╚═══════════════════════════════════════════════════════════╝\n")
;; ============================================================
;; 1. Merge — combine two sorted lists
;; ============================================================
;; Well-founded recursion with compound measure:
;; termination_by length(xs) + length(ys)
;; Each recursive call reduces at least one list, so the sum decreases.
(println "━━━ 1. Verified Merge ━━━\n")
(a/defn merge [xs :- (List Nat), ys :- (List Nat)] (List Nat)
:termination-by (+ (List.length xs) (List.length ys))
(match xs (List Nat) (List Nat)
(nil ys)
(cons [x xs']
(match ys (List Nat) (List Nat)
(nil (cons x xs'))
(cons [y ys']
(if (<= x y)
(cons x (merge xs' (cons y ys')))
(cons y (merge (cons x xs') ys'))))))))
(println "(merge '(1 3 5) '(2 4 6)) =>" (merge '(1 3 5) '(2 4 6)))
(println "(merge '() '(1 2)) =>" (merge '() '(1 2)))
(println "(merge '(1) '()) =>" (merge '(1) '()))
;; ============================================================
;; 2. Take / Drop — split a list at position n
;; ============================================================
(println "\n━━━ 2. Verified Take / Drop ━━━\n")
(a/defn take [n :- Nat, xs :- (List Nat)] (List Nat)
:termination-by n
(match n Nat (List Nat)
(zero nil)
(succ [k]
(match xs (List Nat) (List Nat)
(nil nil)
(cons [hd tl] (cons hd (take k tl)))))))
(a/defn drop [n :- Nat, xs :- (List Nat)] (List Nat)
:termination-by n
(match n Nat (List Nat)
(zero xs)
(succ [k]
(match xs (List Nat) (List Nat)
(nil nil)
(cons [hd tl] (drop k tl))))))
(println "(take 2 '(1 2 3 4)) =>" (take 2 '(1 2 3 4)))
(println "(drop 2 '(1 2 3 4)) =>" (drop 2 '(1 2 3 4)))
;; ============================================================
;; 3. Merge Sort — recursive divide-and-conquer
;; ============================================================
;; Well-founded recursion with measure: length(xs)
;; Each recursive call operates on half the list.
(println "\n━━━ 3. Verified Merge Sort ━━━\n")
(a/defn sort [xs :- (List Nat)] (List Nat)
:termination-by (List.length xs)
(match xs (List Nat) (List Nat)
(nil nil)
(cons [hd tl]
(match tl (List Nat) (List Nat)
;; Single element — already sorted
(nil (cons hd nil))
;; Two or more — split, sort recursively, merge
(cons [hd2 tl2]
(merge
(sort (take (/ (+ 2 (List.length tl2)) 2)
(cons hd (cons hd2 tl2))))
(sort (drop (/ (+ 2 (List.length tl2)) 2)
(cons hd (cons hd2 tl2))))))))))
(println "(sort '(5 3 1 4 2)) =>" (sort '(5 3 1 4 2)))
(println "(sort '(9 1 8 2 7 3)) =>" (sort '(9 1 8 2 7 3)))
(println "(sort '()) =>" (sort '()))
(println "(sort '(42)) =>" (sort '(42)))
(println "(sort '(2 1)) =>" (sort '(2 1)))
;; ============================================================
;; 4. Structures — Clojure defrecord integration
;; ============================================================
(println "\n━━━ 4. Verified Structures (→ defrecord) ━━━\n")
(a/structure Point [] (x Nat) (y Nat))
(a/defn manhattan [p :- Point] Nat (+ (:x p) (:y p)))
(let [p (->Point 3 4)]
(println "Point: " p)
(println "(:x p) =" (:x p))
(println "(manhattan p)=" (manhattan p)))
;; ============================================================
;; 5. Factorial — classic WF recursion
;; ============================================================
(println "\n━━━ 5. Verified Factorial (Well-Founded Recursion) ━━━\n")
(a/defn fact [n :- Nat] Nat
:termination-by n
(if (== n 0) 1 (* n (fact (- n 1)))))
(doseq [n (range 8)]
(println (str "(fact " n ") = " (fact n))))
;; ============================================================
;; 6. Verified Insertion Sort with Correctness Proof
;; ============================================================
(println "\n━━━ 6. Insertion Sort + Correctness Proof ━━━\n")
(a/defn insertSorted [x :- Nat, l :- (List Nat)] (List Nat)
(match l (List Nat) (List Nat)
(nil (cons x nil))
(cons [hd tl] (match (<= x hd) Bool (List Nat)
(true (cons x l)) (false (cons hd ih_tail))))))
(a/defn isort [l :- (List Nat)] (List Nat)
(match l (List Nat) (List Nat)
(nil nil)
(cons [hd tl] (insertSorted hd ih_tail))))
(println "(isort '(5 3 1 4 2)) =>" (isort '(5 3 1 4 2)))
;; Define Sorted as a Prop-valued indexed inductive:
;; Sorted : List Nat → Prop
(a/inductive Sorted [] :in Prop :indices [l (List Nat)]
(nil :where [(nil)])
(single [a Nat] :where [(cons a nil)])
(cons_cons [a Nat] [b Nat] [tl (List Nat)]
[hab (le a b)] [hsorted (Sorted (cons b tl))]
:where [(cons a (cons b tl))]))
;; THE CORRECTNESS THEOREM:
;; "Inserting into a sorted list preserves sortedness"
;;
;; grind handles all 3 induction cases automatically:
;; nil → constructor (Sorted.single)
;; single → case-split on x<=a, simp, constructor + omega
;; cons_cons → nested case-splits on x<=a and x<=b, constructors + IH + omega
(a/theorem insert-preserves
[x :- Nat, l :- (List Nat), h :- (Sorted l)]
(Sorted (insertSorted x l))
(induction h)
(grind "insertSorted"))
(println "✓ Proved: Sorted l → Sorted(insertSorted x l)")
(println " (kernel-verified by CIC type checker)")
;; ============================================================
;; 7. Manual Proof (for comparison)
;; ============================================================
;; The same theorem proved step-by-step without grind.
;; Each tactic line corresponds to a specific proof obligation.
(println "\n━━━ 7. Same Proof — Manual Tactics (for comparison) ━━━\n")
(a/theorem insert-preserves-manual
[x :- Nat, l :- (List Nat), h :- (Sorted l)]
(Sorted (insertSorted x l))
;; Induction on h : Sorted l (3 cases: nil, single, cons_cons)
(induction h)
;; Nil case: insertSorted x [] = [x], need Sorted.single
(apply (Sorted.single x))
;; Case-split on x <= a, unfold insertSorted in each branch
(all_goals (try (by_cases (<= x a))))
(all_goals (try (simp_all "insertSorted")))
;; Sub-split cons_cons case on x <= b
(all_goals (try (by_cases (<= x b))))
(all_goals (try (simp_all "insertSorted")))
(all_goals (try (simp_all "insertSorted")))
;; Close remaining: constructors + arithmetic + assumptions
(all_goals (try (apply Sorted.cons_cons)))
(all_goals (try (omega)))
(all_goals (try (apply Sorted.single)))
(all_goals (try (assumption)))
(all_goals (try (apply Sorted.cons_cons)))
(all_goals (try (omega)))
(all_goals (try (assumption))))
(println "✓ Same theorem proved with 14 manual tactic lines")
(println " (grind automates all of this from the induction hypothesis)")
(println "\n━━━ Summary ━━━\n")
(println "All functions and theorems above are:")
(println " 1. Type-checked by the CIC kernel (same type theory as Lean 4)")
(println " 2. Compiled to native Clojure (defrecord, flat calls, persistent lists)")
(println " 3. Equipped with equation theorems for use in proofs")
(println " 4. Termination-verified via fuel-based Nat.rec measures")
(println " 5. Correctness properties formally proved (insertion sort preserves sortedness)")