-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintersection.lean
1457 lines (1383 loc) · 39.2 KB
/
intersection.lean
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
import classes.context_free.basics.pumping
import classes.context_free.basics.elementary
import classes.context_free.closure_properties.concatenation
import classes.context_free.closure_properties.permutation
section defs_over_fin3
private def a_ : fin 3 := 0
private def b_ : fin 3 := 1
private def c_ : fin 3 := 2
private def a : symbol (fin 3) (fin 1) := symbol.terminal a_
private def b : symbol (fin 3) (fin 1) := symbol.terminal b_
private def c : symbol (fin 3) (fin 1) := symbol.terminal c_
private lemma neq_ab : a_ ≠ b_ := by dec_trivial
private lemma neq_ba : b_ ≠ a_ := neq_ab.symm
private lemma neq_ac : a_ ≠ c_ := by dec_trivial
private lemma neq_ca : c_ ≠ a_ := neq_ac.symm
private lemma neq_bc : b_ ≠ c_ := by dec_trivial
private lemma neq_cb : c_ ≠ b_ := neq_bc.symm
private def lang_eq_any : language (fin 3) :=
λ w, ∃ n m : ℕ, w = list.repeat a_ n ++ list.repeat b_ n ++ list.repeat c_ m
private def lang_any_eq : language (fin 3) :=
λ w, ∃ n m : ℕ, w = list.repeat a_ n ++ list.repeat b_ m ++ list.repeat c_ m
private def lang_eq_eq : language (fin 3) :=
λ w, ∃ n : ℕ, w = list.repeat a_ n ++ list.repeat b_ n ++ list.repeat c_ n
end defs_over_fin3
section not_CF
private lemma false_of_uvvxyyz
{_a _b _c : fin 3} {n : ℕ} {u v x y z : list (fin 3)}
(elimin : ∀ s : fin 3, s ≠ _a → s ≠ _b → s ≠ _c → false)
(no_a : _a ∉ v ++ y) (nonempty : (v ++ y).length > 0)
(counts_ab : ∀ (w : list (fin 3)), w ∈ lang_eq_eq → list.count_in w _a = list.count_in w _b)
(counts_ac : ∀ (w : list (fin 3)), w ∈ lang_eq_eq → list.count_in w _a = list.count_in w _c)
(counted_a : list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) _a = n + 1 + list.count_in (v ++ y) _a)
(counted_b : list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) _b = n + 1 + list.count_in (v ++ y) _b)
(counted_c : list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) _c = n + 1 + list.count_in (v ++ y) _c)
(pumping : u ++ v ^ 2 ++ x ++ y ^ 2 ++ z ∈ lang_eq_eq) :
false :=
begin
have extra_not_a : _b ∈ (v ++ y) ∨ _c ∈ (v ++ y),
{
let first_letter := (v ++ y).nth_le 0 nonempty,
have first_letter_b_or_c : first_letter = _b ∨ first_letter = _c,
{
have first_letter_not_a : first_letter ≠ _a,
{
by_contradiction contra,
have yes_a : _a ∈ v ++ y,
{
rw ←contra,
apply list.nth_le_mem,
},
exact no_a yes_a,
},
by_contradiction contr,
push_neg at contr,
cases contr with first_letter_not_b first_letter_not_c,
exact elimin ((v ++ y).nth_le 0 nonempty) first_letter_not_a first_letter_not_b first_letter_not_c,
},
cases first_letter_b_or_c with first_letter_b first_letter_c,
{
left,
rw ←first_letter_b,
apply list.nth_le_mem,
},
{
right,
rw ←first_letter_c,
apply list.nth_le_mem,
},
},
have hab := counts_ab (u ++ v ^ 2 ++ x ++ y ^ 2 ++ z) pumping,
have hac := counts_ac (u ++ v ^ 2 ++ x ++ y ^ 2 ++ z) pumping,
cases pumping with n' pump',
have count_a : list.count_in (u ++ v ^ 2 ++ x ++ y ^ 2 ++ z) _a = n + 1,
{
unfold list.n_times,
simp [- list.append_assoc],
repeat {
rw list.count_in_append,
},
have rearrange :
list.count_in u _a + (list.count_in v _a + list.count_in v _a) + list.count_in x _a +
(list.count_in y _a + list.count_in y _a) + list.count_in z _a =
(list.count_in u _a + list.count_in v _a + list.count_in x _a + list.count_in y _a + list.count_in z _a) +
(list.count_in v _a + list.count_in y _a),
{
ring,
},
have zero_in_v : list.count_in v _a = 0,
{
rw list.mem_append at no_a,
push_neg at no_a,
exact list.count_in_zero_of_notin no_a.left,
},
have zero_in_y : list.count_in y _a = 0,
{
rw list.mem_append at no_a,
push_neg at no_a,
exact list.count_in_zero_of_notin no_a.right,
},
rw rearrange,
repeat {
rw ←list.count_in_append,
},
rw counted_a,
rw list.count_in_append,
rw zero_in_v,
rw zero_in_y,
},
cases extra_not_a with extra_b extra_c,
{
have count_b : list.count_in (u ++ v ^ 2 ++ x ++ y ^ 2 ++ z) _b > n + 1,
{
unfold list.n_times,
simp [- list.append_assoc],
repeat {
rw list.count_in_append,
},
have big_equality :
list.count_in u _b + (list.count_in v _b + list.count_in v _b) + list.count_in x _b +
(list.count_in y _b + list.count_in y _b) + list.count_in z _b =
(list.count_in u _b + list.count_in v _b + list.count_in x _b + list.count_in y _b + list.count_in z _b) +
(list.count_in v _b + list.count_in y _b),
{
ring,
},
rw big_equality,
repeat {
rw ←list.count_in_append,
},
rw counted_b,
have at_least_one_b : list.count_in (v ++ y) _b > 0,
{
exact list.count_in_pos_of_in extra_b,
},
linarith,
},
rw count_a at hab,
rw hab at count_b,
exact has_lt.lt.false count_b,
},
{
have count_c : list.count_in (u ++ v ^ 2 ++ x ++ y ^ 2 ++ z) _c > n + 1,
{
unfold list.n_times,
simp [- list.append_assoc],
repeat {
rw list.count_in_append,
},
have big_equality :
list.count_in u _c + (list.count_in v _c + list.count_in v _c) + list.count_in x _c +
(list.count_in y _c + list.count_in y _c) + list.count_in z _c =
(list.count_in u _c + list.count_in v _c + list.count_in x _c + list.count_in y _c + list.count_in z _c) +
(list.count_in v _c + list.count_in y _c),
{
ring,
},
rw big_equality,
repeat {
rw ←list.count_in_append,
},
rw counted_c,
have at_least_one_c : list.count_in (v ++ y) _c > 0,
{
exact list.count_in_pos_of_in extra_c,
},
linarith,
},
rw count_a at hac,
rw hac at count_c,
exact has_lt.lt.false count_c,
},
end
private lemma notCF_lang_eq_eq : ¬ is_CF lang_eq_eq :=
begin
intro h,
have pum := CF_pumping h,
cases pum with n pump,
specialize pump (list.repeat a_ (n+1) ++ list.repeat b_ (n+1) ++ list.repeat c_ (n+1)),
specialize pump (by { use n + 1, }) (by {
rw list.length_append,
rw list.length_repeat,
calc (list.repeat a_ (n + 1) ++ list.repeat b_ (n + 1)).length + (n + 1)
≥ n + 1 : le_add_self
... ≥ n : nat.le_succ n,
}),
rcases pump with ⟨u, v, x, y, z, concatenating, nonempty, vxy_short, pumping⟩,
specialize pumping 2,
have not_all_letters : a_ ∉ (v ++ y) ∨ b_ ∉ (v ++ y) ∨ c_ ∉ (v ++ y),
{
by_contradiction contr,
push_neg at contr,
rcases contr with ⟨hva, -, hvc⟩,
have vxy_long : (v ++ x ++ y).length > n,
{
by_contradiction contr,
push_neg at contr,
have total_length_exactly : u.length + (v ++ x ++ y).length + z.length = 3 * n + 3,
{
have total_length := congr_arg list.length concatenating,
repeat {
rw list.length_append at total_length,
},
repeat {
rw list.length_repeat at total_length,
},
ring_nf at total_length,
rw ←add_assoc x.length at total_length,
rw ←add_assoc v.length at total_length,
rw ←add_assoc v.length at total_length,
rw ←add_assoc u.length at total_length,
rw ←list.length_append_append at total_length,
exact total_length.symm,
},
have u_short : u.length ≤ n,
{
-- in contradiction with `hva: a_ ∈ v ++ y`
by_contradiction u_too_much,
push_neg at u_too_much,
have relaxed_a : a_ ∈ v ++ x ++ y ++ z,
{
cases (list.mem_append.1 hva) with a_in_v a_in_y,
{
rw list.append_assoc,
rw list.append_assoc,
rw list.mem_append,
left,
exact a_in_v,
},
{
have a_in_yz : a_ ∈ y ++ z,
{
rw list.mem_append,
left,
exact a_in_y,
},
rw list.append_assoc,
rw list.mem_append,
right,
exact a_in_yz,
},
},
repeat {
rw list.append_assoc at concatenating,
},
rcases list.nth_le_of_mem relaxed_a with ⟨nₐ, hnₐ, h_nthₐ⟩,
obtain ⟨h_nth_a_pr, h_nth_a⟩ :
∃ proofoo, (v ++ x ++ y ++ z).nth_le ((nₐ + u.length) - u.length) proofoo = a_,
{
rw nat.add_sub_cancel nₐ u.length,
use hnₐ,
exact h_nthₐ,
},
have lt_len : (nₐ + u.length) < (u ++ (v ++ x ++ y ++ z)).length,
{
rw list.length_append,
linarith,
},
rw ←list.nth_le_append_right le_add_self lt_len at h_nth_a,
have orig_nth_le_eq_a :
∃ proofoo,
(list.repeat a_ (n + 1) ++ (list.repeat b_ (n + 1) ++ list.repeat c_ (n + 1))).nth_le
(nₐ + u.length) proofoo =
a_,
{
have rebracket : u ++ (v ++ (x ++ (y ++ z))) = u ++ (v ++ x ++ y ++ z),
{
simp only [list.append_assoc],
},
rw concatenating,
rw rebracket,
use lt_len,
exact h_nth_a,
},
cases orig_nth_le_eq_a with rrr_nth_le_eq_a_pr rrr_nth_le_eq_a,
rw @list.nth_le_append_right (fin 3)
(list.repeat a_ (n + 1))
(list.repeat b_ (n + 1) ++ list.repeat c_ (n + 1))
(nₐ + u.length)
(by {
rw list.length_repeat,
calc n + 1 ≤ u.length : u_too_much
... ≤ nₐ + u.length : le_add_self,
})
(by {
rw concatenating,
rw ←list.append_assoc x,
rw ←list.append_assoc v,
rw ←list.append_assoc v,
exact lt_len,
}) at rrr_nth_le_eq_a,
have a_in_rb_rc : a_ ∈ (list.repeat b_ (n + 1) ++ list.repeat c_ (n + 1)),
{
rw ←rrr_nth_le_eq_a,
apply list.nth_le_mem,
},
rw list.mem_append at a_in_rb_rc,
cases a_in_rb_rc,
{
rw list.mem_repeat at a_in_rb_rc,
exact neq_ab a_in_rb_rc.right,
},
{
rw list.mem_repeat at a_in_rb_rc,
exact neq_ac a_in_rb_rc.right,
},
},
have z_short : z.length ≤ n,
{
have our_bound : 2 * n + 2 < (u ++ v ++ x ++ y).length,
{
have relaxed_c : c_ ∈ u ++ v ++ x ++ y,
{
cases (list.mem_append.1 hvc) with c_in_v c_in_y,
{
have c_in_uv : c_ ∈ u ++ v,
{
rw list.mem_append,
right,
exact c_in_v,
},
rw list.append_assoc,
rw list.mem_append,
left,
exact c_in_uv,
},
{
rw list.mem_append,
right,
exact c_in_y,
},
},
repeat {
rw list.append_assoc at concatenating,
},
rcases list.nth_le_of_mem relaxed_c with ⟨m, hm, mth_is_c⟩,
have m_big : m ≥ 2 * n + 2,
{
have orig_mth_is_c :
∃ proofoo,
((list.repeat a_ (n + 1) ++ list.repeat b_ (n + 1)) ++ list.repeat c_ (n + 1)).nth_le
m proofoo =
c_,
{
repeat {
rw ←list.append_assoc at concatenating,
},
rw concatenating,
have m_small : m < (u ++ v ++ x ++ y ++ z).length,
{
rw list.length_append,
linarith,
},
rw ←@list.nth_le_append _ _ z m m_small at mth_is_c,
use m_small,
exact mth_is_c,
},
cases orig_mth_is_c with trash mth_is_c,
by_contradiction mle,
push_neg at mle,
have m_lt_len : m < (list.repeat a_ (n + 1) ++ list.repeat b_ (n + 1)).length,
{
rw list.length_append,
rw list.length_repeat,
rw list.length_repeat,
ring_nf,
exact mle,
},
rw list.nth_le_append _ m_lt_len at mth_is_c,
{
have c_in_ra_rb : c_ ∈ (list.repeat a_ (n + 1) ++ list.repeat b_ (n + 1)),
{
rw ←mth_is_c,
apply list.nth_le_mem,
},
rw list.mem_append at c_in_ra_rb,
cases c_in_ra_rb with c_in_ra c_in_rb,
{
rw list.mem_repeat at c_in_ra,
exact neq_ca c_in_ra.right,
},
{
rw list.mem_repeat at c_in_rb,
exact neq_cb c_in_rb.right,
},
},
},
linarith,
},
rw ←list.length_append at total_length_exactly,
rw ←list.append_assoc at total_length_exactly,
rw ←list.append_assoc at total_length_exactly,
linarith,
},
linarith,
},
exact not_le_of_gt vxy_long vxy_short,
},
have counts_ab : ∀ w ∈ lang_eq_eq, list.count_in w a_ = list.count_in w b_,
{
intros w w_in,
cases w_in with w_n w_prop,
rw w_prop,
repeat {
rw list.count_in_append,
},
rw list.count_in_repeat_neq neq_ab,
rw list.count_in_repeat_neq neq_ba,
rw list.count_in_repeat_neq neq_ca,
rw list.count_in_repeat_neq neq_cb,
rw list.count_in_repeat_eq a_,
rw list.count_in_repeat_eq b_,
repeat {
rw add_zero,
},
rw zero_add,
},
have counts_ac : ∀ w ∈ lang_eq_eq, list.count_in w a_ = list.count_in w c_,
{
intros w w_in,
cases w_in with w_n w_prop,
rw w_prop,
repeat {
rw list.count_in_append,
},
rw list.count_in_repeat_neq neq_ac,
rw list.count_in_repeat_neq neq_ca,
rw list.count_in_repeat_neq neq_ba,
rw list.count_in_repeat_neq neq_bc,
rw list.count_in_repeat_eq a_,
rw list.count_in_repeat_eq c_,
repeat {
rw add_zero,
},
rw zero_add,
},
have counts_bc : ∀ w ∈ lang_eq_eq, list.count_in w b_ = list.count_in w c_,
{
intros w w_in,
rw ←counts_ab w w_in,
exact counts_ac w w_in,
},
have counts_ba : ∀ w ∈ lang_eq_eq, list.count_in w b_ = list.count_in w a_,
{
intros w w_in,
symmetry,
exact counts_ab w w_in,
},
have counts_ca : ∀ w ∈ lang_eq_eq, list.count_in w c_ = list.count_in w a_,
{
intros w w_in,
symmetry,
exact counts_ac w w_in,
},
have counts_cb : ∀ w ∈ lang_eq_eq, list.count_in w c_ = list.count_in w b_,
{
intros w w_in,
symmetry,
exact counts_bc w w_in,
},
have counted_letter : ∀ s,
list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) s =
list.count_in (list.repeat a_ (n+1)) s + list.count_in (list.repeat b_ (n+1)) s +
list.count_in (list.repeat c_ (n+1)) s + list.count_in (v ++ y) s,
{
intro s,
rw ←concatenating,
repeat {
rw list.count_in_append,
},
},
have counted_a : list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) a_ = n + 1 + list.count_in (v ++ y) a_,
{
rw counted_letter,
rw list.count_in_repeat_eq a_,
rw list.count_in_repeat_neq neq_ba,
rw list.count_in_repeat_neq neq_ca,
},
have counted_b : list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) b_ = n + 1 + list.count_in (v ++ y) b_,
{
rw counted_letter,
rw list.count_in_repeat_eq b_,
rw list.count_in_repeat_neq neq_cb,
rw list.count_in_repeat_neq neq_ab,
rw zero_add,
},
have counted_c : list.count_in (u ++ v ++ x ++ y ++ z ++ (v ++ y)) c_ = n + 1 + list.count_in (v ++ y) c_,
{
rw counted_letter,
rw list.count_in_repeat_eq c_,
rw list.count_in_repeat_neq neq_ac,
rw list.count_in_repeat_neq neq_bc,
rw zero_add,
},
have elimin_abc : ∀ s : fin 3, s ≠ a_ → s ≠ b_ → s ≠ c_ → false,
{
intros s hsa hsb hsc,
fin_cases s,
{
rw a_ at hsa,
exact hsa rfl,
},
{
rw b_ at hsb,
exact hsb rfl,
},
{
rw c_ at hsc,
exact hsc rfl,
},
},
cases not_all_letters with no_a foo,
{
exact false_of_uvvxyyz elimin_abc no_a nonempty counts_ab counts_ac
counted_a counted_b counted_c pumping,
},
cases foo with no_b no_c,
{
have elimin_bca : ∀ s : fin 3, s ≠ b_ → s ≠ c_ → s ≠ a_ → false,
{
intros s hsb hsc hsa,
exact elimin_abc s hsa hsb hsc,
},
exact false_of_uvvxyyz elimin_bca no_b nonempty counts_bc counts_ba
counted_b counted_c counted_a pumping,
},
{
have elimin_cab : ∀ s : fin 3, s ≠ c_ → s ≠ a_ → s ≠ b_ → false,
{
intros s hsc hsa hsb,
exact elimin_abc s hsa hsb hsc,
},
exact false_of_uvvxyyz elimin_cab no_c nonempty counts_ca counts_cb
counted_c counted_a counted_b pumping,
},
end
end not_CF
section yes_CF
private def lang_aux_ab : language (fin 3) :=
λ w, ∃ n : ℕ, w = list.repeat a_ n ++ list.repeat b_ n
private lemma CF_lang_aux_ab : is_CF lang_aux_ab :=
begin
let S_ : fin 1 := 0,
let S : symbol (fin 3) (fin 1) := symbol.nonterminal S_,
let g := CF_grammar.mk
(fin 1)
S_
[
(S_, [a, S, b]),
(S_, ([] : list (symbol (fin 3) (fin 1))))
],
use g,
apply set.eq_of_subset_of_subset,
{
intros w ass,
change CF_derives g [S] (list.map symbol.terminal w) at ass,
have indu :
∀ v : list (symbol (fin 3) (fin 1)),
CF_derives g [S] v →
∃ n : ℕ,
v = list.repeat a n ++ list.repeat b n ∨
v = list.repeat a n ++ [S] ++ list.repeat b n,
{
intros v hyp,
induction hyp with u u' trash orig hyp_ih,
{
use 0,
right,
refl,
},
rcases orig with ⟨r, rin, p, q, bef, aft⟩,
cases hyp_ih with k ih,
cases ih,
{
exfalso,
rw ih at bef,
have yes_in : symbol.nonterminal r.fst ∈ p ++ [symbol.nonterminal r.fst] ++ q,
{
apply list.mem_append_left,
apply list.mem_append_right,
apply list.mem_cons_self,
},
have not_in : symbol.nonterminal r.fst ∉ list.repeat a k ++ list.repeat b k,
{
rw list.mem_append_eq,
push_neg,
split;
{
rw list.mem_repeat,
push_neg,
intro trash,
apply symbol.no_confusion,
},
},
rw bef at not_in,
exact not_in yes_in,
},
have both_rule_rewrite_S : symbol.nonterminal r.fst = S,
{
cases rin,
{
rw rin,
},
cases rin,
{
rw rin,
},
cases rin,
},
rw bef at ih,
rw both_rule_rewrite_S at ih,
have p_len : p.length = k,
{
by_contradiction contra,
have kth_eq := congr_fun (congr_arg list.nth ih) p.length,
have plengthth_is_S : (p ++ [S] ++ q).nth p.length = some S,
{
rw list.append_assoc,
rw list.nth_append_right (le_of_eq rfl),
{
rw nat.sub_self,
refl,
},
},
rw plengthth_is_S at kth_eq,
cases lt_or_gt_of_ne contra,
{
have plengthth_is_a :
(list.repeat a k ++ [S] ++ list.repeat b k).nth p.length =
some a,
{
rw list.append_assoc,
have plength_small : p.length < (list.repeat a k).length,
{
rw list.length_repeat,
exact h,
},
rw list.nth_append plength_small,
rw list.nth_le_nth plength_small,
apply congr_arg,
exact list.nth_le_repeat a plength_small,
},
rw plengthth_is_a at kth_eq,
have S_neq_a : S ≠ a,
{
apply symbol.no_confusion,
},
rw option.some_inj at kth_eq,
exact S_neq_a kth_eq,
},
{
have plengthth_is_b :
(list.repeat a k ++ [S] ++ list.repeat b k).nth p.length =
some b,
{
have plength_big : (list.repeat a k ++ [S]).length ≤ p.length,
{
rw list.length_append,
rw list.length_repeat,
exact nat.succ_le_iff.mpr h,
},
rw list.nth_append_right plength_big,
have len_within_list : p.length - (list.repeat a k ++ [S]).length < (list.repeat b k).length,
{
have ihlen := congr_arg list.length ih,
simp only [list.length_repeat, list.length_append, list.length_singleton] at *,
have ihlen' : p.length + 1 ≤ k + 1 + k,
{
exact nat.le.intro ihlen,
},
have ihlen'' : p.length < k + 1 + k,
{
exact nat.succ_le_iff.mp ihlen',
},
rw ←tsub_lt_iff_left plength_big at ihlen'',
exact ihlen'',
},
rw list.nth_le_nth len_within_list,
apply congr_arg,
exact list.nth_le_repeat b len_within_list,
},
rw plengthth_is_b at kth_eq,
have S_neq_b : S ≠ b,
{
apply symbol.no_confusion,
},
rw option.some_inj at kth_eq,
exact S_neq_b kth_eq,
},
},
have ihl_len : (p ++ [symbol.nonterminal S_]).length = k + 1,
{
rw list.length_append,
rw p_len,
refl,
},
have ihr_len : (list.repeat a k ++ [S]).length = k + 1,
{
rw list.length_append,
rw list.length_repeat,
refl,
},
have qb : q = list.repeat b k,
{
apply list.append_inj_right ih,
rw ihl_len,
rw ihr_len,
},
have ih_reduced : p ++ [symbol.nonterminal S_] = list.repeat a k ++ [S],
{
rw qb at ih,
rw list.append_left_inj at ih,
exact ih,
},
have pa : p = list.repeat a k,
{
rw list.append_left_inj at ih_reduced,
exact ih_reduced,
},
cases rin,
{
use k + 1,
right,
rw aft,
rw rin,
convert_to
p ++ (S_, [a, S, b]).snd ++ q =
list.repeat a k ++ [a] ++ [S] ++ [b] ++ list.repeat b k,
{
rw list.repeat_add,
rw add_comm,
rw list.repeat_add,
simp only [list.repeat, list.append_assoc],
},
rw [pa, qb],
simp only [list.append_assoc, list.cons_append, list.singleton_append],
},
cases rin,
{
use k,
left,
rw aft,
rw rin,
rw list.append_nil,
rw [pa, qb],
},
exfalso,
exact rin,
},
cases indu (list.map symbol.terminal w) ass with n instantiated,
clear indu,
cases instantiated,
{
use n,
have foo := congr_arg (list.filter_map (
λ z : symbol (fin 3) (fin 1),
match z with
| symbol.terminal t := some t
| symbol.nonterminal _ := none
end
)) instantiated,
rw list.filter_map_append at foo,
rw list.filter_map_map at foo,
rw list.filter_map_some at foo,
rw [foo, a, b],
clear foo,
apply congr_arg2;
{
clear instantiated,
induction n with n ih,
{
refl,
},
rw list.repeat_succ,
rw list.repeat_succ,
rw list.filter_map_cons,
simp only [eq_self_iff_true, true_and, ih],
},
},
exfalso,
have yes_in : S ∈ list.repeat a n ++ [S] ++ list.repeat b n,
{
apply list.mem_append_left,
apply list.mem_append_right,
apply list.mem_cons_self,
},
have not_in : S ∉ list.map symbol.terminal w,
{
intro hyp,
have S_isnt_terminal : ¬ ∃ x, S = symbol.terminal x,
{
tauto,
},
rw list.mem_map at hyp,
cases hyp with y hypo,
push_neg at S_isnt_terminal,
exact S_isnt_terminal y hypo.right.symm,
},
rw instantiated at not_in,
exact not_in yes_in,
},
{
intros w ass,
cases ass with n hw,
change CF_derives g [symbol.nonterminal g.initial] (list.map symbol.terminal w),
rw [hw, list.map_append, list.map_repeat, list.map_repeat, ←a, ←b],
clear hw,
induction n with n ih,
{
convert_to CF_derives g [symbol.nonterminal g.initial] [],
apply CF_deri_of_tran,
use (S_, ([] : list (symbol (fin 3) (fin 1)))),
split_ile,
use [[], []],
split;
refl,
},
convert_to
CF_derives g
[symbol.nonterminal g.initial]
(list.map
symbol.terminal
([a_] ++ (list.repeat a_ n ++ list.repeat b_ n) ++ [b_])
),
{
convert_to
list.repeat a (1 + n) ++ list.repeat b (n + 1) =
list.map symbol.terminal ([a_] ++ (list.repeat a_ n ++ list.repeat b_ n) ++ [b_]),
{
rw add_comm,
},
rw [
list.map_append_append,
list.map_singleton,
list.map_singleton,
list.repeat_add,
list.repeat_add,
a, b
],
simp only [list.repeat, list.append_assoc, list.map_append, list.map_repeat],
},
apply CF_deri_of_tran_deri,
{
use (S_, [a, S, b]),
split_ile,
use [[], []],
split;
refl,
},
rw list.map_append_append,
change
CF_derives g
([a] ++ [S] ++ [b])
([a] ++ list.map symbol.terminal (list.repeat a_ n ++ list.repeat b_ n) ++ [b]),
apply CF_deri_with_prefix_and_postfix,
convert ih,
rw [list.map_append, list.map_repeat, list.map_repeat, a, b],
},
end
private def lang_aux_c : language (fin 3) :=
λ w, ∃ n : ℕ, w = list.repeat c_ n
private lemma CF_lang_aux_c : is_CF lang_aux_c :=
begin
use cfg_symbol_star c_,
unfold lang_aux_c,
apply language_of_cfg_symbol_star,
end
private lemma CF_lang_eq_any : is_CF lang_eq_any :=
begin
have concatenated : lang_eq_any = lang_aux_ab * lang_aux_c,
{
ext1 w,
split,
{
rintro ⟨n, m, hnm⟩,
fconstructor,
use list.repeat a_ n ++ list.repeat b_ n,
use list.repeat c_ m,
split,
{
use n,
},
split,
{
use m,
},
exact hnm.symm,
},
{
rintro ⟨u, v, ⟨n, u_eq⟩, ⟨m, v_eq⟩, eq_w⟩,
use n,
use m,
rw [←eq_w, ←u_eq, ←v_eq],
},
},
rw concatenated,
apply CF_of_CF_c_CF,
exact and.intro CF_lang_aux_ab CF_lang_aux_c,
end
private def lang_aux_a : language (fin 3) :=
λ w, ∃ n : ℕ, w = list.repeat a_ n
private lemma CF_lang_aux_a : is_CF lang_aux_a :=
begin
use cfg_symbol_star a_,
unfold lang_aux_a,
apply language_of_cfg_symbol_star,
end
private def lang_aux_bc : language (fin 3) :=
λ w, ∃ n : ℕ, w = list.repeat b_ n ++ list.repeat c_ n
private def permut : equiv.perm (fin 3) := equiv.mk
(λ x, ite (x = 2) 0 (x + 1))
(λ x, ite (x = 0) 2 (x - 1))
(by {
intro x,
fin_cases x;
refl,
})
(by {
intro x,
fin_cases x;
refl,
})
private lemma CF_lang_aux_bc : is_CF lang_aux_bc :=
begin
have permuted : lang_aux_bc = permute_lang lang_aux_ab permut,
{
have compos : permut.to_fun ∘ permut.inv_fun = id,
{
simp,
},
ext1 w,
split;
{
intro h,
cases h with n hn,
use n,
try
{
rw hn
},
try
{
have other_case := congr_arg (list.map permut.to_fun) hn,
rw list.map_map at other_case,
rw compos at other_case,