Skip to content

Commit f8ce68b

Browse files
committed
[stdlib]: List: more lemmas on insert and related
1 parent 2bb54a6 commit f8ce68b

File tree

1 file changed

+123
-24
lines changed

1 file changed

+123
-24
lines changed

theories/datatypes/List.ec

Lines changed: 123 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ qed.
343343
344344
lemma onth_some ['a] (xs : 'a list) (n : int) x:
345345
onth xs n = Some x => 0 <= n < size xs /\ nth witness xs n = x.
346-
proof. by rewrite nth_onth => ^h -> /=; elim: xs n x h => //#. qed.
346+
proof. by rewrite nth_onth => ^h -> /=; elim: xs n x h => //=; smt(size_ge0). qed.
347347
348348
lemma onth_some_rg l n (x:'a): onth l n = Some x => 0 <= n < size l.
349349
proof. by move/onth_some. qed.
@@ -819,6 +819,14 @@ lemma drop_cat n (s1 s2 : 'a list):
819819
if n < size s1 then drop n s1 ++ s2 else drop (n - size s1) s2.
820820
proof. by elim: s1 n => /= [|x s ih] n; smt(drop_le0 size_ge0). qed.
821821
822+
lemma drop_cat_le ['a] (n : int) (s1 s2 : 'a list) :
823+
drop n (s1 ++ s2) =
824+
if n <= size s1 then drop n s1 ++ s2 else drop (n - size s1) s2.
825+
proof.
826+
rewrite drop_cat lez_eqVlt; case: (n = size s1) => [->|] //=.
827+
by rewrite drop0 drop_size.
828+
qed.
829+
822830
lemma drop_size_cat n (s1 s2 : 'a list):
823831
size s1 = n => drop n (s1 ++ s2) = s2.
824832
proof. by move=> <-; rewrite drop_cat subzz ltzz drop0. qed.
@@ -858,7 +866,14 @@ proof. by rewrite /= lezNgt; case: (0 < n). qed.
858866

859867
lemma size_take n (s : 'a list):
860868
0 <= n => size (take n s) = if n < size s then n else size s.
861-
proof. by elim: s n => //= /#. qed.
869+
proof. by elim: s n => //=; smt(size_ge0). qed.
870+
871+
lemma size_take_condle ['a] (n : int) (s : 'a list) :
872+
0 <= n => size (take n s) = if n <= size s then n else size s.
873+
proof.
874+
move=> ge0_n; rewrite size_take // lez_eqVlt.
875+
by case: (n = size s) => [->|].
876+
qed.
862877
863878
lemma size_takel n (s : 'a list ):
864879
0 <= n <= size s => size (take n s) = n.
@@ -879,6 +894,14 @@ lemma take_cat n (s1 s2 : 'a list):
879894
if n < size s1 then take n s1 else s1 ++ take (n - size s1) s2.
880895
proof. by elim: s1 n => //=; smt(take_le0 size_ge0). qed.
881896

897+
lemma take_cat_le ['a] (n : int) (s1 s2 : 'a list) :
898+
take n (s1 ++ s2) =
899+
if n <= size s1 then take n s1 else s1 ++ take (n - size s1) s2.
900+
proof.
901+
rewrite take_cat lez_eqVlt; case: (n = size s1) => [->|] //=.
902+
by rewrite take0 take_size cats0.
903+
qed.
904+
882905
lemma take_size_cat n (s1 s2 : 'a list):
883906
size s1 = n => take n (s1 ++ s2) = s1.
884907
proof. by move=> <-; rewrite take_cat subzz ltzz take0 cats0. qed.
@@ -891,7 +914,7 @@ by elim: n => [|n ge0_n _] /=; rewrite ?take0 //= /#.
891914
qed.
892915
893916
lemma cat_take_drop n (s : 'a list): take n s ++ drop n s = s.
894-
proof. by elim: s n=>/#. qed.
917+
proof. by elim: s n=> /#. qed.
895918

896919
lemma mem_drop n (s:'a list) x: mem (drop n s) x => mem s x.
897920
proof. by rewrite -{2}[s](cat_take_drop n) mem_cat=>->. qed.
@@ -902,29 +925,40 @@ proof. by rewrite -{2}[s](cat_take_drop n) mem_cat=>->. qed.
902925
lemma nth_drop (x0 : 'a) n s i:
903926
0 <= n => 0 <= i => nth x0 (drop n s) i = nth x0 s (n + i).
904927
proof.
905-
move=> n_ge0 i_ge0; case: (n < size s) => [lt_n_s|le_s_n]; last smt(nth_out drop_oversize).
906-
rewrite -{2}(cat_take_drop n s) nth_cat size_take //; smt().
928+
move=> n_ge0 i_ge0; case: (n < size s) => [lt_n_s|le_s_n].
929+
- by rewrite -{2}(cat_take_drop n s) nth_cat size_take //#.
930+
- by rewrite !(nth_out, drop_oversize) //#.
907931
qed.
908932
909933
lemma nth_take (x0 : 'a) n s i:
910934
0 <= n => i < n => nth x0 (take n s) i = nth x0 s i.
911935
proof.
912-
move=> n_ge0 i_ge0; case: (n < size s) => [lt_n_s|le_s_n]; last smt(nth_out take_oversize).
913-
by rewrite -{2}(cat_take_drop n s) nth_cat size_take //; smt().
936+
move=> n_ge0 i_ge0; case: (n < size s) => [lt_n_s|le_s_n].
937+
- by rewrite -{2}(cat_take_drop n s) nth_cat size_take //#.
938+
- by rewrite take_oversize 1:/#.
914939
qed.
915940

916941
lemma take_take (s : 'a list) (i j : int) :
917942
take i (take j s) = if i <= j then take i s else take j s.
918943
proof. by elim: s i j => // /#. qed.
919944
945+
lemma cat_take_insert_drop ['a] (x0 : 'a) (n : int) (s : 'a list) :
946+
0 <= n < size s => take n s ++ nth x0 s n :: drop (n+1) s = s.
947+
proof.
948+
case=> ge0_n lt_n_s; apply/eq_sym/(eq_from_nth x0).
949+
- by rewrite size_cat size_take -1:lt_n_s //= size_drop //#.
950+
move=> i [ge0_i lti]; rewrite nth_cat size_take //= lt_n_s /=.
951+
smt(nth_take nth_drop).
952+
qed.
953+
920954
lemma splitPr (xs : 'a list) (x : 'a): mem xs x =>
921955
exists s1, exists s2, xs = s1 ++ x :: s2.
922956
proof.
923-
move=> x_in_xs; pose i := index x xs.
924-
have lt_ip: i < size xs by rewrite /i index_mem.
925-
exists (take i xs); exists (drop (i+1) xs).
926-
rewrite -{1}(@cat_take_drop i) -(@nth_index x x xs) //.
927-
by rewrite -drop_nth // index_ge0 lt_ip.
957+
move=> x_in_xs; pose i := index x xs.
958+
have lt_ip: i < size xs by rewrite /i index_mem.
959+
exists (take i xs); exists (drop (i+1) xs).
960+
rewrite -{1}(@cat_take_drop i) -(@nth_index x x xs) //.
961+
by rewrite -drop_nth // index_ge0 lt_ip.
928962
qed.
929963

930964
(* -------------------------------------------------------------------- *)
@@ -1121,6 +1155,13 @@ elim: s => //= x s ih; case: (p x)=> @/predC -> //=;
11211155
by rewrite perm_cons. by rewrite perm_cons.
11221156
qed.
11231157
1158+
lemma perm_eq_nth_take_drop ['a] (x0 : 'a) (n : int) (s : 'a list) :
1159+
0 <= n < size s => perm_eq (nth x0 s n :: take n s ++ drop (n + 1) s) s.
1160+
proof.
1161+
move=> rg; rewrite -cat1s perm_catCA -catA /= perm_eq_refl_eq.
1162+
by rewrite cat_take_insert_drop // perm_eq_refl.
1163+
qed.
1164+
11241165
(* -------------------------------------------------------------------- *)
11251166
(* Element removal *)
11261167
(* -------------------------------------------------------------------- *)
@@ -1203,20 +1244,20 @@ qed.
12031244

12041245
lemma perm_eqP_pred1 ['a] (s1 s2 : 'a list) : perm_eq s1 s2 <=> forall (x : 'a), count (pred1 x) s1 = count (pred1 x) s2.
12051246
proof.
1206-
rewrite perm_eqP; split => [Heq x|Heq p]; first by apply/Heq.
1207-
elim s1 s2 Heq => [s2 /= Heq|hs1 ts1 IHs1 s2 /= Heq].
1208-
+ elim: s2 Heq => //= hs2 ts2 IHs2 Heq.
1209-
move: (Heq hs2); rewrite /b2i /pred1 /= eqz_leq => -[_].
1210-
by rewrite addrC -ltzE ltzNge count_ge0.
1211-
move: IHs1 => /(_ (rem hs1 s2)) => ->.
1212-
+ move => x; move: (Heq hs1) (Heq x) => {Heq}.
1213-
rewrite {1}/b2i {1}/pred1 /= => Heqhs1.
1214-
rewrite (count_rem (pred1 x) s2 hs1); last by apply addrI.
1215-
by rewrite mem_count -Heqhs1 addrC ltzS count_ge0.
1216-
move: (Heq hs1) => {Heq}.
1247+
rewrite perm_eqP; split => [Heq x|Heq p]; first by apply/Heq.
1248+
elim s1 s2 Heq => [s2 /= Heq|hs1 ts1 IHs1 s2 /= Heq].
1249+
+ elim: s2 Heq => //= hs2 ts2 IHs2 Heq.
1250+
move: (Heq hs2); rewrite /b2i /pred1 /= eqz_leq => -[_].
1251+
by rewrite addrC -ltzE ltzNge count_ge0.
1252+
move: IHs1 => /(_ (rem hs1 s2)) => ->.
1253+
+ move => x; move: (Heq hs1) (Heq x) => {Heq}.
12171254
rewrite {1}/b2i {1}/pred1 /= => Heqhs1.
1218-
rewrite (count_rem p s2 hs1) //.
1255+
rewrite (count_rem (pred1 x) s2 hs1); last by apply addrI.
12191256
by rewrite mem_count -Heqhs1 addrC ltzS count_ge0.
1257+
move: (Heq hs1) => {Heq}.
1258+
rewrite {1}/b2i {1}/pred1 /= => Heqhs1.
1259+
rewrite (count_rem p s2 hs1) //.
1260+
by rewrite mem_count -Heqhs1 addrC ltzS count_ge0.
12201261
qed.
12211262
12221263
(* -------------------------------------------------------------------- *)
@@ -1228,6 +1269,64 @@ op insert (x : 'a) (s : 'a list) (n : int) =
12281269
op trim (xs : 'a list) (n : int) =
12291270
take n xs ++ (drop (n+1) xs).
12301271

1272+
(* -------------------------------------------------------------------- *)
1273+
lemma size_insert ['a] (x : 'a) (s : 'a list) (n : int) :
1274+
0 <= n <= size s => size (insert x s n) = size s + 1.
1275+
proof.
1276+
move=> [ge0_n ltn] @/insert; rewrite size_cat /=.
1277+
by rewrite size_take // size_drop //#.
1278+
qed.
1279+
1280+
lemma nth_insert ['a] (x0 x : 'a) (s : 'a list) (n : int) :
1281+
0 <= n <= size s => nth x0 (insert x s n) n = x.
1282+
proof. by move=> [ge0_n ltn] @/insert; rewrite nth_cat size_take //#. qed.
1283+
1284+
(* -------------------------------------------------------------------- *)
1285+
lemma mem_insert ['a] (x : 'a) (s : 'a list) (n : int) (y : 'a) :
1286+
y \in insert x s n => y = x \/ y \in s.
1287+
proof.
1288+
rewrite /insert mem_cat /=; case.
1289+
- by move/mem_take=> ->.
1290+
- by case=> [->//|/mem_drop ->].
1291+
qed.
1292+
1293+
lemma insert_cat ['a] (x : 'a) (s1 s2 : 'a list) (n : int) :
1294+
insert x (s1 ++ s2) n =
1295+
if n < size s1 then insert x s1 n ++ s2 else s1 ++ insert x s2 (n - size s1).
1296+
proof.
1297+
rewrite /insert take_cat drop_cat; case: (n < size s1) => /= _.
1298+
- by rewrite -cat_cons catA. - by rewrite catA.
1299+
qed.
1300+
1301+
lemma insert0 ['a] (x : 'a) (s : 'a list) : insert x s 0 = x :: s.
1302+
proof. by rewrite /insert take0 drop0 cat0s. qed.
1303+
1304+
hint simplify insert0.
1305+
1306+
lemma insert_nth_take_drop ['a] (x0 : 'a) (s : 'a list) (n : int) :
1307+
0 <= n < size s => insert (nth x0 s n) (take n s ++ drop (n + 1) s) n = s.
1308+
proof.
1309+
case=> ge0_n ltn; have sz_take: size (take n s) = n by rewrite size_take // ltn.
1310+
by rewrite insert_cat sz_take /= cat_take_insert_drop.
1311+
qed.
1312+
1313+
lemma take_insert_le ['a] (x : 'a) (s : 'a list) (i j : int) :
1314+
0 <= i <= j <= size s => take i (insert x s j) = take i s.
1315+
proof.
1316+
move=> [# ge0_i le_ij le_js] @/insert; rewrite take_cat_le.
1317+
rewrite iftrue; first by rewrite size_take //#.
1318+
by rewrite take_take le_ij.
1319+
qed.
1320+
1321+
lemma drop_insert_gt ['a] (x : 'a) (s : 'a list) (i j : int) :
1322+
0 <= j < i <= size s + 1 => drop i (insert x s j) = drop (i - 1) s.
1323+
proof.
1324+
move=> [# ge0_j lt_ji le_i_Ss] @/insert; rewrite drop_cat.
1325+
rewrite iffalse; first by rewrite size_take //#.
1326+
rewrite size_take_condle // iftrue 1:/# drop_cons.
1327+
by rewrite iftrue 1:/# drop_drop ~-1://#; congr => //#.
1328+
qed.
1329+
12311330
(* -------------------------------------------------------------------- *)
12321331
lemma trim_neg (xs : 'a list) (n : int): n < 0 => trim xs n = xs.
12331332
proof. by move=> lt0_n; rewrite /trim take_le0 2:drop_le0 /#. qed.

0 commit comments

Comments
 (0)