-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathMultiply.v
1237 lines (1078 loc) · 43.3 KB
/
Multiply.v
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
From stdpp Require Import prelude finite.
From VLSM.Core Require Import VLSM PreloadedVLSM VLSMProjections Composition.
From Coq Require Import FunctionalExtensionality.
(** * Tutorial: VLSMs that Multiply
This module demonstrates some basic notions of the VLSM framework.
We define a family of VLSMs that store an integer and continually decrement it
using input messages (also integers), while a constraint is checked at each step.
The definitions and lemmas tap into concepts such as valid and constrained
traces, transitions, states, and messages.
The "doubling" VLSM has 2 as its only initial message and as output doubles
the messages it receives as input. Therefore, constrained messages are
positive even numbers ([doubling_constrained_messages]) and valid messages are
powers of 2 ([doubling_valid_messages_powers_of_2]). Similarly, the "tripling"
VLSM has 3 as its only initial message and as output triples the messages it
receives as input.
When composing the doubling and tripling VLSMs, they become more than
the sum of their parts: the free composition's valid messages are
all integers which can be decomposed as a product of powers of 2 and 3.
*)
#[local] Open Scope Z_scope.
(** ** Definition of common features of the multiplying VLSMs
The multiplying VLSMs have only one type of transition, decrementing their
state and multiplying their input message as an output.
For this reason, the [unit] type can be used as a label.
*)
Definition multiplying_label : Type := unit.
(** The state will hold an integer. *)
Definition multiplying_state : Type := Z.
(** Messages are integers. *)
Definition multiplying_message : Type := Z.
(** A VLSM Type is defined using [multiplying_state] and [multiplying_label]. *)
Definition multiplying_type : VLSMType multiplying_message :=
{|
state := multiplying_state;
label := multiplying_label;
|}.
(**
To improve readability, we explicitly define [multiply_label] as the value of
the unit type.
*)
Definition multiply_label : label multiplying_type := ().
(** The initial states of multiplying VLSMs will be positive integers. *)
Definition multiplying_initial_state_prop (st : multiplying_state) : Prop :=
st >= 1.
(**
We must also provide a proof that the intial state type
is inhabited as the set of initial states is non-empty.
*)
Definition multiplying_initial_state_type : Type :=
{st : multiplying_state | multiplying_initial_state_prop st}.
Program Definition multiplying_initial_state :
multiplying_initial_state_type := exist _ 1 _.
Next Obligation.
Proof. done. Defined.
#[export] Instance multiplying_initial_state_type_inhabited :
Inhabited (multiplying_initial_state_type) :=
populate (multiplying_initial_state).
(**
The transition validity predicate is also common for all multiplying VLSMs:
the message must exist, must be larger than 1, and not larger than the current state.
*)
Definition multiplying_valid
(l : multiplying_label) (st : multiplying_state) (om : option multiplying_message) : Prop :=
match om with
| Some msg => 2 <= msg <= st
| None => False
end.
(** ** Definition of the doubling VLSM
The doubling VLSM is a multiplying VLSM whose initial message is 2 and which
outputs the double of the received input, while using it to decrement the
current state; the [multiplying_valid] constraint ensures that the valid/constraines
states don't become negative.
Not that, since the transition function must be total, it must also be defined
for the case in which no input is provided, although that case will be
filtered out by the transition validity predicate.
*)
Definition doubling_transition
(l : multiplying_label) (st : multiplying_state) (om : option multiplying_message)
: multiplying_state * option multiplying_message :=
match om with
| Some j => (st - j, Some (2 * j))
| None => (st, None)
end.
(**
An intermediate representation for the VLSM is required.
It uses the previously defined specifications with the addition that it
states that 2 is the only initial message.
*)
Definition doubling_machine : VLSMMachine multiplying_type :=
{|
initial_state_prop := multiplying_initial_state_prop;
initial_message_prop := fun (ms : multiplying_message) => ms = 2;
s0 := multiplying_initial_state_type_inhabited;
transition := fun l '(st, om) => doubling_transition l st om;
valid := fun l '(st, om) => multiplying_valid l st om;
|}.
(** The definition of the doubling VLSM *)
Definition doubling_vlsm : VLSM multiplying_message :=
{|
vlsm_type := multiplying_type;
vlsm_machine := doubling_machine;
|}.
(** *** Doubling VLSM examples *)
(** **** Example of an arbitrary transition *)
Lemma doubling_example_transition_1 `(X : VLSM multiplying_message) :
transition doubling_vlsm multiply_label (4, Some 10) = (-6, Some 20).
Proof. done. Qed.
(** **** Example of a valid trace *)
(** The initial state cannot be included to this definition, because, since there is no
transition reaching this state, it cannot be expressed in the below manner
Regarding the transition which leads to the final state, it technically could be
included, but we choose to model this way, in order to be consistent
with the subsequent example, where adding the last transition makes a qualitative
difference to the trace
*)
Definition doubling_trace1_init : list (transition_item doubling_vlsm) :=
[ Build_transition_item multiply_label (Some 4)
4 (Some 8)
; Build_transition_item multiply_label (Some 2)
2 (Some 4) ].
Definition doubling_trace1_last_item : transition_item doubling_vlsm :=
Build_transition_item multiply_label (Some 2)
0 (Some 4).
Definition doubling_trace1 : list (transition_item doubling_vlsm) :=
doubling_trace1_init ++ [doubling_trace1_last_item].
Definition doubling_trace1_first_state : multiplying_state := 8.
Definition doubling_trace1_last_state : multiplying_state :=
destination doubling_trace1_last_item.
(** Defined trace is valid: *)
Example doubling_valid_message_prop_2 : valid_message_prop doubling_vlsm 2.
Proof. by apply initial_message_is_valid. Qed.
Example doubling_can_emit_4 : can_emit doubling_vlsm 4.
Proof.
exists (2, Some 2), multiply_label, 0.
repeat split; [| | by lia.. | by cbn; do 2 f_equal; lia].
- by apply initial_state_is_valid; cbn; unfold multiplying_initial_state_prop; lia.
- by app_valid_tran.
Qed.
Example doubling_valid_message_prop_4 : valid_message_prop doubling_vlsm 4.
Proof.
by apply (emitted_messages_are_valid doubling_vlsm 4 doubling_can_emit_4).
Qed.
Proposition doubling_valid_transition_1 :
input_valid_transition doubling_vlsm multiply_label (8, Some 4) (4, Some 8).
Proof.
repeat split; [| | | by lia].
- by apply initial_state_is_valid; cbn;
unfold multiplying_initial_state_prop, doubling_trace1_first_state; lia.
- by apply doubling_valid_message_prop_4.
- by unfold doubling_trace1_first_state; nia.
Qed.
Proposition doubling_valid_transition_2 :
input_valid_transition doubling_vlsm multiply_label (4, Some 2) (2, Some 4).
Proof.
repeat split; [| | by lia..].
- by app_valid_tran; eapply doubling_valid_transition_1; lia.
- by apply doubling_valid_message_prop_2.
Qed.
Proposition doubling_valid_transition_3 :
input_valid_transition doubling_vlsm multiply_label (2, Some 2) (0, Some 4).
Proof.
repeat split; [| | by lia..].
- by app_valid_tran; apply doubling_valid_transition_2.
- by apply doubling_valid_message_prop_2.
Qed.
Example doubling_valid_trace1 :
finite_valid_trace_init_to doubling_vlsm
doubling_trace1_first_state doubling_trace1_last_state doubling_trace1.
Proof.
constructor; [| done].
repeat apply finite_valid_trace_from_to_extend.
- by eapply finite_valid_trace_from_to_empty,
input_valid_transition_destination, doubling_valid_transition_3.
- by apply doubling_valid_transition_3.
- by apply doubling_valid_transition_2.
- by apply doubling_valid_transition_1.
Qed.
Example doubling_valid_trace1_alt :
finite_valid_trace_init_to_alt doubling_vlsm
doubling_trace1_first_state doubling_trace1_last_state doubling_trace1.
Proof.
constructor; [| done].
by repeat apply mvt_extend; [.. | apply mvt_empty]; try done;
[apply doubling_valid_message_prop_4 | apply doubling_valid_message_prop_2 ..].
Qed.
(** **** Example of a constrained trace *)
(** Previously defined trace is obviously constrained, since it's valid *)
Lemma doubling_constrained_trace1 :
finite_constrained_trace_init_to_direct doubling_vlsm
doubling_trace1_first_state doubling_trace1_last_state doubling_trace1.
Proof.
constructor; [| done].
by repeat apply ct_extend; [.. | apply ct_empty].
Qed.
Definition doubling_trace2_init : list (transition_item doubling_vlsm) :=
[ Build_transition_item multiply_label (Some 2) 5 (Some 4)
; Build_transition_item multiply_label (Some 2) 3 (Some 4) ].
Definition doubling_trace2_last_item : transition_item doubling_vlsm :=
Build_transition_item multiply_label (Some 3) 0 (Some 6).
Definition doubling_trace2 : list (transition_item doubling_vlsm) :=
doubling_trace2_init ++ [doubling_trace2_last_item].
Definition doubling_trace2_init_first_state : multiplying_state := 7.
Definition doubling_trace2_init_last_state : multiplying_state := 3.
Definition doubling_trace2_last_state : multiplying_state :=
destination doubling_trace2_last_item.
(** The given trace is valid without the last transition. *)
Proposition doubling_valid_transition_1' :
input_valid_transition doubling_vlsm multiply_label
(doubling_trace2_init_first_state, Some 2) (5, Some 4).
Proof. by app_valid_tran. Qed.
Proposition doubling_valid_transition_2' :
input_valid_transition doubling_vlsm multiply_label
(5, Some 2) (3, Some 4).
Proof. by app_valid_tran; apply doubling_valid_transition_1'. Qed.
Example doubling_valid_trace2_init :
finite_valid_trace_init_to doubling_vlsm
doubling_trace2_init_first_state doubling_trace2_init_last_state doubling_trace2_init.
Proof.
constructor; [| done].
repeat apply finite_valid_trace_from_to_extend.
- by eapply finite_valid_trace_from_to_empty,
input_valid_transition_destination, doubling_valid_transition_2'.
- by apply doubling_valid_transition_2'.
- by apply doubling_valid_transition_1'.
Qed.
Example doubling_valid_trace2_init_alt :
finite_valid_trace_init_to_alt doubling_vlsm
doubling_trace2_init_first_state doubling_trace2_init_last_state doubling_trace2_init.
Proof.
constructor; [| done].
by repeat apply mvt_extend; [..| apply mvt_empty]; try done;
apply doubling_valid_message_prop_2.
Qed.
(**
From the previous lemmas, it follows that the given trace
without its last transition is constrained.
*)
Example doubling_constrained_trace2_init :
finite_constrained_trace_init_to doubling_vlsm
doubling_trace2_init_first_state doubling_trace2_init_last_state doubling_trace2_init.
Proof.
apply VLSM_incl_finite_valid_trace_init_to.
- by apply vlsm_incl_preloaded.
- by apply doubling_valid_trace2_init.
Qed.
(**
The trace is valid (in the preloaded doubling VLSM) without
its last element and appending it to the end also gives
a valid trace (in the preloaded doubling VLSM).
It follows that the full trace is constrained in
the original doubling VLSM.
*)
Example doubling_constrained_trace2 :
finite_constrained_trace_init_to doubling_vlsm
doubling_trace2_init_first_state doubling_trace2_last_state doubling_trace2.
Proof.
destruct doubling_constrained_trace2_init.
split; [| done].
eapply (extend_right_finite_trace_from_to (preloaded_with_all_messages_vlsm doubling_vlsm));
[done |].
repeat split; [| | done..].
- by eapply finite_valid_trace_from_to_last_pstate.
- by apply any_message_is_valid_in_preloaded.
Qed.
(** **** Example of a valid transition
The last transition of a valid trace is valid.
*)
Lemma doubling_example_valid_transition :
input_valid_transition doubling_vlsm multiply_label
(2, Some 2) (0, Some 4).
Proof.
apply (finite_valid_trace_from_to_last_transition doubling_vlsm
doubling_trace1_first_state doubling_trace1_last_state
doubling_trace1_init doubling_trace1 doubling_trace1_last_item); [| done].
by apply doubling_valid_trace1.
Qed.
(** **** Example of a constrained transition
The last transition of a constrained trace is constrained.
*)
Example doubling_example_constrained_transition :
input_constrained_transition doubling_vlsm multiply_label
(3, Some 3) (0, Some 6).
Proof.
apply (finite_valid_trace_from_to_last_transition
(preloaded_with_all_messages_vlsm doubling_vlsm)
doubling_trace2_init_first_state doubling_trace2_last_state doubling_trace2_init
doubling_trace2 doubling_trace2_last_item); [| done].
by apply doubling_constrained_trace2.
Qed.
(** *** Doubling VLSM properties *)
(** **** Inclusion into preloaded with all messages *)
Lemma doubling_valid_is_constrained :
VLSM_incl doubling_vlsm (preloaded_with_all_messages_vlsm doubling_vlsm).
Proof.
by apply vlsm_incl_preloaded_with_all_messages_vlsm.
Qed.
(** *** Constrained messages are positive even integers *)
Lemma doubling_constrained_messages_left :
forall (m : multiplying_message), constrained_message_prop doubling_vlsm m ->
Z.Even m /\ m >= 4.
Proof.
intros m ([s []] & [] & s' & (_ & _ & []) & Ht).
inversion Ht; subst.
by split; [eexists | lia].
Qed.
Lemma doubling_constrained_messages_right :
forall (m : multiplying_message), Z.Even m -> m >= 4 ->
constrained_message_prop doubling_vlsm m.
Proof.
intros m [n ->] Hmgt0.
exists (n, Some n), multiply_label, 0.
repeat split; [| | by lia.. | by cbn; do 2 f_equal; lia].
- apply initial_state_is_valid; cbn; red; lia.
- by apply any_message_is_valid_in_preloaded.
Qed.
Lemma doubling_constrained_messages :
forall (m : multiplying_message),
constrained_message_prop doubling_vlsm m <-> (Z.Even m /\ m >= 4).
Proof.
split.
- by apply doubling_constrained_messages_left.
- by intros [? ?]; apply doubling_constrained_messages_right.
Qed.
(** *** Constrained states property *)
Lemma doubling_constrained_states_right :
forall (st : multiplying_state),
constrained_state_prop doubling_vlsm st ->
st >= 0.
Proof.
induction 1 using valid_state_prop_ind.
- cbn in Hs; red in Hs; lia.
- destruct l, om, Ht as [(Hs & _ & []) Ht].
by inversion Ht; subst; cbn in *; lia.
Qed.
Lemma doubling_constrained_states_left :
forall (st : multiplying_state), st >= 0 ->
constrained_state_prop doubling_vlsm st.
Proof.
intros st Hst.
apply input_valid_transition_destination
with (l := multiply_label) (s := st + 2) (om := Some 2) (om' := Some 4).
repeat split; [| | by lia.. | by cbn; do 2 f_equal; lia].
- apply initial_state_is_valid; cbn; red; lia.
- by apply any_message_is_valid_in_preloaded.
Qed.
Lemma doubling_constrained_states :
forall (st : multiplying_state),
constrained_state_prop doubling_vlsm st <-> st >= 0.
Proof.
split.
- by apply doubling_constrained_states_right.
- by apply doubling_constrained_states_left.
Qed.
(** *** Powers of 2 greater than or equal to 2 are valid messages *)
Lemma doubling_valid_messages_powers_of_2_right :
forall (m : multiplying_message),
valid_message_prop doubling_vlsm m ->
exists p : Z, p >= 1 /\ m = 2 ^ p.
Proof.
intros m [s Hvsm].
assert (Hom : is_Some (Some m)) by (eexists; done).
replace m with (is_Some_proj Hom) by done.
revert Hvsm Hom; generalize (Some m) as om; intros.
clear m; induction Hvsm using valid_state_message_prop_ind.
- destruct Hom as [m ->]; cbn in *; subst.
by exists 1; split; lia.
- destruct om as [m |]; [| done].
unshelve edestruct IHHvsm2 as [x Hx]; [done |].
inversion Ht; subst; clear Ht.
cbn in Hx |- *; destruct Hx as [Hgeq1 ->].
exists (x + 1).
split; [by lia |].
by rewrite <- Z.pow_succ_r; [| lia].
Qed.
Lemma doubling_valid_messages_powers_of_2_left :
forall (p : Z),
p >= 1 -> valid_message_prop doubling_vlsm (2 ^ p).
Proof.
intros p Hp.
assert (Hle : 0 <= p - 1) by lia.
replace p with (p - 1 + 1) by lia.
remember (p - 1) as x.
clear p Hp Heqx.
revert x Hle.
apply natlike_ind; [by apply initial_message_is_valid; cbn; lia |].
intros x Hxgt0 Hindh.
apply emitted_messages_are_valid.
exists (2 ^ (x + 1), Some (2 ^ (x + 1))), multiply_label, 0.
repeat split.
- by apply initial_state_is_valid; cbn; red; lia.
- by apply Hindh.
- replace (x + 1) with (Z.succ x) by lia.
by rewrite Z.pow_succ_r; lia.
- by lia.
- by cbn; rewrite <- Z.pow_succ_r, Z.add_succ_l; [do 2 f_equal; lia | lia].
Qed.
Lemma doubling_valid_messages_powers_of_2 : forall (m : multiplying_message),
valid_message_prop doubling_vlsm m <->
exists p : Z, p >= 1 /\ m = 2 ^ p.
Proof.
split.
- by intros; apply doubling_valid_messages_powers_of_2_right.
- by intros (p & Hpgt0 & [= ->]); apply doubling_valid_messages_powers_of_2_left.
Qed.
(**
The constrained transition from [doubling_example_constrained_transition]
is not also valid.
*)
Example doubling_example_constrained_transition_not_valid :
~ input_valid_transition doubling_vlsm multiply_label
(3, Some 3) (0, Some 6).
Proof.
intros [(_ & Hm & _) _].
apply doubling_valid_messages_powers_of_2 in Hm as (p & Hp & Heq).
rewrite <- (Z.succ_pred p) in Heq.
by rewrite Z.pow_succ_r in Heq; lia.
Qed.
(** **** Valid states hold non-negative integers *)
Lemma doubling_valid_states_right (s : multiplying_state) :
valid_state_prop doubling_vlsm s -> s >= 0.
Proof.
induction 1 using valid_state_prop_ind;
[by cbn in Hs; red in Hs; lia |].
destruct om, l, Ht as [(Hs & Hm & Hv) Ht]; [| done].
inversion Ht; subst.
by destruct Hv; lia.
Qed.
Lemma doubling_valid_states_left (s : multiplying_state) :
s >= 0 -> valid_state_prop doubling_vlsm s.
Proof.
intro.
destruct (decide (s = 0)) as [-> |];
[| by apply initial_state_is_valid; cbn; red; lia].
apply input_valid_transition_destination
with (l := multiply_label) (s := 2) (om := Some 2) (om' := Some 4).
repeat split; cbn; [| | by lia..].
- by apply initial_state_is_valid; cbn; red; lia.
- by apply initial_message_is_valid.
Qed.
Lemma doubling_valid_states :
forall (s : multiplying_state),
valid_state_prop doubling_vlsm s <-> s >= 0.
Proof.
split.
- by apply doubling_valid_states_right.
- by apply doubling_valid_states_left.
Qed.
(** ** Definition of the tripling VLSM
Similarly to the doubling VLSM, the tripling VLSM is a multiplying VLSM,
differing only by the fact that its initial message is 3 and that it
outputs the triple of the received input.
It can be shown that its constrained messages are multiples of three and that
its valid messages are powers of three, but the proofs will be similar to
those for the doubling VLSM so we will omit them. The development in module
[PrimesComposition] will make the results for the doubling and tripling VLSM be
particular instances of more general results.
*)
Definition tripling_transition
(l : multiplying_label) (st : multiplying_state) (om : option multiplying_message)
: multiplying_state * option multiplying_message :=
match om with
| Some j => (st - j, Some (3 * j))
| None => (st, None)
end.
Definition tripling_machine : VLSMMachine multiplying_type :=
{|
initial_state_prop := multiplying_initial_state_prop;
initial_message_prop := fun (ms : multiplying_message) => ms = 3;
s0 := multiplying_initial_state_type_inhabited;
transition := fun l '(st, om) => tripling_transition l st om;
valid := fun l '(st, om) => multiplying_valid l st om;
|}.
Definition tripling_vlsm : VLSM multiplying_message := mk_vlsm tripling_machine.
(** ** Composition of doubling and tripling VLSMs *)
Section sec_23_composition.
(**
Since our notion of [composite_vlsm] is based on an indexed set of components,
we need to define a base index type
*)
Inductive index23 := two | three.
#[local] Instance eq_dec_index23 : EqDecision index23.
Proof. by intros x y; unfold Decision; decide equality. Qed.
Definition components_23 (i : index23) : VLSM multiplying_message :=
match i with
| two => doubling_vlsm
| three => tripling_vlsm
end.
(** We define a helper function to make composite state easier to write. *)
Definition state_23 (n m : Z) : composite_state components_23 :=
fun (i : index23) => match i with two => n | three => m end.
Definition state00 := state_23 0 0.
Definition state01 := state_23 0 1.
Definition state10 := state_23 1 0.
Definition state11 := state_23 1 1.
Definition state12 := state_23 1 2.
Definition state21 := state_23 2 1.
Definition state22 := state_23 2 2.
Definition state02 := state_23 0 2.
Definition zproj (s : composite_state components_23) (i : index23) : Z :=
match i with
| two => s two
| three => s three
end.
Definition free_composition_23 : VLSM multiplying_message :=
free_composite_vlsm components_23.
Lemma composition_23_2_initial :
composite_initial_message_prop components_23 2.
Proof.
by exists two; unshelve eexists (exist _ 2 _); cbn; lia.
Qed.
Lemma composition_23_3_initial :
composite_initial_message_prop components_23 3.
Proof.
by exists three; unshelve eexists (exist _ 3 _); cbn; lia.
Qed.
Lemma free_composition_23_valid_messages_powers_of_23_right :
forall (m : multiplying_message),
valid_message_prop free_composition_23 m ->
exists p2 p3 : Z, p2 >= 0 /\ p3 >= 0 /\ p2 + p3 >= 1 /\
m = 2 ^ p2 * 3 ^ p3.
Proof.
intros m [s Hvsm].
assert (Hom : is_Some (Some m)) by (eexists; done).
replace m with (is_Some_proj Hom) by done.
revert Hvsm Hom; generalize (Some m) as om; intros.
clear m; induction Hvsm using valid_state_message_prop_ind.
- destruct Hom as [m ->]; cbn in *; subst.
destruct Hom0 as ([] & [] & <-); cbn in *.
+ by exists 1, 0; split; lia.
+ by exists 0, 1; split; lia.
- destruct l as [[] []];
(destruct om as [m |]; [| done]);
(unshelve edestruct IHHvsm2 as (p2 & p3 & Hgt1 & Heq); [done |]);
cbn in *; inversion Ht; subst; cbn in *.
+ exists (Z.succ p2), p3.
split; [by lia |].
by rewrite Z.pow_succ_r; lia.
+ exists p2, (Z.succ p3).
split; [by lia |].
by rewrite Z.pow_succ_r; lia.
Qed.
Lemma free_composition_23_valid_messages_powers_of_23_left :
forall (p2 p3 : Z), p2 >= 0 -> p3 >= 0 -> 1 <= p2 + p3 ->
valid_message_prop free_composition_23 (2 ^ p2 * 3 ^ p3).
Proof.
intros p2 p3 Hp2 Hp3 Hp.
remember (p2 + p3) as p.
revert p2 p3 Hp2 Hp3 Heqp.
pose (P (p : Z) := forall (p2 p3 : Z), p2 >= 0 -> p3 >= 0 -> p = p2 + p3 ->
valid_message_prop free_composition_23 (2 ^ p2 * 3 ^ p3)).
cut (P p); [done |].
revert p Hp; apply Zlt_lower_bound_ind; subst P; cbn.
intros p Hind Hp p2 p3 Hp2 Hp3 ->.
destruct (decide (p2 = 0)) as [-> |], (decide (p3 = 0)) as [-> |];
[by lia |..].
- destruct (decide (p3 = 1)) as [-> |];
[by apply initial_message_is_valid, composition_23_3_initial |].
apply emitted_messages_are_valid.
exists (state_23 1 (3 ^ (p3 - 1)), Some (3 ^ (p3 - 1))),
(existT three multiply_label), state10.
repeat split.
+ by apply initial_state_is_valid; intros []; cbn; red; lia.
+ replace (3 ^ (p3 - 1)) with (2 ^ 0 * 3 ^ (p3 - 1)) by lia.
by eapply Hind; cycle 3; [done | lia..].
+ replace (p3 - 1) with (Z.succ (p3 - 2)) by lia.
by rewrite Z.pow_succ_r; lia.
+ by cbn; lia.
+ cbn; f_equal.
* by extensionality i; destruct i; state_update_simpl; cbn; lia.
* replace p3 with (Z.succ (p3 - 1)) at 2 by lia.
by f_equal; rewrite Z.pow_succ_r; lia.
- destruct (decide (p2 = 1)) as [-> |];
[by apply initial_message_is_valid, composition_23_2_initial |].
apply emitted_messages_are_valid.
exists (state_23 (2 ^ (p2 - 1)) 1, Some (2 ^ (p2 - 1))),
(existT two multiply_label), state01.
repeat split.
+ by apply initial_state_is_valid; intros []; cbn; red; lia.
+ replace (2 ^ (p2 - 1)) with (2 ^ (p2 - 1) * 3 ^ 0)
by lia.
by eapply Hind; cycle 3; [done | lia..].
+ replace (p2 - 1) with (Z.succ (p2 - 2)) by lia.
by rewrite Z.pow_succ_r; lia.
+ by cbn; lia.
+ cbn; f_equal.
* by extensionality i; destruct i; state_update_simpl; cbn; lia.
* replace p2 with (Z.succ (p2 - 1)) at 2 by lia.
by f_equal; rewrite Z.pow_succ_r; lia.
- apply emitted_messages_are_valid.
exists
(state_23 (2 ^ (p2 - 1) * 3 ^ p3) 1, Some (2 ^ (p2 - 1) * 3 ^ p3)),
(existT two multiply_label), state01.
repeat split.
+ by apply initial_state_is_valid; intros []; cbn; red; lia.
+ by eapply Hind; cycle 3; [done | lia..].
+ replace p3 with (Z.succ (p3 - 1)) by lia.
by rewrite Z.pow_succ_r; lia.
+ by cbn; lia.
+ cbn; f_equal.
* by extensionality i; destruct i; state_update_simpl; cbn; lia.
* replace p2 with (Z.succ (p2 - 1)) at 2 by lia.
by f_equal; rewrite Z.pow_succ_r; lia.
Qed.
(**
The valid messages of the [free_composition_23] VLSM consist of all integers
larger than 1 which can be decomposed as a product of powers of 2 and 3.
*)
Theorem free_composition_23_valid_messages_powers_of_23 :
forall (m : multiplying_message),
valid_message_prop free_composition_23 m <->
exists p2 p3 : Z, p2 >= 0 /\ p3 >= 0 /\ p2 + p3 >= 1 /\
m = 2 ^ p2 * 3 ^ p3.
Proof.
split.
- by apply free_composition_23_valid_messages_powers_of_23_right.
- intros (? & ? & ? & ? & ? & ->).
by eapply free_composition_23_valid_messages_powers_of_23_left; lia.
Qed.
Section sec_state_update_23_def.
Context
(s : composite_state components_23)
(i : index23)
(z : Z)
.
Definition state_update_23 (j : index23) : state (components_23 j) :=
if (decide (i = j)) then
match j with
| two => z
| three => z
end
else s j.
Lemma state_update_23_eq :
zproj state_update_23 i = z.
Proof.
by unfold state_update_23; destruct i; cbn; rewrite decide_True.
Qed.
Lemma state_update_23_neq :
forall (j : index23), j <> i -> state_update_23 j = s j.
Proof.
by intros; unfold state_update_23; rewrite decide_False.
Qed.
End sec_state_update_23_def.
Lemma state_update_23_twice :
forall (s : composite_state components_23) (i : index23) (z z' : Z),
state_update_23 (state_update_23 s i z) i z' = state_update_23 s i z'.
Proof.
by intros; extensionality j; unfold state_update_23; case_decide; subst.
Qed.
Lemma state_update_23_two (s : composite_state components_23) (z : Z) :
state_update_23 s two z = state_update components_23 s two z.
Proof.
extensionality i; destruct i; unfold state_update_23; state_update_simpl.
- by rewrite decide_True.
- by rewrite decide_False.
Qed.
Lemma state_update_23_three (s : composite_state components_23) (z : Z) :
state_update_23 s three z = state_update components_23 s three z.
Proof.
extensionality i; destruct i; unfold state_update_23; state_update_simpl.
- by rewrite decide_False.
- by rewrite decide_True.
Qed.
Definition label_23 (i : index23) : composite_label components_23.
Proof.
exists i.
by destruct i; exact ().
Defined.
Definition multiplier_23 (i : index23) : Z :=
match i with
| two => 2
| three => 3
end.
Lemma free_composition_23_reachable_0 :
forall (s : composite_state components_23),
valid_state_prop free_composition_23 s ->
forall (i : index23), 2 <= zproj s i ->
in_futures free_composition_23 s (state_update_23 s i 0).
Proof.
intros s Hs i Hi.
remember (zproj s i) as si; revert s Hs Heqsi.
pose (P (si : Z) :=
forall (s : composite_state components_23),
valid_state_prop free_composition_23 s ->
si = zproj s i ->
in_futures free_composition_23 s (state_update_23 s i 0)).
cut (P si); [done |].
revert si Hi; apply Zlt_lower_bound_ind; subst P; cbn.
intros si Hind Hlt s Hs Heqsi.
destruct (decide (4 <= si)); [| destruct (decide (si = 3))].
- pose (s' := state_update_23 s i (si - 2)).
cut (input_valid_transition free_composition_23 (label_23 i)
(s, Some 2) (s', Some (2 * multiplier_23 i))).
{
transitivity s'; [by eapply input_valid_transition_in_futures |].
replace (state_update_23 s i 0) with (state_update_23 s' i 0)
by apply state_update_23_twice.
apply (Hind (si - 2)); [by lia |..].
- by eapply input_valid_transition_destination.
- by symmetry; apply state_update_23_eq.
}
repeat split; [done |..].
+ by apply initial_message_is_valid, composition_23_2_initial.
+ by destruct i; cbn in Heqsi |- *; lia.
+ destruct i; cbn; f_equal; subst si s'; cbn; symmetry.
* by apply state_update_23_two.
* by apply state_update_23_three.
- apply input_valid_transition_in_futures
with (l := label_23 i) (im := Some 3) (om := Some (3 * multiplier_23 i)).
repeat split; [done |..].
+ by apply initial_message_is_valid, composition_23_3_initial.
+ by destruct i; cbn in Heqsi |- *; lia.
+ destruct i; cbn; f_equal; subst si; cbn in *; symmetry.
* by rewrite state_update_23_two; f_equal; lia.
* by rewrite state_update_23_three; f_equal; lia.
- apply input_valid_transition_in_futures
with (l := label_23 i) (im := Some 2) (om := Some (2 * multiplier_23 i)).
repeat split; [done |..].
+ by apply initial_message_is_valid, composition_23_2_initial.
+ by destruct i; cbn in Heqsi |- *; lia.
+ destruct i; cbn; f_equal; subst si; cbn in *; symmetry.
* by rewrite state_update_23_two; f_equal; lia.
* by rewrite state_update_23_three; f_equal; lia.
Qed.
(**
From any composite state whose components are larger than 1
there is a valid trace reaching [state00].
*)
Theorem free_composite_23_reachable_00 :
forall (s2 s3 : Z),
2 <= s2 -> 2 <= s3 ->
in_futures free_composition_23 (state_23 s2 s3) state00.
Proof.
intros.
cut (in_futures free_composition_23 (state_23 s2 s3) (state_23 0 s3)).
{
etransitivity; [done |].
replace state00 with (state_update_23 (state_23 0 s3) three 0).
- apply free_composition_23_reachable_0; [| by cbn; lia].
by eapply in_futures_valid_snd.
- extensionality i; destruct i; cbn.
+ by rewrite state_update_23_neq.
+ by rewrite state_update_23_three; state_update_simpl.
}
replace (state_23 0 s3) with (state_update_23 (state_23 s2 s3) two 0).
- apply free_composition_23_reachable_0; [| by cbn; lia].
by apply initial_state_is_valid; intros []; cbn; red; lia.
- extensionality i; destruct i; cbn.
+ by rewrite state_update_23_two; state_update_simpl.
+ by rewrite state_update_23_neq.
Qed.
Definition composite_state_23_sum (s : composite_state components_23) : Z :=
s two + s three.
Definition parity_constraint_23
(l : composite_label components_23)
(sm : composite_state components_23 * option multiplying_message) : Prop :=
let sm' := composite_transition components_23 l sm in
Z.Even (composite_state_23_sum sm.1 + composite_state_23_sum sm'.1).
Definition parity_composition_23 : VLSM multiplying_message :=
composite_vlsm components_23 parity_constraint_23.
Lemma parity_constraint_23_even
(l : composite_label components_23) (s : composite_state components_23)
(m : multiplying_message) :
parity_constraint_23 l (s, Some m) <-> Z.Even m.
Proof.
unfold parity_constraint_23, composite_state_23_sum.
by split; intros [n Hn]; destruct l as [[] li]; cbn in *; state_update_simpl;
exists (s two + s three - n); lia.
Qed.
Lemma parity_composition_23_valid_messages_powers_of_23_right :
forall (m : multiplying_message),
valid_message_prop parity_composition_23 m ->
m = 3 \/
exists p2 p3 : Z, p2 >= 1 /\ p3 >= 0 /\
m = 2 ^ p2 * 3 ^ p3.
Proof.
intros m [s Hvsm].
assert (Hom : is_Some (Some m)) by (eexists; done).
replace m with (is_Some_proj Hom) by done.
revert Hvsm Hom; generalize (Some m) as om; intros.
clear m; induction Hvsm using valid_state_message_prop_ind.
- destruct Hom as [m ->]; cbn in *; subst.
destruct Hom0 as ([] & [] & <-); cbn in *; [| by left].
by right; exists 1, 0; split; lia.
- right; destruct Hv as [Hv Hc]; unfold parity_constraint_23 in Hc.
assert (H_om : is_Some om) by (destruct l as [[] []], om; done).
destruct om as [m |]; [| by apply is_Some_None in H_om].
specialize (IHHvsm2 H_om); cbn in *.
destruct l as [[] []], IHHvsm2 as [| (p2 & p3 & Hgt1 & Heq)];
cbn in *; inversion Ht; subst; cbn in *.
+ by exists 1, 1; lia.
+ exists (Z.succ p2), p3; split; [lia |].
by rewrite Z.pow_succ_r; lia.
+ exfalso; clear -Hc.
destruct Hc as [n Hn]; unfold composite_state_23_sum in Hn.
by state_update_simpl; lia.
+ exists p2, (Z.succ p3).
split; [by lia |].
by rewrite Z.pow_succ_r; lia.
Qed.
Lemma parity_composition_23_valid_messages_powers_of_23_left :
forall (p2 p3 : Z), 1 <= p2 -> 0 <= p3 ->
valid_message_prop parity_composition_23 (2 ^ p2 * 3 ^ p3).
Proof.
intros p2 p3 Hp2; revert p3.
pose (P (p2 : Z) := forall (p3 : Z), 0 <= p3 ->
valid_message_prop parity_composition_23 (2 ^ p2 * 3 ^ p3)).
cut (P p2); [done |].
revert p2 Hp2; apply Zlt_lower_bound_ind; subst P; cbn.
intros p2 Hind Hp2.
destruct (decide (p2 = 1)) as [-> |].
- clear Hind; apply natlike_ind;
[by apply initial_message_is_valid, composition_23_2_initial |].
intros p3 Hp3 Hind.
apply emitted_messages_are_valid.
exists (state_23 1 ((2 * 3 ^ p3)), Some (2 ^ 1 * 3 ^ p3)),
(existT three multiply_label), state10.
repeat split.
+ by apply initial_state_is_valid; intros []; cbn; red; lia.
+ done.
+ by lia.
+ by cbn; lia.
+ by apply parity_constraint_23_even; exists (3 ^ p3); lia.
+ cbn; f_equal.
* by extensionality i; destruct i; state_update_simpl; cbn; lia.
* by f_equal; rewrite Z.pow_succ_r; lia.
- intros p3 Hp3.
apply emitted_messages_are_valid.
exists (state_23 (2 ^ (p2 - 1) * 3 ^ p3) 1, Some (2 ^ (p2 - 1) * 3 ^ p3)),
(existT two multiply_label), state01.
repeat split.
+ by apply initial_state_is_valid; intros []; cbn; red; lia.
+ by apply Hind; lia.
+ replace (p2 - 1) with (Z.succ (p2 - 2)) by lia.
by rewrite Z.pow_succ_r; lia.
+ by cbn; lia.
+ apply parity_constraint_23_even; exists (2 ^ (p2 - 2) * 3 ^ p3).
replace (p2 - 1) with (Z.succ (p2 - 2)) by lia.
by rewrite Z.pow_succ_r; lia.
+ cbn; f_equal.
* by extensionality i; destruct i; state_update_simpl; cbn; lia.
* replace p2 with (Z.succ (p2 - 1)) at 2 by lia.
by f_equal; rewrite !Z.pow_succ_r; lia.
Qed.
(**
The valid messages of the [parity_composition_23] VLSM consist of the initial
message 3 together with all even integers larger than 1 which can be
decomposed as a product of powers of 2 and 3.
*)
Theorem parity_composition_23_valid_messages_powers_of_23 :
forall (m : multiplying_message),
valid_message_prop parity_composition_23 m <->
m = 3 \/
exists p2 p3 : Z, p2 >= 1 /\ p3 >= 0 /\
m = 2 ^ p2 * 3 ^ p3.
Proof.
split.
- by apply parity_composition_23_valid_messages_powers_of_23_right.