-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBPlusTree_ImpSet.thy
1691 lines (1592 loc) · 69.8 KB
/
BPlusTree_ImpSet.thy
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
theory BPlusTree_ImpSet
imports
BPlusTree_Set
BPlusTree_ImpSplit
"HOL-Real_Asymp.Inst_Existentials"
begin
section "Imperative Set operations"
subsection "Auxiliary operations"
text "This locale extends the abstract split locale,
assuming that we are provided with an imperative program
that refines the abstract split function."
(* TODO separate into split_tree and split + split_list *)
locale split\<^sub>i_set = abs_split_set: split_set split + split\<^sub>i_tree split split\<^sub>i
for split::
"('a bplustree \<times> 'a::{heap,default,linorder,order_top}) list \<Rightarrow> 'a
\<Rightarrow> ('a bplustree \<times> 'a) list \<times> ('a bplustree \<times> 'a) list"
and split\<^sub>i :: "('a btnode ref option \<times> 'a::{heap,default,linorder,order_top}) pfarray \<Rightarrow> 'a \<Rightarrow> nat Heap" +
fixes isin_list\<^sub>i:: "'a \<Rightarrow> ('a::{heap,default,linorder,order_top}) pfarray \<Rightarrow> bool Heap"
and ins_list\<^sub>i:: "'a \<Rightarrow> ('a::{heap,default,linorder,order_top}) pfarray \<Rightarrow> 'a pfarray Heap"
and del_list\<^sub>i:: "'a \<Rightarrow> ('a::{heap,default,linorder,order_top}) pfarray \<Rightarrow> 'a pfarray Heap"
assumes isin_list_rule [sep_heap_rules]:"sorted_less ks \<Longrightarrow>
<is_pfa c ks (a',n')>
isin_list\<^sub>i x (a',n')
<\<lambda>b.
is_pfa c ks (a',n')
* \<up>(isin_list x ks = b)>\<^sub>t"
and ins_list_rule [sep_heap_rules]:"sorted_less ks' \<Longrightarrow>
<is_pfa c ks' (a',n')>
ins_list\<^sub>i x (a',n')
<\<lambda>(a'',n''). is_pfa (max c (length (insert_list x ks'))) (insert_list x ks') (a'',n'') >\<^sub>t"
and del_list_rule [sep_heap_rules]:"sorted_less ks'' \<Longrightarrow>
<is_pfa c ks'' (a',n')>
del_list\<^sub>i x (a',n')
<\<lambda>(a'',n''). is_pfa c (delete_list x ks'') (a'',n'') >\<^sub>t"
begin
subsection "Initialization"
definition empty\<^sub>i ::"nat \<Rightarrow> 'a btnode ref Heap"
where "empty\<^sub>i k = do {
empty_list \<leftarrow> pfa_empty (2*k);
empty_leaf \<leftarrow> ref (Btleaf empty_list None);
return empty_leaf
}"
lemma empty\<^sub>i_rule:
shows "<emp>
empty\<^sub>i k
<\<lambda>r. bplustree_assn k (abs_split_set.empty_bplustree) r (Some r) None>"
apply(subst empty\<^sub>i_def)
apply(sep_auto simp add: abs_split_set.empty_bplustree_def)
done
subsection "Membership"
(* TODO introduce imperative equivalents to searching/inserting/deleting in a list *)
partial_function (heap) isin\<^sub>i :: "'a btnode ref \<Rightarrow> 'a \<Rightarrow> bool Heap"
where
"isin\<^sub>i p x = do {
node \<leftarrow> !p;
(case node of
Btleaf xs _ \<Rightarrow> isin_list\<^sub>i x xs |
Btnode ts t \<Rightarrow> do {
i \<leftarrow> split\<^sub>i ts x;
tsl \<leftarrow> pfa_length ts;
if i < tsl then do {
s \<leftarrow> pfa_get ts i;
let (sub,sep) = s in
isin\<^sub>i (the sub) x
} else
isin\<^sub>i t x
}
)}"
lemma nth_zip_zip:
assumes "length ys = length xs"
and "length zs = length xs"
and "zs1 @ ((suba', x), sepa') # zs2 =
zip (zip ys xs) zs"
shows "suba' = ys ! length zs1 \<and>
sepa' = zs ! length zs1 \<and>
x = xs ! length zs1"
proof -
obtain suba'' x' sepa'' where "zip (zip ys xs) zs ! length zs1 = ((suba'', x'), sepa'')"
by (metis surj_pair)
moreover have "((suba'', x'), sepa'') = ((suba', x), sepa')"
by (metis calculation assms(3) nth_append_length)
moreover have "length zs1 < length xs"
proof -
have "length (zip (zip ys xs) zs) = length xs"
by (simp add: assms(1,2))
then have "length zs1 + 1 + length zs2 = length xs"
by (metis assms(1,3) group_cancel.add1 length_Cons length_append plus_1_eq_Suc)
then show ?thesis
by (simp add: assms(1))
qed
ultimately show ?thesis
using assms(1,2) by auto
qed
lemma "k > 0 \<Longrightarrow> root_order k t \<Longrightarrow> sorted_less (inorder t) \<Longrightarrow> sorted_less (leaves t) \<Longrightarrow>
<bplustree_assn k t ti r z>
isin\<^sub>i ti x
<\<lambda>y. bplustree_assn k t ti r z * \<up>(abs_split_set.isin t x = y)>\<^sub>t"
proof(induction t x arbitrary: ti r z rule: abs_split_set.isin.induct)
case (1 x r z)
then show ?case
apply(subst isin\<^sub>i.simps)
apply sep_auto
done
next
case (2 ts t x ti r z)
obtain ls rs where list_split[simp]: "split ts x = (ls,rs)"
by (cases "split ts x")
moreover have ts_non_empty: "length ts > 0"
using "2.prems"(2) root_order.simps(2) by blast
moreover have "sorted_less (separators ts)"
using "2.prems"(3) sorted_inorder_separators by blast
ultimately show ?case
proof (cases rs)
(* NOTE: induction condition trivial here *)
case [simp]: Nil
show ?thesis
apply(subst isin\<^sub>i.simps)
using ts_non_empty apply(sep_auto)
subgoal using \<open>sorted_less (separators ts)\<close> by blast
apply simp
apply sep_auto
apply(rule hoare_triple_preI)
apply (sep_auto)
subgoal for a b ti tsi' rs x sub sep
apply(auto simp add: split_relation_alt is_pfa_def dest!: mod_starD list_assn_len)[]
done
thm "2.IH"(1)[of ls "[]"]
using 2(3) apply(sep_auto heap: "2.IH"(1)[of ls "[]"] simp add: sorted_wrt_append)
subgoal
using "2.prems"(2) order_impl_root_order
by (auto simp add: split_relation_alt is_pfa_def dest!: mod_starD list_assn_len)[]
subgoal
using "2.prems"(3) sorted_inorder_induct_last
by (auto simp add: split_relation_alt is_pfa_def dest!: mod_starD list_assn_len)[]
subgoal using "2"(6) sorted_leaves_induct_last
by (auto simp add: split_relation_alt is_pfa_def dest!: mod_starD list_assn_len)[]
using 2(3) apply(sep_auto heap: "2.IH"(1)[of ls "[]"] simp add: sorted_wrt_append)
done
next
case [simp]: (Cons h rrs)
obtain sub sep where h_split[simp]: "h = (sub,sep)"
by (cases h)
then show ?thesis
apply(simp split: list.splits prod.splits)
apply(subst isin\<^sub>i.simps)
using "2.prems" sorted_inorder_separators
apply(sep_auto)
(* simplify towards induction step *)
apply(auto simp add: split_relation_alt list_assn_append_Cons_left dest!: mod_starD list_assn_len)[]
(* NOTE show that z = (suba, sepa) -- adjusted since we now contain also current pointers and forward pointers *)
apply(rule norm_pre_ex_rule)+
apply(rule hoare_triple_preI)
subgoal for tsi n ti tsi' pointers suba sepa zs1 z zs2
apply(cases z)
subgoal for subacomb sepa'
apply(cases subacomb)
subgoal for suba' subp subfwd
apply(subgoal_tac "z = ((suba, subp, subfwd), sepa)", simp)
thm "2.IH"(2)[of ls rs h rrs sub sep "(the suba')" subp subfwd]
using 2(3,4,5,6) apply(sep_auto
heap:"2.IH"(2)[of ls rs h rrs sub sep "the suba'" subp subfwd]
simp add: sorted_wrt_append)
using list_split Cons h_split apply simp_all
subgoal
by (meson "2.prems"(1) order_impl_root_order)
subgoal
apply(rule impI)
apply(inst_ex_assn "(tsi,n)" "ti" "tsi'" "(zs1 @ ((suba', subp, subfwd), sepa') # zs2)" "pointers" "zs1" "z" "zs2")
(* proof that previous assumptions hold later *)
apply sep_auto
done
subgoal
(* prove subgoal_tac assumption *)
using nth_zip_zip[of "subtrees tsi'" "zip (r # butlast pointers) pointers" "separators tsi'" zs1 suba' "(subp, subfwd)" sepa' zs2]
apply(auto simp add: split_relation_alt list_assn_append_Cons_left dest!: mod_starD list_assn_len)[]
done
done
done
done
(* eliminate last vacuous case *)
apply(rule hoare_triple_preI)
apply(auto simp add: split_relation_def dest!: mod_starD list_assn_len)[]
done
qed
qed
subsection "Insertion"
datatype 'c btupi =
T\<^sub>i "'c btnode ref" |
Up\<^sub>i "'c btnode ref" "'c" "'c btnode ref"
fun btupi_assn where
"btupi_assn k (abs_split_set.T\<^sub>i l) (T\<^sub>i li) r z =
bplustree_assn k l li r z" |
(*TODO ai is not necessary not in the heap area of li *)
"btupi_assn k (abs_split_set.Up\<^sub>i l a r) (Up\<^sub>i li ai ri) r' z' =
(\<exists>\<^sub>A newr. bplustree_assn k l li r' newr * bplustree_assn k r ri newr z' * id_assn a ai)" |
"btupi_assn _ _ _ _ _ = false"
(* TODO take in a pointer ot a btnode instead, only create one new node *)
definition node\<^sub>i :: "nat \<Rightarrow> 'a btnode ref \<Rightarrow> 'a btupi Heap" where
"node\<^sub>i k p \<equiv> do {
pt \<leftarrow> !p;
let a = kvs pt; ti = lst pt in do {
n \<leftarrow> pfa_length a;
if n \<le> 2*k then do {
a' \<leftarrow> pfa_shrink_cap (2*k) a;
p := Btnode a' ti;
return (T\<^sub>i p)
}
else do {
b \<leftarrow> (pfa_empty (2*k) :: ('a btnode ref option \<times> 'a) pfarray Heap);
i \<leftarrow> split_half a;
m \<leftarrow> pfa_get a (i-1);
b' \<leftarrow> pfa_drop a i b;
a' \<leftarrow> pfa_shrink (i-1) a;
a'' \<leftarrow> pfa_shrink_cap (2*k) a';
let (sub,sep) = m in do {
p := Btnode a'' (the sub);
r \<leftarrow> ref (Btnode b' ti);
return (Up\<^sub>i p sep r)
}
}
}
}"
definition Lnode\<^sub>i :: "nat \<Rightarrow> 'a btnode ref \<Rightarrow> 'a btupi Heap" where
"Lnode\<^sub>i k p \<equiv> do {
pt \<leftarrow> !p;
let a = vals pt; nxt = fwd pt in do {
n \<leftarrow> pfa_length a;
if n \<le> 2*k then do {
a' \<leftarrow> pfa_shrink_cap (2*k) a;
p := Btleaf a' nxt;
return (T\<^sub>i p)
}
else do {
b \<leftarrow> (pfa_empty (2*k) :: 'a pfarray Heap);
i \<leftarrow> split_half a;
m \<leftarrow> pfa_get a (i-1);
b' \<leftarrow> pfa_drop a i b;
a' \<leftarrow> pfa_shrink i a;
a'' \<leftarrow> pfa_shrink_cap (2*k) a';
r \<leftarrow> ref (Btleaf b' nxt);
p := Btleaf a'' (Some r);
return (Up\<^sub>i p m r)
}
}
}"
(* TODO Lnode\<^sub>i allocates a new node when invoked, do not invoke if array didn't grow *)
partial_function (heap) ins\<^sub>i :: "nat \<Rightarrow> 'a \<Rightarrow> 'a btnode ref \<Rightarrow> 'a btupi Heap"
where
"ins\<^sub>i k x p = do {
node \<leftarrow> !p;
(case node of
Btleaf ksi nxt \<Rightarrow> do {
ksi' \<leftarrow> ins_list\<^sub>i x ksi;
p := Btleaf ksi' nxt;
Lnode\<^sub>i k p
} |
Btnode tsi ti \<Rightarrow> do {
i \<leftarrow> split\<^sub>i tsi x;
tsl \<leftarrow> pfa_length tsi;
if i < tsl then do {
s \<leftarrow> pfa_get tsi i;
let (sub,sep) = s in do {
r \<leftarrow> ins\<^sub>i k x (the sub);
case r of (T\<^sub>i lp) \<Rightarrow> do {
pfa_set tsi i (Some lp,sep);
return (T\<^sub>i p)
} |
(Up\<^sub>i lp x' rp) \<Rightarrow> do {
pfa_set tsi i (Some rp,sep);
tsi' \<leftarrow> pfa_insert_grow tsi i (Some lp,x');
p := Btnode tsi' ti;
node\<^sub>i k p
}
}
}
else do {
r \<leftarrow> ins\<^sub>i k x ti;
case r of (T\<^sub>i lp) \<Rightarrow> do {
p := (Btnode tsi lp);
return (T\<^sub>i p)
} | (Up\<^sub>i lp x' rp) \<Rightarrow> do {
tsi' \<leftarrow> pfa_append_grow' tsi (Some lp,x');
p := Btnode tsi' rp;
node\<^sub>i k p
}
}
}
)}"
(*fun tree\<^sub>i::"'a up\<^sub>i \<Rightarrow> 'a bplustree" where
"tree\<^sub>i (T\<^sub>i sub) = sub" |
"tree\<^sub>i (Up\<^sub>i l a r) = (Node [(l,a)] r)"
fun insert::"nat \<Rightarrow> 'a \<Rightarrow> 'a bplustree \<Rightarrow> 'a bplustree" where
"insert k x t = tree\<^sub>i (ins k x t)"
*)
definition insert\<^sub>i :: "nat \<Rightarrow> 'a \<Rightarrow> 'a btnode ref \<Rightarrow> 'a btnode ref Heap" where
"insert\<^sub>i \<equiv> \<lambda>k x ti. do {
ti' \<leftarrow> ins\<^sub>i k x ti;
case ti' of
T\<^sub>i sub \<Rightarrow> return sub |
Up\<^sub>i l a r \<Rightarrow> do {
kvs \<leftarrow> pfa_init (2*k) (Some l,a) 1;
t' \<leftarrow> ref (Btnode kvs r);
return t'
}
}"
lemma take_butlast_prepend: "take n (butlast (r # pointers)) =
butlast (r # take n pointers)"
apply (cases "length pointers > n")
by (simp_all add: butlast_take take_Cons' take_butlast)
lemma take_butlast_append: "take n (butlast (xs @ x # ys)) =
take n (xs @ (butlast (x#ys)))"
by (auto simp add: butlast_append)
lemma map_eq_nth_eq_diff:
assumes A: "map f l = map g l'"
and B: "i < length l"
shows "f (l!i) = g (l'!i)"
proof -
from A have "length l = length l'"
by (metis length_map)
thus ?thesis using A B
apply (induct l l' arbitrary: i rule: list_induct2)
apply (simp)
subgoal for x xs y ys i
apply(cases i)
apply(simp add: nth_def)
apply simp
done
done
qed
lemma "BPlusTree_Split.split_half ts = (ls,rs) \<Longrightarrow> length ls = Suc (length ts) div 2"
by (metis Suc_eq_plus1 split_half_conc)
lemma take_half_less: "take (Suc (length ts) div 2) ts = ls @ [(sub, sep)] \<Longrightarrow> length ls < length ts"
proof -
assume " take (Suc (length ts) div 2) ts = ls @ [(sub, sep)]"
then have "ts \<noteq> []"
by force
then have "Suc (length ts) div 2 \<le> length ts"
by linarith
then have "length (take (Suc (length ts) div 2) ts) \<le> length ts"
by simp
moreover have "length ls < length (take (Suc (length ts) div 2) ts)"
by (simp add: \<open>take (Suc (length ts) div 2) ts = ls @ [(sub, sep)]\<close>)
ultimately show "length ls < length ts"
by linarith
qed
declare abs_split_set.node\<^sub>i.simps [simp add]
declare last.simps[simp del] butlast.simps[simp del]
lemma node\<^sub>i_rule: assumes c_cap: "2*k \<le> c" "c \<le> 4*k+1"
and "length tsi' = length pointers"
and "tsi'' = zip (zip (map fst tsi') (zip (butlast (r#pointers)) (butlast (pointers@[z])))) (map snd tsi')"
shows "<p \<mapsto>\<^sub>r Btnode (a,n) ti * is_pfa c tsi' (a,n) * blist_assn k ts tsi'' * bplustree_assn k t ti (last (r#pointers)) z>
node\<^sub>i k p
<\<lambda>u. btupi_assn k (abs_split_set.node\<^sub>i k ts t) u r z>\<^sub>t"
proof (cases "length ts \<le> 2*k")
case [simp]: True
then show ?thesis
apply(subst node\<^sub>i_def)
apply(rule hoare_triple_preI)
apply(sep_auto)
subgoal by (sep_auto simp add: is_pfa_def)[]
subgoal using c_cap by (sep_auto simp add: is_pfa_def)[]
subgoal using assms(3,4) by (sep_auto)
subgoal
apply(subgoal_tac "length ts = length tsi'")
subgoal using True by (sep_auto)
subgoal using True assms by (sep_auto dest!: mod_starD list_assn_len)
done
done
next
case [simp]: False
then obtain ls sub sep rs where
split_half_eq: "BPlusTree_Split.split_half ts = (ls@[(sub,sep)],rs)"
using abs_split_set.node\<^sub>i_cases by blast
then show ?thesis
apply(subst node\<^sub>i_def)
apply(rule hoare_triple_preI)
apply sep_auto
subgoal by (sep_auto simp add: split_relation_alt split_relation_length is_pfa_def dest!: mod_starD list_assn_len)
subgoal using assms by (sep_auto dest!: mod_starD list_assn_len)
subgoal
apply(subgoal_tac "length ts = length tsi'")
subgoal using False by (sep_auto dest!: mod_starD list_assn_len)
subgoal using assms(3,4) by (sep_auto dest!: mod_starD list_assn_len)
done
apply sep_auto
subgoal using c_cap by (sep_auto simp add: is_pfa_def)[]
subgoal using c_cap by (sep_auto simp add: is_pfa_def)[]
using c_cap apply sep_auto
subgoal using c_cap by (sep_auto simp add: is_pfa_def)[]
subgoal using c_cap by (sep_auto simp add: is_pfa_def)[]
using c_cap apply simp
apply(rule hoare_triple_preI)
apply(vcg)
apply(simp add: split_relation_alt)
apply(rule impI)+
subgoal for _ _ rsia subi' sepi' rsin lsi _
supply R = append_take_drop_id[of "(length ls)" ts,symmetric]
thm R
apply(subst R)
supply R = Cons_nth_drop_Suc[of "length ls" ts, symmetric]
thm R
apply(subst R)
subgoal
by (meson take_half_less)
supply R=list_assn_append_Cons_left[where xs="take (length ls) ts" and ys="drop (Suc (length ls)) ts" and x="ts ! (length ls)"]
thm R
apply(subst R)
apply(auto)[]
apply(rule ent_ex_preI)+
apply(subst ent_pure_pre_iff; rule impI)
apply (simp add: prod_assn_def split!: prod.splits)
subgoal for tsi''l subi'' subir subinext sepi'' tsi''r sub' sep'
(* instantiate right hand side *)
(* newr is the first leaf of the tree directly behind sub
and (r#pointers) is the list of all first leafs of the tree in this node
\<rightarrow> the pointer at position of sub in pointers
or the pointer at position of sub+1 in (r#pointers)
*)
(* Suc (length tsi') div 2 - Suc 0) = length ls *)
apply(inst_ex_assn "subinext" "(rsia,rsin)" ti
"drop (length ls+1) tsi'"
"drop (length ls+1) tsi''"
"drop (length ls+1) pointers"
lsi
"the subi'"
"take (length ls) tsi'"
"take (length ls) tsi''"
"take (length ls) pointers"
)
apply (sep_auto)
subgoal using assms(3) by linarith
subgoal
using assms(3,4) by (auto dest!: mod_starD
simp add: take_map[symmetric] take_zip[symmetric] take_butlast_prepend[symmetric]
)
subgoal using assms(3,4) by (auto dest!: mod_starD
simp add: list_assn_prod_map id_assn_list_alt)
subgoal
apply(subgoal_tac "length ls < length pointers")
apply(subgoal_tac "subinext = pointers ! (length ls)")
subgoal
using assms(3,4) apply (auto
simp add: drop_map[symmetric] drop_zip[symmetric] drop_butlast[symmetric] Cons_nth_drop_Suc
)[]
supply R = drop_Suc_Cons[where n="length ls" and xs="butlast pointers" and x=r, symmetric]
thm R
apply(simp only: R drop_zip[symmetric])
apply (simp add: last.simps butlast.simps)
done
subgoal apply(auto dest!: mod_starD list_assn_len)
proof (goal_cases)
case 1
have "length ls < length tsi''"
using assms(3,4) "1" by auto
moreover have "subinext = snd (snd (fst (tsi'' ! length ls)))"
using 1 calculation by force
ultimately have "subinext = map snd (map snd (map fst tsi'')) ! length ls"
by auto
then show ?case
using assms(3,4) by auto
qed
subgoal apply(auto dest!: mod_starD list_assn_len)
proof (goal_cases)
case 1
then have "length ls < length ts"
by (simp)
moreover have "length ts = length tsi''"
by (simp add: 1)
moreover have "\<dots> = length pointers"
using assms(3,4) by auto
ultimately show ?case by simp
qed
done
apply(rule entails_preI)
(* introduce some simplifying equalities *)
apply(subgoal_tac "Suc (length tsi') div 2 = length ls + 1")
prefer 2 subgoal
apply(auto dest!: mod_starD list_assn_len)
proof (goal_cases)
case 1
have "length tsi' = length tsi''"
using assms(3,4) by auto
also have "\<dots> = length ts"
by (simp add: 1)
finally show ?case
using 1
by (metis Suc_eq_plus1 abs_split_set.length_take_left div2_Suc_Suc length_append length_append_singleton numeral_2_eq_2)
qed
apply(subgoal_tac "length ts = length tsi''")
prefer 2 subgoal using assms(3,4) by (auto dest!: mod_starD list_assn_len)
apply(subgoal_tac "(sub', sep') = (sub, sep)")
prefer 2 subgoal
by (metis One_nat_def Suc_eq_plus1 Suc_length_conv abs_split_set.length_take_left length_0_conv length_append less_add_Suc1 nat_arith.suc1 nth_append_length nth_take)
apply(subgoal_tac "length ls = length tsi''l")
prefer 2 subgoal by (auto dest!: mod_starD list_assn_len)
apply(subgoal_tac "(subi'', sepi'') = (subi', sepi')")
prefer 2 subgoal
using assms(3,4) apply (auto dest!: mod_starD list_assn_len)
proof (goal_cases)
case 1
then have "tsi'' ! length tsi''l = ((subi'', subir, subinext), sepi'')"
by auto
moreover have "length tsi''l < length tsi''"
by (simp add: 1)
moreover have "length tsi''l < length tsi'"
using "1" assms(3) by linarith
ultimately have
"fst (fst (tsi'' ! length tsi''l)) = fst (tsi' ! length tsi''l)"
"snd (tsi'' ! length tsi''l) = snd (tsi' ! length tsi''l)"
using assms(4) by auto
then show ?case
by (simp add: "1" \<open>tsi'' ! length tsi''l = ((subi'', subir, subinext), sepi'')\<close>)
case 2
then show ?case
by (metis \<open>snd (tsi'' ! length tsi''l) = snd (tsi' ! length tsi''l)\<close> \<open>tsi'' ! length tsi''l = ((subi'', subir, subinext), sepi'')\<close> snd_conv)
qed
apply(subgoal_tac "(last (r # take (length ls) pointers)) = subir")
prefer 2 subgoal
using assms(3) apply (auto dest!: mod_starD list_assn_len)
proof (goal_cases)
case 1
have "length tsi''l < length tsi''"
by (simp add: 1)
then have "fst (snd (fst (tsi'' ! length tsi''l))) = subir"
using 1 assms(4) by auto
moreover have "map fst (map snd (map fst tsi'')) = butlast (r#pointers)"
using assms(3,4) by auto
moreover have "(last (r#take (length ls) pointers)) = butlast (r#pointers) ! (length tsi''l)"
by (smt (z3) "1" One_nat_def Suc_eq_plus1 Suc_to_right abs_split_set.length_take_left append_butlast_last_id div_le_dividend le_add2 length_butlast length_ge_1_conv length_take lessI list.size(4) min_eq_arg(2) nth_append_length nth_take nz_le_conv_less take_Suc_Cons take_butlast_conv)
ultimately show ?case
using 1 apply auto
by (metis (no_types, opaque_lifting) 1 length_map map_map nth_append_length)
qed
apply(subgoal_tac "(last (subinext # drop (Suc (length tsi''l)) pointers)) = last (r#pointers)")
prefer 2 subgoal
using assms(3) apply (auto dest!: mod_starD list_assn_len)
proof (goal_cases)
case 1
have "length tsi''l < length tsi''"
using 1 by auto
moreover have "subinext = snd (snd (fst (tsi'' ! length tsi''l)))"
using "1" calculation by force
ultimately have "subinext = map snd (map snd (map fst tsi'')) ! length tsi''l"
by auto
then have "subinext = pointers ! length tsi''l"
using assms(3,4) by auto
then have "(subinext # drop (Suc (length tsi''l)) pointers) = drop (length tsi''l) pointers"
by (metis 1 Cons_nth_drop_Suc Suc_eq_plus1 Suc_to_right abs_split_set.length_take_left div_le_dividend le_add1 less_Suc_eq nz_le_conv_less take_all_iff zero_less_Suc)
moreover have "last (drop (length tsi''l) pointers) = last pointers"
using \<open>length tsi''l < length tsi''\<close> 1 by force
ultimately show ?case
by (auto simp add: last.simps butlast.simps)
qed
apply(subgoal_tac "take (length tsi''l) ts = ls")
prefer 2 subgoal
by (metis append.assoc append_eq_conv_conj append_take_drop_id)
apply(subgoal_tac "drop (Suc (length tsi''l)) ts = rs")
prefer 2 subgoal by (metis One_nat_def Suc_eq_plus1 Suc_length_conv append_eq_conv_conj append_take_drop_id length_0_conv length_append)
subgoal by (sep_auto)
done
done
done
qed
declare last.simps[simp add] butlast.simps[simp add]
declare abs_split_set.node\<^sub>i.simps [simp del]
declare abs_split_set.Lnode\<^sub>i.simps [simp add]
lemma Lnode\<^sub>i_rule:
assumes "k > 0 " "r = Some a" "2*k \<le> c" "c \<le> 4*k"
shows "<a \<mapsto>\<^sub>r (Btleaf xsi z) * is_pfa c xs xsi>
Lnode\<^sub>i k a
<\<lambda>a. btupi_assn k (abs_split_set.Lnode\<^sub>i k xs) a r z>\<^sub>t"
proof (cases "length xs \<le> 2*k")
case [simp]: True
then show ?thesis
apply(subst Lnode\<^sub>i_def)
apply(rule hoare_triple_preI; simp)
using assms apply(sep_auto eintros del: exI heap add: pfa_shrink_cap_rule)
subgoal for _ _ aaa ba
apply(inst_existentials aaa ba z)
apply simp_all
done
subgoal
apply(rule hoare_triple_preI)
using True apply (auto dest!: mod_starD list_assn_len)+
done
done
next
case [simp]: False
then obtain ls sep rs where
split_half_eq: "BPlusTree_Split.split_half xs = (ls@[sep],rs)"
using abs_split_set.Lnode\<^sub>i_cases by blast
then show ?thesis
apply(subst Lnode\<^sub>i_def)
apply auto
using assms apply (vcg heap add: pfa_shrink_cap_rule; simp)
apply(rule hoare_triple_preI)
apply (sep_auto heap add: pfa_drop_rule simp add: split_relation_alt
dest!: mod_starD list_assn_len)
subgoal by (sep_auto simp add: is_pfa_def split!: prod.splits)
subgoal by (sep_auto simp add: is_pfa_def split!: prod.splits)
apply(sep_auto)
subgoal by (sep_auto simp add: is_pfa_def split!: prod.splits)
subgoal by (sep_auto simp add: is_pfa_def split!: prod.splits)
apply(sep_auto eintros del: exI)
subgoal for _ _ _ _ rsa rn lsa ln newr
(* instantiate right hand side *)
apply(inst_existentials "Some newr"
rsa rn z
lsa ln "Some newr"
)
(* introduce equality between equality of split tsi/ts and original lists *)
apply(simp_all add: pure_def)
apply(sep_auto dest!: mod_starD)
apply(subgoal_tac "Suc (length xs) div 2 = Suc (length ls)")
apply(subgoal_tac "xs = take (Suc (length ls)) xs @ drop (Suc (length ls)) xs")
subgoal
by (metis nth_append_length)
subgoal by auto
subgoal by auto
subgoal by sep_auto
done
done
qed
declare abs_split_set.Lnode\<^sub>i.simps [simp del]
lemma Lnode\<^sub>i_rule_tree:
assumes "k > 0"
shows "<bplustree_assn k (Leaf xs) a r z>
Lnode\<^sub>i k a
<\<lambda>a. btupi_assn k (abs_split_set.Lnode\<^sub>i k xs) a r z>\<^sub>t"
using assms by (sep_auto heap add: Lnode\<^sub>i_rule)
lemma node\<^sub>i_no_split: "length ts \<le> 2*k \<Longrightarrow> abs_split_set.node\<^sub>i k ts t = abs_split_set.T\<^sub>i (Node ts t)"
by (simp add: abs_split_set.node\<^sub>i.simps)
lemma Lnode\<^sub>i_no_split: "length ts \<le> 2*k \<Longrightarrow> abs_split_set.Lnode\<^sub>i k ts = abs_split_set.T\<^sub>i (Leaf ts)"
by (simp add: abs_split_set.Lnode\<^sub>i.simps)
lemma id_assn_emp[simp]: "id_assn a a = emp"
by (simp add: pure_def)
lemma butlast2[simp]: "butlast (ts@[a,b]) = ts@[a]"
by (induction ts) auto
lemma butlast3[simp]: "butlast (ts@[a,b,c]) = ts@[a,b]"
by (induction ts) auto
lemma zip_append_last: "length as = length bs \<Longrightarrow> zip (as@[a]) (bs@[b]) = zip as bs @ [(a,b)]"
by simp
lemma pointers_append: "zip (z#as) (as@[a]) = zip (butlast (z#as)) as @ [(last (z#as),a)]"
by (metis (no_types, opaque_lifting) Suc_eq_plus1 append_butlast_last_id butlast_snoc length_Cons length_append_singleton length_butlast list.distinct(1) zip_append_last)
lemma node\<^sub>i_rule_app: assumes c_cap: "2*k \<le> c" "c \<le> 4*k+1"
and "length tsi' = length pointers"
and "tsi'' = zip (zip (map fst tsi') (zip (butlast (r'#pointers)) pointers)) (map snd tsi')"
shows "
< p \<mapsto>\<^sub>r Btnode (tsia,tsin) ri *
is_pfa c (tsi' @ [(Some li, a)]) (tsia, tsin) *
blist_assn k ts tsi'' *
bplustree_assn k l li (last (r'#pointers)) lz *
bplustree_assn k r ri lz rz> node\<^sub>i k p
<\<lambda>u. btupi_assn k (abs_split_set.node\<^sub>i k (ts @ [(l, a)]) r) u r' rz>\<^sub>t"
proof -
(*[of k c "(tsi' @ [(Some li, b)])" _ _ "(ls @ [(l, a)])" r ri]*)
note node\<^sub>i_rule[of k c "tsi'@[(Some li, a)]" "pointers@[lz]" "tsi''@[((Some li, last(r'#pointers), lz),a)]" r' rz p tsia tsin ri "ts@[(l,a)]" r, OF assms(1,2)]
then show ?thesis
using assms
apply (auto simp add:
list_assn_app_one pointers_append
mult.left_assoc
)
done
qed
lemma norm_pre_ex_drule: "<\<exists>\<^sub>Ax. P x> c <Q> \<Longrightarrow> (\<And>x. <P x> c <Q>)"
proof (goal_cases)
case 1
then show ?case
using Hoare_Triple.cons_pre_rule by blast
qed
(* setting up the simplifier for tsi'' in the other direction *)
lemma node\<^sub>i_rule_diff_simp: assumes c_cap: "2*k \<le> c" "c \<le> 4*k+1"
and "length tsi' = length pointers"
and "zip (zip (map fst tsi') (zip (butlast (r#pointers)) (butlast (pointers@[z])))) (map snd tsi') = tsi''"
shows "<p \<mapsto>\<^sub>r Btnode (a,n) ti * is_pfa c tsi' (a,n) * blist_assn k ts tsi'' * bplustree_assn k t ti (last (r#pointers)) z>
node\<^sub>i k p
<\<lambda>u. btupi_assn k (abs_split_set.node\<^sub>i k ts t) u r z>\<^sub>t"
using node\<^sub>i_rule assms by (auto simp del: butlast.simps last.simps)
lemma list_assn_aux_append_Cons2:
shows "length xs = length zsl \<Longrightarrow> list_assn R (xs@x#y#ys) (zsl@z1#z2#zsr) = (list_assn R xs zsl * R x z1 * R y z2 * list_assn R ys zsr)"
by (sep_auto simp add: mult.assoc)
lemma pointer_zip_access: "length tsi' = length pointers \<Longrightarrow> i < length tsi' \<Longrightarrow>
zip (zip (map fst tsi') (zip (butlast (r'#pointers)) (butlast (pointers@[z])))) (map snd tsi') ! i
= ((fst (tsi' ! i), (r'#pointers) ! i, pointers ! i), snd (tsi' ! i))"
apply(auto)
by (metis append_butlast_last_id butlast.simps(2) len_greater_imp_nonempty length_Cons length_append_singleton nth_butlast)
lemma pointer_zip'_access: "length tsi' = length pointers \<Longrightarrow> i < length tsi' \<Longrightarrow>
zip (zip (map fst tsi') (zip (butlast (r'#pointers)) (butlast (pointers@[z])))) (map snd tsi') ! i
= ((fst (tsi' ! i), (r'#pointers) ! i, pointers ! i), snd (tsi' ! i))"
apply(auto)
by (metis One_nat_def nth_take take_Cons' take_butlast_conv)
lemma access_len_last: "(x#xs@ys) ! (length xs) = last (x#xs)"
by (induction xs) auto
lemma node\<^sub>i_rule_ins2: assumes c_cap: "2*k \<le> c" "c \<le> 4*k+1"
and "pointers = lpointers@lz#rz#rpointers"
and "length tsi'' = length pointers"
and "length lpointers = length lsi'"
and "length rpointers = length rsi'"
and "length lsi'' = length ls"
and "length lsi' = length ls"
and "tsi'' = zip (zip (map fst tsi') (zip (butlast (r'#pointers)) (butlast (pointers@[z])))) (map snd tsi')"
and "tsi' = (lsi' @ (Some li, a) # (Some ri,a') # rsi')"
and "lsi'' = take (length lsi') tsi''"
and "rsi'' = drop (Suc (Suc (length lsi'))) tsi''"
and "r'' = last (r'#lpointers)"
and "z'' = last (r'#pointers)"
and "length tsi' = length pointers"
shows "
< p \<mapsto>\<^sub>r Btnode (tsia,tsin) ti *
is_pfa c (lsi' @ (Some li, a) # (Some ri,a') # rsi') (tsia, tsin) *
blist_assn k ls lsi'' *
bplustree_assn k l li r'' lz*
bplustree_assn k r ri lz rz*
blist_assn k rs rsi'' *
bplustree_assn k t ti z'' z> node\<^sub>i k p
<\<lambda>u. btupi_assn k (abs_split_set.node\<^sub>i k (ls @ (l, a) # (r,a') # rs) t) u r' z>\<^sub>t"
proof -
have "
tsi'' =
lsi'' @ ((Some li, r'', lz), a) # ((Some ri, lz, rz), a') # rsi''"
proof (goal_cases)
case 1
have "tsi'' = take (length lsi') tsi'' @ drop (length lsi') tsi''"
by auto
also have "\<dots> = take (length lsi') tsi'' @ tsi''!(length lsi') # drop (Suc (length lsi')) tsi''"
by (simp add: Cons_nth_drop_Suc assms(3) assms(4) assms(5))
also have "\<dots> = take (length lsi') tsi'' @ tsi''!(length lsi') # tsi''!(Suc (length lsi')) #drop (Suc (Suc (length lsi'))) tsi''"
by (metis (no_types, lifting) Cons_nth_drop_Suc One_nat_def Suc_eq_plus1 Suc_le_eq assms(3) assms(4) assms(5) diff_add_inverse2 diff_is_0_eq length_append list.size(4) nat.simps(3) nat_add_left_cancel_le not_less_eq_eq)
also have "\<dots> = lsi'' @ tsi''!(length lsi') # tsi''!(Suc (length lsi')) # rsi''"
using assms(11) assms(12) by force
also have "\<dots> = lsi'' @ ((Some li, r'', lz), a) # ((Some ri, lz, rz), a') # rsi''"
proof (auto, goal_cases)
case 1
have "pointers ! length lsi' = lz"
by (metis assms(3) assms(5) list.sel(3) nth_append_length)
moreover have "(r'#pointers) ! length lsi' = r''"
using assms access_len_last[of r' lpointers]
by (auto simp del: last.simps butlast.simps)
moreover have " tsi'!(length lsi') = (Some li,a)"
using assms(10) by auto
moreover have "length lsi' < length tsi'"
using \<open>take (length lsi') tsi'' @ tsi'' ! length lsi' # drop (Suc (length lsi')) tsi'' = take (length lsi') tsi'' @ tsi'' ! length lsi' # tsi'' ! Suc (length lsi') # drop (Suc (Suc (length lsi'))) tsi''\<close> assms(15) assms(4) same_append_eq by fastforce
ultimately show ?case
using pointer_zip'_access[of tsi' "pointers" "length lsi'" r'] assms(15) assms(9)
by (auto simp del: last.simps butlast.simps)
next
case 2
have "pointers ! (Suc (length lsi')) = rz"
by (metis Suc_eq_plus1 append_Nil assms(3) assms(5) list.sel(3) nth_Cons_Suc nth_append_length nth_append_length_plus)
moreover have "(r'#pointers) ! (Suc (length lsi')) = lz"
using assms(3,4,5,6,7,8) apply auto
by (metis nth_append_length)
moreover have " tsi'!(Suc (length lsi')) = (Some ri,a')"
using assms(10)
by (metis (no_types, lifting) Cons_nth_drop_Suc Suc_le_eq append_eq_conv_conj assms(15) assms(4) drop_all drop_eq_ConsD list.inject list.simps(3) not_less_eq_eq)
moreover have "Suc (length lsi') < length tsi'"
by (simp add: assms(10))
ultimately show ?case
using pointer_zip'_access[of tsi' pointers "Suc (length lsi')"] assms(15) assms(9)
by (auto simp del: last.simps butlast.simps)
qed
finally show ?thesis .
qed
moreover note node\<^sub>i_rule_diff_simp[of k c
"(lsi' @ (Some li, a) # (Some ri,a') # rsi')"
"lpointers@lz#rz#rpointers" r' z
"lsi''@((Some li, r'', lz), a)#((Some ri, lz, rz), a')#rsi''"
p tsia tsin ti "ls@(l,a)#(r,a')#rs" t
]
ultimately show ?thesis
using assms(1,2,3,4,5,6,7,8,9,10,13,14)
apply (auto simp add: mult.left_assoc list_assn_aux_append_Cons2 prod_assn_def
simp del: last.simps)
done
qed
lemma upd_drop_prepend: "i < length xs \<Longrightarrow> drop i (list_update xs i a) = a#(drop (Suc i) xs)"
by (simp add: upd_conv_take_nth_drop)
lemma zip_update: "(zip xs ys)!i = (a,b) \<Longrightarrow> list_update (zip xs ys) i (c,b) = zip (list_update xs i c) ys"
by (metis fst_conv list_update_beyond list_update_id not_le_imp_less nth_zip snd_conv update_zip)
lemma append_Cons_last: "last (xs@x#ys) = last (x#ys)"
by (induction xs) auto
declare last.simps[simp del] butlast.simps[simp del]
lemma ins\<^sub>i_rule:
"k > 0 \<Longrightarrow>
sorted_less (inorder t) \<Longrightarrow>
sorted_less (leaves t) \<Longrightarrow>
root_order k t \<Longrightarrow>
<bplustree_assn k t ti r z>
ins\<^sub>i k x ti
<\<lambda>a. btupi_assn k (abs_split_set.ins k x t) a r z>\<^sub>t"
proof (induction k x t arbitrary: ti r z rule: abs_split_set.ins.induct)
case (1 k x xs ti r z)
then show ?case
apply(subst ins\<^sub>i.simps)
apply (sep_auto heap: Lnode\<^sub>i_rule)
done
next
case (2 k x ts t ti r' z)
obtain ls rrs where list_split: "split ts x = (ls,rrs)"
by (cases "split ts x")
have [simp]: "sorted_less (separators ts)"
using "2.prems" sorted_inorder_separators by simp
have [simp]: "sorted_less (inorder t)"
using "2.prems" sorted_inorder_induct_last by simp
show ?case
proof (cases rrs)
case Nil
then have split_rel_i: "split_relation ts (ls,[]) i \<Longrightarrow> i = length ts" for i
by (simp add: split_relation_alt)
show ?thesis
proof (cases "abs_split_set.ins k x t")
case (T\<^sub>i a)
then show ?thesis
apply(subst ins\<^sub>i.simps)
using Nil
apply(simp)
apply vcg
apply(simp)
apply vcg
thm split\<^sub>i_rule
apply sep_auto
apply(rule hoare_triple_preI)
using Nil split_rel_i list_split
apply (sep_auto dest!: split_rel_i mod_starD)
subgoal
using Nil list_split
by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal
using Nil list_split
by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal for tsil tsin tti tsi'
thm "2.IH"(1)[of ls rrs tti]
using "2.prems" sorted_leaves_induct_last
using Nil list_split T\<^sub>i abs_split_set.split_conc[OF list_split] order_impl_root_order
apply(sep_auto split!: list.splits simp add: split_relation_alt
heap add: "2.IH"(1)[of ls rrs tti])
subgoal for ai
apply(cases ai)
subgoal by sep_auto
subgoal by sep_auto
done
done
done
next
case (Up\<^sub>i l a r)
then show ?thesis
apply(subst ins\<^sub>i.simps)
using Nil
apply(simp)
apply vcg
apply simp
apply vcg
apply sep_auto
apply(rule hoare_triple_preI)
using Nil list_split
apply (sep_auto dest!: split_rel_i mod_starD)
subgoal
using Nil list_split
by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal
using Nil list_split
by (simp add: list_assn_aux_ineq_len split_relation_alt)
subgoal for tsia tsin tti tsi' pointers _ _ _ _ _ _ _ _ _ _ i
thm "2.IH"(1)[of ls rrs tti "last (r'#pointers)" z]
using "2.prems" sorted_leaves_induct_last
using Nil list_split Up\<^sub>i abs_split_set.split_conc[OF list_split] order_impl_root_order
apply(sep_auto split!: list.splits
simp add: split_relation_alt
heap add: "2.IH"(1)[of ls rrs tti])
subgoal for ai
apply(cases ai)
subgoal by sep_auto
apply(rule hoare_triple_preI)
thm node\<^sub>i_rule_app
apply(sep_auto heap add: node\<^sub>i_rule_app)
apply(sep_auto simp add: pure_def)
done
done
done
qed
next
case (Cons a rs)
obtain sub sep where a_split: "a = (sub,sep)"
by (cases a)
then have [simp]: "sorted_less (inorder sub)"
by (metis "2"(4) abs_split_set.split_set(1) list_split local.Cons some_child_sub(1) sorted_inorder_subtrees)
from Cons have split_rel_i: "ts = ls@a#rs \<and> i = length ls \<Longrightarrow> i < length ts" for i
by (simp add: split_relation_alt)
then show ?thesis
proof (cases "abs_split_set.ins k x sub")
case (T\<^sub>i a')
then show ?thesis
apply(auto simp add: Cons list_split a_split)
apply(subst ins\<^sub>i.simps)
apply vcg
apply auto
apply vcg
subgoal by sep_auto
apply simp
(*this solves a subgoal*) apply simp
(* at this point, we want to introduce the split, and after that tease the
hoare triple assumptions out of the bracket, s.t. we don't split twice *)
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
apply (vcg (ss))
using list_split Cons abs_split_set.split_conc[of ts x ls rrs]
apply (simp add: list_assn_append_Cons_left)
apply(rule norm_pre_ex_rule)+
apply(rule hoare_triple_preI)
apply(simp add: split_relation_alt prod_assn_def split!: prod.splits)
(* actual induction branch *)
subgoal for tsia tsin tti tsi' pointers suba' sepa' lsi' suba subleaf subnext sepa rsi' _ _ sub' sep'
apply(subgoal_tac "length ls = length lsi'")
apply(subgoal_tac "(suba', sepa') = (suba, sepa)")
apply(subgoal_tac "(sub', sep') = (sub, sep)")
thm "2.IH"(2)[of ls rs a rrs sub sep "the suba" subleaf subnext]
apply (sep_auto heap add: "2.IH"(2))
subgoal using "2.prems" by metis
subgoal using "2.prems" sorted_leaves_induct_subtree \<open>sorted_less (inorder sub)\<close>
by (auto split!: btupi.splits)
subgoal
using "2.prems"(3) sorted_leaves_induct_subtree by blast
subgoal using "2.prems"(1,4) order_impl_root_order[of k sub] by auto
subgoal for up
apply(cases up)
subgoal for ai
apply (sep_auto eintros del: exI)
apply(inst_existentials tsia tsin tti "tsi'[length ls := (Some ai, sepa)]" "lsi'@((Some ai, subleaf, subnext),sepa)#rsi'" pointers)
apply (sep_auto simp add: prod_assn_def split!: prod.splits)
subgoal (* necessary goal due to the difference between implementation and abstract code *)