forked from NicolasT/paxos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Paxos.thy
2467 lines (2117 loc) · 118 KB
/
Paxos.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 Paxos
imports Main
begin
locale propNoL =
fixes lt :: "'pid \<Rightarrow> 'pid \<Rightarrow> bool" (infixl "\<prec>" 50)
fixes le :: "'pid \<Rightarrow> 'pid \<Rightarrow> bool" (infixl "\<preceq>" 50)
assumes le_lt_eq [simp]: "\<And>p q. p \<preceq> q = (p \<prec> q \<or> p = q)"
assumes wf: "wf {(p,q). p \<prec> q}"
assumes trans: "trans {(p,q). p \<prec> q}"
assumes total: "\<And>p q. p \<prec> q \<or> p = q \<or> q \<prec> p"
lemma (in propNoL) propNo_acyclic: "acyclic {(p,q). p \<prec> q}"
using local.wf by (intro wf_acyclic)
lemma (in propNoL) propNo_cases:
assumes lt: "p1 \<prec> p2 \<Longrightarrow> P"
and eq: "p1 = p2 \<Longrightarrow> P"
and gt: "p2 \<prec> p1 \<Longrightarrow> P"
shows P
using assms total by auto
lemma (in propNoL) propNo_leE [elim]:
assumes le1: "p1 \<preceq> p2"
and lt: "p1 \<prec> p2 \<Longrightarrow> P"
and eq: "p1 = p2 \<Longrightarrow> P"
shows P
using assms local.le_lt_eq by auto
lemma (in propNoL) propNo_irreflexive [simp]:
shows "\<not> p \<prec> p"
by (metis local.wf mem_Collect_eq old.prod.case wf_irrefl)
lemma (in propNoL) propNo_trans_lt_lt [trans]:
"p1 \<prec> p2 \<Longrightarrow> p2 \<prec> p3 \<Longrightarrow> p1 \<prec> p3"
using trans by (elim transE, auto)
lemma (in propNoL) propNo_lt_not_ge_E [elim]:
assumes lt: "p1 \<prec> p2"
and not_gt: "\<lbrakk> p1 \<noteq> p2; \<not>(p2 \<prec> p1) \<rbrakk> \<Longrightarrow> P"
shows P
by (metis lt not_gt propNo_irreflexive propNo_trans_lt_lt)
lemma (in propNoL) propNo_trans_lt_le [trans]:
"p1 \<prec> p2 \<Longrightarrow> p2 \<preceq> p3 \<Longrightarrow> p1 \<prec> p3"
by (metis le_lt_eq propNo_trans_lt_lt)
lemma (in propNoL) propNo_trans_le_lt [trans]:
"p1 \<preceq> p2 \<Longrightarrow> p2 \<prec> p3 \<Longrightarrow> p1 \<prec> p3"
by (metis le_lt_eq propNo_trans_lt_lt)
lemma (in propNoL) propNo_trans_le_le [trans]:
assumes p12: "p1 \<preceq> p2" and p23: "p2 \<preceq> p3"
shows "p1 \<preceq> p3"
by (metis le_lt_eq p12 p23 propNo_trans_lt_le)
fun weight :: "('acc \<Rightarrow> nat) \<Rightarrow> 'acc set \<Rightarrow> nat"
where "weight f S = setsum f { a \<in> S. f a \<noteq> 0 }"
fun isWeightedMajority :: "('acc \<Rightarrow> nat) \<Rightarrow> 'acc set \<Rightarrow> bool"
where "isWeightedMajority f S = (finite { a. f a \<noteq> 0 } \<and> finite S \<and> weight f UNIV < 2 * weight f S)"
lemma
assumes S1: "isWeightedMajority f1 S1"
assumes S2: "isWeightedMajority f2 S2"
assumes d1: "d \<le> 1"
assumes fa0: "f2 a0 = f1 a0 + d"
assumes f: "\<And>a. a \<noteq> a0 \<Longrightarrow> f1 a = f2 a"
shows weighted_majority_intersects: "S1 \<inter> S2 \<noteq> ({} :: 'acc set)"
proof (intro notI)
assume inter: "S1 \<inter> S2 = {}"
{
have halves_gt: "\<And>a b c::nat. c < 2 * a \<Longrightarrow> c \<le> 2 * b \<Longrightarrow> c < a + b" by linarith
presume "weight f1 UNIV \<le> 2 * weight f1 S2"
with S1 have "weight f1 UNIV < weight f1 S1 + weight f1 S2"
by (intro halves_gt, simp_all)
also presume "weight f1 S1 + weight f1 S2 = weight f1 (S1 \<union> S2)"
also have "weight f1 (S1 \<union> S2) \<le> weight f1 UNIV"
using S1 by (unfold weight.simps, intro setsum_mono3, auto)
finally show False by simp
next
show "weight f1 S1 + weight f1 S2 = weight f1 (S1 \<union> S2)"
proof -
have "weight f1 (S1 \<union> S2) = setsum f1 {a \<in> S1 \<union> S2. f1 a \<noteq> 0}" by simp
also have "... = setsum f1 ({ a \<in> S1. f1 a \<noteq> 0 } \<union> { a \<in> S2. f1 a \<noteq> 0 })"
by (rule cong [where f = "setsum f1"], auto)
also have "... = weight f1 S1 + weight f1 S2"
proof (unfold weight.simps, intro setsum.union_disjoint)
from S1 show "finite {a \<in> S1. f1 a \<noteq> 0}" and "finite {a \<in> S2. f1 a \<noteq> 0}" by auto
from inter show "{a \<in> S1. f1 a \<noteq> 0} \<inter> {a \<in> S2. f1 a \<noteq> 0} = {}" by auto
qed
finally show "weight f1 S1 + weight f1 S2 = weight f1 (S1 \<union> S2)" ..
qed
next
presume "weight f1 UNIV + d = weight f2 UNIV"
also from S2 have "... < 2 * weight f2 S2" by simp
also presume "weight f2 S2 \<le> weight f1 S2 + d"
hence "2 * weight f2 S2 \<le> 2 * (weight f1 S2 + d)" by simp
finally show "weight f1 UNIV \<le> 2 * weight f1 S2" using d1 by simp
next
have p: "\<And>S. a0 \<notin> S \<Longrightarrow> weight f2 S = weight f1 S"
proof -
fix S
assume a0S: "a0 \<notin> S"
with f have eq: "\<And>a. a \<in> S \<Longrightarrow> f1 a = f2 a" by metis
also from eq a0S have "setsum f2 { a \<in> S. f2 a \<noteq> 0 } = setsum f1 { a \<in> S. f1 a \<noteq> 0 }"
by (intro setsum.cong sym [OF f] equalityI subsetI CollectI conjI, auto)
thus "?thesis S" by simp
qed
have q: "\<And>S. weight f2 S = weight f1 S + (if a0 \<in> S then d else 0)"
proof (cases "d = 0")
case True
have "f2 = f1"
proof (intro ext)
fix a from f fa0 True show "f2 a = f1 a" by (cases "a = a0", auto)
qed
with True show "\<And>S. ?thesis S" by simp
next
case False
with d1 have d: "d = 1" by simp
fix S
show "?thesis S"
proof (cases "a0 \<in> S")
case False
with p [OF this] show ?thesis by simp
next
case True
note a0S = this
from d fa0 have fa01: "f2 a0 = f1 a0 + 1" by simp
have add_cong: "\<And>a b c d :: nat. a = c \<Longrightarrow> b = d \<Longrightarrow> a + b = c + d" by linarith
have "weight f2 S = setsum f2 { a \<in> S. f2 a \<noteq> 0 }" by simp
also from fa01 True have "... = setsum f2 (insert a0 { a \<in> (S - {a0}). f2 a \<noteq> 0 })"
by (intro setsum.cong refl, auto)
also from S2 have "... = f2 a0 + setsum f2 {a \<in> (S - {a0}). f2 a \<noteq> 0}"
by (intro setsum.insert, simp_all)
also have "... = f2 a0 + weight f2 (S - {a0})" by simp
also have "... = (f1 a0 + 1) + weight f1 (S - {a0})"
by (intro add_cong [OF fa01] p, simp)
also have "... = (f1 a0 + weight f1 (S - {a0})) + 1" by simp
also have "... = weight f1 S + (if a0 \<in> S then 1 else 0)"
proof (intro add_cong)
from True show "1 = (if a0 \<in> S then 1 else 0)" by simp
show "f1 a0 + weight f1 (S - {a0}) = weight f1 S"
proof (cases "f1 a0 = 0")
case True
have "weight f1 (S - {a0}) = weight f1 S"
by (unfold weight.simps, metis True member_remove remove_def)
with True show ?thesis by simp
next
case False
have "f1 a0 + weight f1 (S - {a0}) = f1 a0 + setsum f1 { a \<in> S - {a0}. f1 a \<noteq> 0 }" by simp
also from S1 have "... = setsum f1 (insert a0 { a \<in> S - {a0}. f1 a \<noteq> 0 })"
by (intro sym [OF setsum.insert], simp_all)
also from a0S False have "... = setsum f1 { a \<in> S. f1 a \<noteq> 0 }"
by (intro setsum.cong refl, auto)
also have "... = weight f1 S" by simp
finally show ?thesis .
qed
qed
also from d have "... = weight f1 S + (if a0 \<in> S then d else 0)" by simp
finally show ?thesis .
qed
qed
thus "weight f1 UNIV + d = weight f2 UNIV"
by (auto simp del: weight.simps)
from q show "weight f2 S2 \<le> weight f1 S2 + d"
by (cases "a0 \<in> S", auto simp del: weight.simps)
}
qed
lemma
assumes eq: "\<And>a :: 'aid. f1 a * d1 = f2 a * d2"
assumes d1: "0 < d1" and d2: "0 < d2"
shows weighted_majority_mul: "isWeightedMajority f1 = isWeightedMajority f2"
proof (intro ext iffI)
have p: "\<And>f1 f2 d1 d2 S. isWeightedMajority f1 S \<Longrightarrow> 0 < d1 \<Longrightarrow> 0 < (d2 :: nat) \<Longrightarrow> (\<And>a :: 'aid. f1 a * d1 = f2 a * d2) \<Longrightarrow> isWeightedMajority f2 S"
proof -
fix f1 f2 d1 d2 S
assume eq: "\<And>a :: 'aid. f1 a * d1 = f2 a * (d2 :: nat)"
and d1: "0 < d1" and d2: "0 < d2"
hence s0: "\<And> T. {a \<in> T. f2 a \<noteq> 0} = {a \<in> T. f1 a \<noteq> 0}"
by (metis le0 mult_is_0 not_le)
hence s1: "{a. f2 a \<noteq> 0} = {a. f1 a \<noteq> 0}" by auto
have d2I: "\<And>n m. d2 * n < d2 * (2 * m) \<Longrightarrow> n < 2 * m"
by (metis nat_mult_less_cancel_disj)
have d21: "\<And>T. d2 * setsum f2 T = d1 * setsum f1 T"
proof -
fix T
have "d2 * setsum f2 T = setsum (%n. d2 * f2 n) T" by (simp add: setsum_right_distrib)
also have "... = setsum (%n. d1 * f1 n) T"
proof (intro setsum.cong refl)
fix a
have "d1 * f1 a = f1 a * d1" by simp
also note eq
also have "f2 a * d2 = d2 * f2 a" by simp
finally show "d2 * f2 a = d1 * f1 a" ..
qed
also have "... = d1 * setsum f1 T" by (simp add: setsum_right_distrib)
finally show "?thesis T" .
qed
assume w1: "isWeightedMajority f1 S"
show "isWeightedMajority f2 S"
proof (unfold isWeightedMajority.simps weight.simps s0 s1, intro conjI d2I)
from w1 show "finite {a. f1 a \<noteq> 0}" and "finite S" by auto
have "d2 * setsum f2 {a \<in> UNIV. f1 a \<noteq> 0} = d1 * setsum f1 {a \<in> UNIV. f1 a \<noteq> 0}"
by (simp add: d21)
also from w1 d1 have "... < d1 * (2 * setsum f1 {a \<in> S. f1 a \<noteq> 0})"
by simp
also have "... = 2 * (d1 * setsum f1 {a \<in> S. f1 a \<noteq> 0})" by simp
also from d21 have "... = 2 * (d2 * setsum f2 {a \<in> S. f1 a \<noteq> 0})" by simp
also have "... = d2 * (2 * setsum f2 {a \<in> S. f1 a \<noteq> 0})" by simp
finally show "d2 * setsum f2 {a \<in> UNIV. f1 a \<noteq> 0} < ..." .
qed
qed
fix S
{
assume "isWeightedMajority f1 S"
from p [OF this d1 d2 eq]
show "isWeightedMajority f2 S".
next
assume "isWeightedMajority f2 S"
from p [OF this d2 d1 sym [OF eq]]
show "isWeightedMajority f1 S".
}
qed
locale topologyL =
fixes quorums_seq :: "'value list \<Rightarrow> ('aid set \<Rightarrow> bool) list"
assumes quorums_seq_nil: "quorums_seq [] \<noteq> []"
assumes quorums_seq_cons: "\<And>v vs. \<exists> qv. quorums_seq (v # vs) = qv @ quorums_seq vs"
assumes quorum_inter: "\<And>vs q S1 S2. q \<in> set (quorums_seq vs) \<Longrightarrow> q S1 \<Longrightarrow> q S2 \<Longrightarrow> S1 \<inter> S2 \<noteq> {}"
assumes quorum_inter_Suc: "\<And>vs tv S1 S2. Suc tv < length (quorums_seq vs) \<Longrightarrow> (quorums_seq vs ! tv) S1 \<Longrightarrow> (quorums_seq vs ! (Suc tv)) S2 \<Longrightarrow> S1 \<inter> S2 \<noteq> {}"
assumes quorum_finite: "\<And>vs q S. q \<in> set (quorums_seq vs) \<Longrightarrow> q S \<Longrightarrow> finite S"
assumes quorum_nonempty: "\<And>vs q S. q \<in> set (quorums_seq vs) \<Longrightarrow> q S \<Longrightarrow> S \<noteq> {}"
fixes topology_version :: "'value list \<Rightarrow> nat"
assumes topology_version_nil: "topology_version [] = 0"
assumes topology_version_cons: "\<And>v vs. topology_version (v#vs) \<ge> topology_version vs"
assumes topology_version_lt: "\<And>vs. topology_version vs < length (quorums_seq vs)"
lemma (in topologyL) quorums_seq_length_mono: "length (quorums_seq vs0) \<le> length (quorums_seq (vs1 @ vs0))"
proof (induct vs1)
case Nil thus ?case by simp
next
case (Cons v vs1)
from quorums_seq_cons
obtain qv where qv: "quorums_seq ((v # vs1) @ vs0) = qv @ quorums_seq (vs1 @ vs0)" by auto
note Cons
also have "length (quorums_seq (vs1 @ vs0)) \<le> length (quorums_seq ((v # vs1) @ vs0))"
by (unfold qv, auto)
finally show ?case .
qed
lemma (in topologyL) take_quorums_seq_append:
assumes n: "n \<le> length (quorums_seq vs0)"
shows "take n (rev (quorums_seq vs0)) = take n (rev (quorums_seq (vs1 @ vs0)))"
proof (induct vs1)
case Nil thus ?case by simp
next
case (Cons v vs1)
from quorums_seq_cons
obtain qv where qv: "quorums_seq ((v # vs1) @ vs0) = qv @ quorums_seq (vs1 @ vs0)" by auto
note n
also note quorums_seq_length_mono
finally have n_max: "n \<le> length (quorums_seq (vs1 @ vs0))".
note Cons
also have "take n (rev (quorums_seq (vs1 @ vs0))) = take n (rev (quorums_seq ((v # vs1) @ vs0)))"
by (unfold qv, simp add: n_max)
finally show ?case .
qed
lemma (in topologyL) take_quorums_seq:
assumes n: "n \<le> length (quorums_seq vs0)"
assumes ex1: "EX vs_new. vs1 = vs_new @ vs0"
assumes ex2: "EX vs_new. vs2 = vs_new @ vs0"
shows "take n (rev (quorums_seq vs1)) = take n (rev (quorums_seq vs2))"
proof -
from ex1 obtain vs1' where vs1: "vs1 = vs1' @ vs0" by auto
from ex2 obtain vs2' where vs2: "vs2 = vs2' @ vs0" by auto
have "take n (rev (quorums_seq vs1)) = take n (rev (quorums_seq vs0))"
by (unfold vs1, intro sym [OF take_quorums_seq_append] n)
also have "... = take n (rev (quorums_seq vs2))"
by (unfold vs2, intro take_quorums_seq_append n)
finally show ?thesis .
qed
lemma (in topologyL) quorums_seq_nonempty:
"quorums_seq vs \<noteq> []"
using quorums_seq_nil quorums_seq_cons
by (induct vs, simp, metis Nil_is_append_conv)
lemma (in topologyL) topology_version_mono:
"topology_version vs0 \<le> topology_version (vs1 @ vs0)"
proof (induct vs1)
case (Cons v vs1)
note Cons.hyps
also from topology_version_cons
have "topology_version (vs1 @ vs0) \<le> topology_version ((v # vs1) @ vs0)" by simp
finally show ?case .
qed simp
locale paxosL = propNoL +
fixes quorum_proposer :: "'pid \<Rightarrow> 'aid set \<Rightarrow> bool"
fixes quorum_learner :: "'pid \<Rightarrow> 'aid set \<Rightarrow> bool"
fixes promised_free :: "'aid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes promised_prev :: "'aid \<Rightarrow> 'pid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes proposed :: "'pid \<Rightarrow> bool"
fixes accepted :: "'aid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes chosen :: "'pid \<Rightarrow> bool"
fixes value_promised :: "'aid \<Rightarrow> 'pid \<Rightarrow> 'value"
fixes value_proposed :: "'pid \<Rightarrow> 'value"
fixes value_accepted :: "'aid \<Rightarrow> 'pid \<Rightarrow> 'value"
assumes quorum_inter: "\<And> SP SL p0 p1.
\<lbrakk> quorum_proposer p1 SP; quorum_learner p0 SL; chosen p0; proposed p1; p0 \<prec> p1 \<rbrakk>
\<Longrightarrow> SP \<inter> SL \<noteq> {}"
assumes quorum_finite: "\<And> SP p. quorum_proposer p SP \<Longrightarrow> finite SP"
assumes quorum_nonempty: "\<And> SL p. quorum_learner p SL \<Longrightarrow> SL \<noteq> {}"
assumes proposed_quorum:
"\<And> p . proposed p \<Longrightarrow> EX S. quorum_proposer p S
\<and> (ALL a:S. promised_free a p \<or> (EX p1. promised_prev a p p1))
\<and> (ALL a1:S. ALL p1. promised_prev a1 p p1
\<longrightarrow> value_proposed p = value_promised a1 p
\<or> (EX a2:S. EX p2. promised_prev a2 p p2 \<and> p1 \<prec> p2))"
assumes promised_free:
"\<And> a p0 p1. \<lbrakk> promised_free a p0; accepted a p1 \<rbrakk> \<Longrightarrow> p0 \<preceq> p1"
assumes promised_prev_accepted:
"\<And> a p0 p1. promised_prev a p0 p1 \<Longrightarrow> accepted a p1"
assumes promised_prev_prev:
"\<And> a p0 p1. promised_prev a p0 p1 \<Longrightarrow> p1 \<prec> p0"
assumes promised_prev_max:
"\<And> a p0 p1 p2. \<lbrakk> promised_prev a p0 p1; accepted a p2; p2 \<prec> p0 \<rbrakk>
\<Longrightarrow> ((p1 = p2 \<and> value_accepted a p1 = value_promised a p0) \<or> p2 \<prec> p1)"
assumes accepts_proposed:
"\<And> p a. accepted a p \<Longrightarrow> proposed p"
assumes accepts_value:
"\<And> p a. accepted a p \<Longrightarrow> value_accepted a p = value_proposed p"
assumes chosen_quorum:
"\<And> p . chosen p \<Longrightarrow> EX S. quorum_learner p S \<and> (ALL a:S. accepted a p)"
lemma (in paxosL) promised_some_none:
assumes "promised_prev a p0 p1" "promised_free a p0"
shows P
proof -
have "promised_prev a p0 p1 \<longrightarrow> \<not> promised_free a p0"
by (metis promised_free promised_prev_accepted promised_prev_prev propNo_leE propNo_lt_not_ge_E)
with assms show P by simp
qed
lemma (in paxosL) promised_prev_fun:
assumes "promised_prev a p0 p1" "promised_prev a p0 p2"
shows "p1 = p2"
by (metis assms promised_prev_accepted promised_prev_max promised_prev_prev propNo_lt_not_ge_E)
lemma (in paxosL)
assumes "quorum_proposer p S"
shows paxos_max_proposer: "(ALL a0:S. ALL p1. \<not> promised_prev a0 p p1)
\<or> (EX a1:S. EX p1. promised_prev a1 p p1
\<and> (ALL a3:S. ALL p3. promised_prev a3 p p3 \<longrightarrow> p3 \<preceq> p1))"
(is "?P1 S \<or> ?P2 S")
proof -
from assms quorum_finite
have "finite S" by simp
thus ?thesis
proof (induct S rule: finite_induct)
case empty thus ?case by simp
next
case (insert a S')
show ?case
proof (cases "EX p0. promised_prev a p p0")
case False
from insert.hyps
show ?thesis
proof (elim disjE)
assume hyp1: "?P1 S'"
show ?thesis
by (intro disjI1 ballI allI impI, metis False hyp1 insert_iff)
next
assume hyp2: "?P2 S'"
then obtain a1 p1 where a1S: "a1 \<in> S'" and p: "promised_prev a1 p p1"
and p1_max: "\<And>a3 p3. \<lbrakk> a3 \<in> S'; promised_prev a3 p p3 \<rbrakk> \<Longrightarrow> p3 \<preceq> p1"
by auto
show ?thesis
proof (intro disjI2 bexI exI conjI ballI allI impI)
from p show "promised_prev a1 p p1" .
from a1S show "a1 \<in> insert a S'" by simp
fix a3 p3
assume "a3 \<in> insert a S'" and "promised_prev a3 p p3"
thus "p3 \<preceq> p1" by (metis False insert_iff p1_max)
qed
qed
next
case True
then obtain p0 where p0: "promised_prev a p p0" by auto
from insert.hyps
have "?P2 (insert a S')"
proof (elim disjE)
assume "?P1 S'"
hence none_proposed: "\<And> a1 p1 P. \<lbrakk> a1 \<in> S'; promised_prev a1 p p1 \<rbrakk> \<Longrightarrow> P" by simp
show ?thesis
proof (intro bexI exI conjI impI ballI allI)
show "a \<in> insert a S'" by simp
from p0 show "promised_prev a p p0" .
fix a3 p3
assume "a3 \<in> insert a S'" and p: "promised_prev a3 p p3"
thus "p3 \<preceq> p0"
by (metis insert_iff le_lt_eq none_proposed p0 promised_prev_fun)
qed
next
assume "?P2 S'"
then obtain a1 p1 where a1S: "a1 \<in> S'" and p: "promised_prev a1 p p1"
and p1_max: "\<And>a3 p3. \<lbrakk> a3 \<in> S'; promised_prev a3 p p3 \<rbrakk> \<Longrightarrow> p3 \<preceq> p1" by auto
have le: "p0 \<preceq> p1 \<Longrightarrow> ?thesis"
proof (intro bexI exI conjI ballI allI impI)
assume p10: "p0 \<preceq> p1"
hence p10_cases: "p0 \<prec> p1 \<or> p0 = p1" by simp
from p show "promised_prev a1 p p1" .
from a1S show "a1 \<in> insert a S'" by simp
fix a3 p3
assume "a3 \<in> insert a S'"
and p3: "promised_prev a3 p p3"
hence "a3 = a \<or> a3 \<in> S'" by simp
from this p10_cases show "p3 \<preceq> p1"
apply (elim disjE)
apply (metis p0 p10 p3 promised_prev_fun)
apply (metis le_lt_eq p0 p3 promised_prev_fun)
apply (metis p1_max p3)
by (metis p1_max p3)
qed
show ?thesis
proof (rule propNo_cases)
assume "p1 = p0" with le show ?thesis by simp
next
assume "p0 \<prec> p1" with le show ?thesis by simp
next
assume p1p: "p1 \<prec> p0"
show ?thesis
proof (intro bexI exI conjI ballI allI impI)
from p0 show "promised_prev a p p0" .
show "a \<in> insert a S'" by simp
fix a3 p3
assume "a3 \<in> insert a S'"
and p3: "promised_prev a3 p p3"
hence "a3 = a \<or> a3 \<in> S'" by simp
thus "p3 \<preceq> p0"
apply (elim disjE)
apply (metis le_lt_eq p0 p3 promised_prev_fun)
by (metis le_lt_eq p1_max p1p p3 propNo_trans_le_le)
qed
qed
qed
thus ?thesis by simp
qed
qed
qed
lemma (in paxosL) p2c:
assumes proposed_p0: "proposed p0"
obtains S where "quorum_proposer p0 S"
and "(ALL a1 : S. ALL p1. p1 \<prec> p0 \<longrightarrow> \<not> accepted a1 p1)
\<or> (EX a1 : S. EX p1. accepted a1 p1
\<and> value_proposed p0 = value_accepted a1 p1
\<and> p1 \<prec> p0
\<and> (ALL a2 : S. ALL p2. (accepted a2 p2 \<and> p2 \<prec> p0) \<longrightarrow> p2 \<preceq> p1))"
proof -
from proposed_quorum [OF proposed_p0]
obtain S where quorum_S: "quorum_proposer p0 S"
and S_promised: "\<And> a1. a1 \<in> S \<Longrightarrow> promised_free a1 p0 \<or> (\<exists>p1. promised_prev a1 p0 p1)"
and S_value: "\<And>a1 p1. \<lbrakk> a1 \<in> S; promised_prev a1 p0 p1 \<rbrakk> \<Longrightarrow> value_proposed p0 = value_promised a1 p0 \<or> (\<exists>a2\<in>S. \<exists>p2. promised_prev a2 p0 p2 \<and> p1 \<prec> p2)"
by auto
show thesis
proof (intro that)
from quorum_S show "quorum_proposer p0 S" .
show "(ALL a1 : S. ALL p1. p1 \<prec> p0 \<longrightarrow> \<not> accepted a1 p1)
\<or> (EX a1 : S. EX p1. accepted a1 p1
\<and> value_proposed p0 = value_accepted a1 p1
\<and> p1 \<prec> p0
\<and> (ALL a2 : S. ALL p2. (accepted a2 p2 \<and> p2 \<prec> p0) \<longrightarrow> p2 \<preceq> p1))"
(is "?ALLFRESH \<or> ?EXISTSMAX")
proof (cases "ALL a1:S. promised_free a1 p0")
case True
show ?thesis
by (metis True promised_free propNo_irreflexive propNo_trans_lt_le)
next
case False
then obtain a2 where a2S: "a2 \<in> S" and not_None: "\<not> promised_free a2 p0" by auto
from S_promised a2S not_None obtain p2 where p2: "promised_prev a2 p0 p2" by metis
from paxos_max_proposer [OF quorum_S]
obtain a1 p1
where a1S: "a1 \<in> S"
and p1: "promised_prev a1 p0 p1"
and p1_max: "\<And>a3 p3. \<lbrakk> a3 \<in> S; promised_prev a3 p0 p3 \<rbrakk> \<Longrightarrow> p3 \<preceq> p1"
by (metis a2S p2)
have lt10: "p1 \<prec> p0" by (metis p1 promised_prev_prev)
show ?thesis
proof (intro exI conjI disjI2 bexI ballI allI impI)
from p1 show acc1: "accepted a1 p1" by (metis promised_prev_accepted)
from a1S show "a1 \<in> S" .
from S_value [OF a1S p1]
show "value_proposed p0 = value_accepted a1 p1"
by (metis acc1 lt10 p1 p1_max promised_prev_max propNo_irreflexive propNo_trans_lt_le)
from lt10 show "p1 \<prec> p0" .
fix a3 p3 assume a3S: "a3 \<in> S" and p3: "accepted a3 p3 \<and> p3 \<prec> p0"
from a3S S_promised obtain p4 where p4: "promised_prev a3 p0 p4"
by (metis p3 promised_free propNo_leE propNo_lt_not_ge_E)
show "p3 \<preceq> p1"
by (metis a3S le_lt_eq p1_max p3 p4 promised_prev_max propNo_trans_le_le)
qed
qed
qed
qed
lemma (in paxosL) p2b:
assumes chosen: "chosen p0"
shows "\<And>p1. \<lbrakk> proposed p1; p0 \<prec> p1 \<rbrakk> \<Longrightarrow> value_proposed p0 = value_proposed p1"
proof -
from chosen_quorum [OF chosen] obtain SL
where SC_quorum: "quorum_learner p0 SL"
and SC_accepts: "\<And>a. \<lbrakk> a \<in> SL \<rbrakk> \<Longrightarrow> accepted a p0" by auto
fix p1_base
assume "proposed p1_base" "p0 \<prec> p1_base" thus "?thesis p1_base"
proof (induct p1_base rule: wf_induct [OF wf])
fix p1
assume proposed: "proposed p1" and p01: "p0 \<prec> p1"
assume "\<forall>p2. (p2, p1) \<in> {(p,q). p \<prec> q} \<longrightarrow> proposed p2 \<longrightarrow> p0 \<prec> p2 \<longrightarrow> value_proposed p0 = value_proposed p2"
hence
hyp: "\<And>p2. \<lbrakk> p2 \<prec> p1; proposed p2; p0 \<prec> p2 \<rbrakk> \<Longrightarrow> value_proposed p0 = value_proposed p2" by auto
from p2c [OF proposed] obtain SP where SP_quorum: "quorum_proposer p1 SP"
and S_mess: "((\<forall>a1\<in>SP. \<forall>p1a. p1a \<prec> p1 \<longrightarrow> \<not> accepted a1 p1a)
\<or> (\<exists>a1\<in>SP. \<exists>p1a. accepted a1 p1a \<and> value_proposed p1 = value_accepted a1 p1a \<and> p1a \<prec> p1
\<and> (\<forall>a2\<in>SP. \<forall>p2. accepted a2 p2 \<and> p2 \<prec> p1 \<longrightarrow> p2 \<preceq> p1a)))"
(is "?P1 \<or> ?P2") by auto
from SP_quorum SC_quorum quorum_inter chosen proposed p01
obtain a where aSP: "a \<in> SP" and aSC: "a \<in> SL"
by (metis disjoint_iff_not_equal)
from S_mess
show "value_proposed p0 = value_proposed p1"
proof (elim disjE)
assume "?P1"
thus ?thesis
by (metis SC_accepts aSC aSP p01)
next
assume "?P2"
thus ?thesis
by (metis SC_accepts aSC aSP accepts_proposed accepts_value hyp p01 propNo_leE)
qed
qed
qed
lemma (in paxosL)
assumes "chosen p0" and "accepted a1 p1" and "p0 \<prec> p1"
shows p2a: "value_proposed p0 = value_proposed p1"
using assms by (intro p2b accepts_proposed)
lemma (in paxosL)
assumes chosen0: "chosen p0"
assumes chosen1: "chosen p1"
assumes p01: "p0 \<prec> p1"
shows p2: "value_proposed p0 = value_proposed p1"
proof -
from chosen_quorum [OF chosen1]
obtain S where QL: "quorum_learner p1 S" and acc: "\<And>a. a \<in> S \<Longrightarrow> accepted a p1" by auto
from quorum_nonempty [OF QL] obtain a where aS: "a \<in> S" by auto
show ?thesis by (metis p2a chosen0 p01 acc aS)
qed
theorem (in paxosL)
assumes chosen0: "chosen p0"
assumes chosen1: "chosen p1"
shows paxos_consistent: "value_proposed p0 = value_proposed p1"
by (metis assms le_lt_eq p2 propNo_cases)
lemma (in paxosL)
assumes "quorum_learner p0 S"
assumes "\<And>a. a \<in> S \<Longrightarrow> accepted a p0"
assumes p0_quorum_inter: "\<And> SP SL p1.
\<lbrakk> quorum_proposer p1 SP; quorum_learner p0 SL; proposed p1; p0 \<prec> p1 \<rbrakk>
\<Longrightarrow> SP \<inter> SL \<noteq> {}"
shows paxos_add_chosen: "paxosL lt le quorum_proposer quorum_learner promised_free promised_prev
proposed accepted (%p. p = p0 \<or> chosen p) value_promised value_proposed value_accepted"
using accepts_proposed accepts_value chosen_quorum promised_free
promised_prev_accepted promised_prev_max promised_prev_prev
proposed_quorum quorum_finite quorum_inter
quorum_nonempty assms
apply unfold_locales
proof -
fix SP SL p0a p1
assume "quorum_proposer p1 SP" "quorum_learner p0a SL" "proposed p1" "p0a \<prec> p1" "p0a = p0 \<or> chosen p0a"
thus "SP \<inter> SL \<noteq> {}" by (metis p0_quorum_inter quorum_inter)
qed auto
fun desc_lt :: "nat \<Rightarrow> nat list"
where "desc_lt 0 = []"
| "desc_lt (Suc n) = n # desc_lt n"
lemma desc_lt_seq: "desc_lt n = rev [0 ..< n]" by (induct n, auto)
lemma
assumes jk: "j \<le> k"
shows desc_lt_append: "desc_lt k = map (\<lambda>i. i + j) (desc_lt (k - j)) @ desc_lt j"
proof -
have "map (\<lambda>i. i + j) (desc_lt (k - j)) @ desc_lt j = rev ([0..<j] @ (map (\<lambda>i. i + j) [0..<k - j]))"
by (simp add: desc_lt_seq rev_map)
also have "... = rev [0..<k]"
by (metis add.commute jk le0 le_add_diff_inverse map_add_upt upt_add_eq_append)
also have "... = desc_lt k" by (simp add: desc_lt_seq)
finally show "desc_lt k = map (\<lambda>i. i + j) (desc_lt (k - j)) @ desc_lt j"..
qed
locale propTvL = propNoL +
fixes prop_topology_version :: "'pid \<Rightarrow> nat"
assumes prop_topology_version_mono: "\<And>p0 p1. p0 \<preceq> p1 \<Longrightarrow> prop_topology_version p0 \<le> prop_topology_version p1"
locale multiPaxosL
= p: propNoL lt le
+ t: topologyL quorums_seq topology_version
+ v: propTvL lt le prop_topology_version
for lt :: "'pid \<Rightarrow> 'pid \<Rightarrow> bool" (infixl "\<prec>" 50)
and le :: "'pid \<Rightarrow> 'pid \<Rightarrow> bool" (infixl "\<preceq>" 50)
and quorums_seq :: "'value list \<Rightarrow> ('aid set \<Rightarrow> bool) list"
and topology_version :: "'value list \<Rightarrow> nat"
and prop_topology_version :: "'pid \<Rightarrow> nat"
+
(* Message predicates *)
fixes multi_promised :: "nat \<Rightarrow> 'aid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes promised_free :: "nat \<Rightarrow> 'aid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes promised_prev :: "nat \<Rightarrow> 'aid \<Rightarrow> 'pid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes proposed :: "nat \<Rightarrow> 'pid \<Rightarrow> bool"
fixes accepted :: "nat \<Rightarrow> 'aid \<Rightarrow> 'pid \<Rightarrow> bool"
fixes chosen :: "nat \<Rightarrow> 'pid \<Rightarrow> bool"
fixes some_chosen :: "nat \<Rightarrow> bool"
defines some_chosen_def: "some_chosen == (%i. EX p. chosen i p)"
fixes chosen_to :: "nat \<Rightarrow> bool"
defines chosen_to_def: "chosen_to == (%i. ALL j < i. some_chosen j)"
(* Value functions *)
fixes value_promised :: "nat \<Rightarrow> 'aid \<Rightarrow> 'pid \<Rightarrow> 'value"
fixes value_proposed :: "nat \<Rightarrow> 'pid \<Rightarrow> 'value"
fixes value_accepted :: "nat \<Rightarrow> 'aid \<Rightarrow> 'pid \<Rightarrow> 'value"
fixes value_chosen :: "nat \<Rightarrow> 'value"
defines value_chosen_def: "value_chosen == (%i. THE v. EX p'. chosen i p' \<and> value_proposed i p' = v)"
fixes values_lt_list :: "nat \<Rightarrow> 'value list"
defines values_lt_list_def: "values_lt_list == (%i. map value_chosen (desc_lt i))"
fixes instance_topology_version :: "nat \<Rightarrow> nat"
defines instance_topology_version_def: "instance_topology_version == (%i. topology_version (values_lt_list i))"
fixes quorum :: "nat \<Rightarrow> 'aid set \<Rightarrow> bool"
defines quorum_def: "quorum == (%tv. rev (quorums_seq (values_lt_list (SOME i. tv < length (quorums_seq (values_lt_list i))))) ! tv)"
assumes proposed_quorum:
"\<And> i p. proposed i p \<Longrightarrow> \<exists> S.
(quorum (prop_topology_version p) S)
\<and> (\<forall> a \<in> S. (promised_free i a p
\<or> (\<exists>j \<le> i. multi_promised j a p))
\<or> (\<exists> p1. promised_prev i a p p1))
\<and> (\<forall> a1 \<in> S. ALL p1. promised_prev i a1 p p1
\<longrightarrow> value_proposed i p = value_promised i a1 p
\<or> (\<exists> a2 \<in> S. EX p2. promised_prev i a2 p p2 \<and> p1 \<prec> p2))"
assumes proposed_topology:
"\<And> i p. proposed i p \<Longrightarrow> prop_topology_version p \<le> instance_topology_version (GREATEST j. j \<le> i \<and> chosen_to j)"
assumes promised_free:
"\<And> i a p0 p1. \<lbrakk> promised_free i a p0; accepted i a p1 \<rbrakk> \<Longrightarrow> p0 \<preceq> p1"
assumes multi_promised:
"\<And>i j a p0 p1. \<lbrakk> multi_promised i a p0; accepted j a p1; i \<le> j \<rbrakk> \<Longrightarrow> p0 \<preceq> p1"
assumes promised_prev_accepted:
"\<And> i a p0 p1. promised_prev i a p0 p1 \<Longrightarrow> accepted i a p1"
assumes promised_prev_prev:
"\<And> i a p0 p1. promised_prev i a p0 p1 \<Longrightarrow> p1 \<prec> p0"
assumes promised_prev_max:
"\<And> i a p0 p1 p2. \<lbrakk> promised_prev i a p0 p1; accepted i a p2; p2 \<prec> p0 \<rbrakk>
\<Longrightarrow> ((p1 = p2 \<and> value_accepted i a p1 = value_promised i a p0) \<or> p2 \<prec> p1)"
assumes accepts_proposed:
"\<And> i p a. accepted i a p \<Longrightarrow> proposed i p"
assumes accepts_value:
"\<And> i p a. accepted i a p \<Longrightarrow> value_accepted i a p = value_proposed i p"
assumes chosen_quorum:
"\<And> i p. chosen i p \<Longrightarrow> EX S. S \<noteq> {} \<and> quorum (prop_topology_version p) S \<and> (ALL a:S. accepted i a p)"
assumes chosen_topology:
"\<And> i p. chosen i p \<Longrightarrow> instance_topology_version i \<le> Suc (prop_topology_version p)"
assumes chosen_Suc: "\<And>i. some_chosen (Suc i) \<Longrightarrow> some_chosen i"
lemma take_mem_eq:
assumes take_eq: "take (Suc n) xs = take (Suc n) ys"
shows "xs ! n = ys ! n"
proof -
have "xs ! n = take (Suc n) xs ! n" by (intro sym [OF nth_take], simp)
also note take_eq
also have "take (Suc n) ys ! n = ys ! n" by (intro nth_take, simp)
finally show ?thesis .
qed
lemma (in multiPaxosL) quorum_topology_version:
fixes i tv
assumes le: "tv \<le> instance_topology_version i"
shows "quorum tv = rev (quorums_seq (values_lt_list i)) ! tv"
proof -
from le have "tv \<le> topology_version (values_lt_list i)" by (simp add: instance_topology_version_def)
also note topology_version_lt
finally have tv_len: "tv < length (quorums_seq (values_lt_list i))" .
def min_i == "LEAST j. tv < length (quorums_seq (values_lt_list j))"
from tv_len have le_min: "tv < length (quorums_seq (values_lt_list min_i))"
by (unfold min_i_def, intro LeastI)
have values_ex: "\<And>j k. j \<le> k \<Longrightarrow> \<exists>vs_new. values_lt_list k = vs_new @ values_lt_list j"
proof (intro exI, unfold values_lt_list_def)
fix j k :: nat
assume jk: "j \<le> k"
from desc_lt_append [OF this]
show "map value_chosen (desc_lt k) = map value_chosen (map (%i. i + j) (desc_lt (k - j))) @ map value_chosen (desc_lt j)"
by (fold map_append, intro cong [OF refl, where f = "map value_chosen"])
qed
show ?thesis
apply (unfold quorum_def)
apply (intro take_mem_eq take_quorums_seq [OF _ values_ex values_ex])
proof -
from le_min show "Suc tv \<le> length (quorums_seq (values_lt_list min_i))" by simp
show "min_i \<le> i" by (unfold min_i_def, intro Least_le tv_len)
from le_min show "min_i \<le> (SOME i. tv < length (quorums_seq (values_lt_list i)))"
by (unfold min_i_def, intro Least_le someI)
qed
qed
lemma (in multiPaxosL) chosen_to_0: "chosen_to 0" by (simp add: chosen_to_def)
lemma (in multiPaxosL) chosen_to_Suc: "some_chosen i \<Longrightarrow> chosen_to (Suc i)"
apply (induct i)
apply (unfold chosen_to_def)
by (simp, metis chosen_Suc less_Suc_eq)
lemma (in multiPaxosL) chosen_to_lt: "chosen_to i \<Longrightarrow> j \<le> i \<Longrightarrow> chosen_to j"
by (auto simp add: chosen_to_def)
lemma (in multiPaxosL) chosen_chosen_to:
assumes chosen: "some_chosen i"
shows "chosen_to i"
by (metis chosen_to_lt chosen_to_Suc chosen Suc_n_not_le_n linear)
lemma (in multiPaxosL) Greatest_chosen:
assumes "some_chosen i"
shows "(GREATEST j. j \<le> i \<and> chosen_to j) = i"
by (intro Greatest_equality conjI allI impI chosen_chosen_to [OF assms], simp_all)
lemma (in multiPaxosL)
assumes some_chosen: "some_chosen i"
shows multi_instances: "paxosL lt le
(%p S. quorum (prop_topology_version p) S \<and> prop_topology_version p \<le> instance_topology_version i)
(%p S. quorum (prop_topology_version p) S \<and> prop_topology_version p \<le> instance_topology_version i)
(%a p. promised_free i a p \<or> (EX j. j \<le> i \<and> multi_promised j a p))
(promised_prev i) (proposed i) (accepted i) (chosen i)
(value_promised i) (value_proposed i) (value_accepted i)"
apply unfold_locales
proof -
fix a p
assume acc: "accepted i a p"
from accepts_proposed acc show "proposed i p" by simp
from accepts_value acc show "value_accepted i a p = value_proposed i p" by simp
next
fix p
assume chosen: "chosen i p"
from chosen_quorum [OF this]
obtain S where qS: "quorum (prop_topology_version p) S" and accepted: "\<And>a. a \<in> S \<Longrightarrow> accepted i a p" and nz: "S \<noteq> {}"
by auto
from nz obtain a where aS: "a \<in> S" by auto
from accepts_proposed [OF accepted [OF aS]]
have proposed: "proposed i p" .
from Greatest_chosen [OF some_chosen] proposed_topology [OF proposed]
have p: "prop_topology_version p \<le> instance_topology_version i" by simp
show "\<exists>S. (quorum (prop_topology_version p) S \<and> prop_topology_version p \<le> instance_topology_version i) \<and> (\<forall>a\<in>S. accepted i a p)"
by (intro exI [where x = S] conjI ballI accepted qS p chosen allI impI)
next
fix a p0 p1
assume acc: "accepted i a p1"
assume "promised_free i a p0 \<or> (\<exists>j \<le> i. multi_promised j a p0)"
thus "p0 \<preceq> p1"
proof (elim disjE exE conjE)
assume "promised_free i a p0"
thus ?thesis by (metis promised_free acc)
next
fix j assume ji: "j \<le> i" and mp: "multi_promised j a p0"
thus ?thesis by (metis multi_promised acc)
qed
next
fix a p0 p1
assume pp: "promised_prev i a p0 p1"
show "accepted i a p1" by (metis promised_prev_accepted pp)
show "p1 \<prec> p0" by (metis promised_prev_prev pp)
fix p2
assume "accepted i a p2" and "p2 \<prec> p0"
thus "p1 = p2 \<and> value_accepted i a p1 = value_promised i a p0 \<or> p2 \<prec> p1"
by (metis promised_prev_max pp)
next
fix p
assume p: "proposed i p"
note proposed_quorum
have q: "\<And>P Q R. \<exists>a. P a \<and> R a \<Longrightarrow> Q \<Longrightarrow> \<exists>a. (P a \<and> Q) \<and> R a" by metis
have r: "chosen_to i" by (intro allI impI chosen_chosen_to [OF some_chosen])
from proposed_topology [OF p]
have pi: "prop_topology_version p \<le> instance_topology_version i" by (simp add: Greatest_chosen [OF some_chosen])
show "\<exists>S. (quorum (prop_topology_version p) S \<and> prop_topology_version p \<le> instance_topology_version i) \<and>
(\<forall>a\<in>S. (promised_free i a p \<or> (\<exists>j \<le> i. multi_promised j a p)) \<or> (\<exists>p1. promised_prev i a p p1))
\<and> (\<forall>a1\<in>S. \<forall>p1. promised_prev i a1 p p1 \<longrightarrow> value_proposed i p = value_promised i a1 p
\<or> (\<exists>a2\<in>S. \<exists>p2. promised_prev i a2 p p2 \<and> p1 \<prec> p2))"
by (intro proposed_quorum q p proposed_topology r pi)
next
{
fix p
assume le: "prop_topology_version p \<le> instance_topology_version i"
have "quorum (prop_topology_version p) \<in> set (rev (quorums_seq (values_lt_list i)))"
proof (unfold quorum_topology_version [OF le], intro nth_mem)
from le have "prop_topology_version p \<le> topology_version (values_lt_list i)"
by (simp add: instance_topology_version_def)
also note topology_version_lt
finally show "prop_topology_version p < length (rev (quorums_seq (values_lt_list i)))" by simp
qed
hence "quorum (prop_topology_version p) \<in> set (quorums_seq (values_lt_list i))" by simp
}
note quorum_mem = this
{
fix S p
assume p: "quorum (prop_topology_version p) S \<and> prop_topology_version p \<le> instance_topology_version i"
hence q: "quorum (prop_topology_version p) S" and le: "prop_topology_version p \<le> instance_topology_version i" by simp_all
note mem = quorum_mem [OF le]
show "finite S"
by (intro quorum_finite [where q = "quorum (prop_topology_version p)" and vs = "values_lt_list i"] mem q)
show "S \<noteq> {}"
by (intro quorum_nonempty [where q = "quorum (prop_topology_version p)" and vs = "values_lt_list i"] mem q)
next
fix SP SL p0 p1
assume "quorum (prop_topology_version p1) SP \<and> prop_topology_version p1 \<le> instance_topology_version i"
and "quorum (prop_topology_version p0) SL \<and> prop_topology_version p0 \<le> instance_topology_version i"
hence qSP: "quorum (prop_topology_version p1) SP" and p1i: "prop_topology_version p1 \<le> instance_topology_version i"
and qSL: "quorum (prop_topology_version p0) SL" and p0i: "prop_topology_version p0 \<le> instance_topology_version i"
by simp_all
note quorum_topology_version [OF p1i]
assume chosen: "chosen i p0" and proposed: "proposed i p1" and p01: "p0 \<prec> p1"
from chosen have some_chosen: "some_chosen i" by (auto simp add: some_chosen_def)
from proposed_topology [OF proposed] have "prop_topology_version p1 \<le> instance_topology_version i"
by (simp add: Greatest_chosen [OF some_chosen])
also note chosen_topology [OF chosen]
finally have tv10: "prop_topology_version p1 \<le> Suc (prop_topology_version p0)" .
from p01 have tv01: "prop_topology_version p0 \<le> prop_topology_version p1"
by (intro prop_topology_version_mono, simp)
from tv01 tv10 have "prop_topology_version p0 = prop_topology_version p1 \<or> Suc (prop_topology_version p0) = prop_topology_version p1"
by auto
thus "SP \<inter> SL \<noteq> {}"
proof (elim disjE)
assume eq: "prop_topology_version p0 = prop_topology_version p1"
show ?thesis
by (intro quorum_inter [OF quorum_mem [OF p0i]] qSL, unfold eq, intro qSP)
next
assume eq: "Suc (prop_topology_version p0) = prop_topology_version p1"
show ?thesis
proof (intro quorum_inter_Suc)
have prop_p1_lt_len: "prop_topology_version p1 < length (quorums_seq (values_lt_list i))"
proof -
from p1i have "prop_topology_version p1 \<le> topology_version (values_lt_list i)"
by (simp add: instance_topology_version_def)
also note topology_version_lt
finally show ?thesis .
qed
note quorum_topology_version [OF p1i]
also have "rev (quorums_seq (values_lt_list i)) ! prop_topology_version p1 = quorums_seq (values_lt_list i) ! (length (quorums_seq (values_lt_list i) ) - Suc (prop_topology_version p1))"
by (intro rev_nth prop_p1_lt_len)
finally have "quorum (prop_topology_version p1) = quorums_seq (values_lt_list i) ! (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1))" .
with qSP show "(quorums_seq (values_lt_list i) ! (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1))) SP" by simp
from prop_p1_lt_len
have Suc_Suc_eq: "Suc (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1)) = length (quorums_seq (values_lt_list i)) - prop_topology_version p1" by auto
note quorum_topology_version [OF p0i]
also have "rev (quorums_seq (values_lt_list i)) ! prop_topology_version p0 = quorums_seq (values_lt_list i) ! (length (quorums_seq (values_lt_list i) ) - Suc (prop_topology_version p0))"
proof (intro rev_nth)
from p0i have "prop_topology_version p0 \<le> topology_version (values_lt_list i)"
by (simp add: instance_topology_version_def)
also note topology_version_lt
finally show "prop_topology_version p0 < length (quorums_seq (values_lt_list i))" .
qed
finally have "quorum (prop_topology_version p0) = quorums_seq (values_lt_list i) ! (Suc (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1)))"
by (simp add: eq Suc_Suc_eq)
with qSL show "(quorums_seq (values_lt_list i) ! Suc (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1))) SL" by simp
from quorums_seq_nonempty have nz: "0 < length (quorums_seq (values_lt_list i))" by simp
from prop_p1_lt_len eq
have "Suc (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1)) = length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p0)"
by auto
also from nz have "... < length (quorums_seq (values_lt_list i))" by auto
finally show "Suc (length (quorums_seq (values_lt_list i)) - Suc (prop_topology_version p1)) < length (quorums_seq (values_lt_list i))" .
qed
qed
}
qed
theorem (in multiPaxosL)
assumes "chosen i p1" and "chosen i p2"
shows multi_paxos_consistent: "value_proposed i p1 = value_proposed i p2"
using assms by (intro paxosL.paxos_consistent [OF multi_instances], auto simp add: some_chosen_def)
lemma (in multiPaxosL) multiPaxos_the_value:
assumes c: "chosen i p"