Comparing BB4_Legacy_Monolith.v (original) with experiment_deobfuscated.v (AI-generated / deobfuscated).
loop1_nonhaltloop1_nonhalt'Green = AI proof shorter, Yellow = same length, Red = AI proof longer
These are intermediary lemmas introduced by the AI to structure the proofs. They do not exist in the original file.
| Name ▴▾ | Orig Lines ▴▾ | AI Lines ▴▾ | Diff ▴▾ | % Change ▴▾ | Status |
|---|---|---|---|---|---|
AES_Closed_NonHalt |
15 | 9 | -6 | -40% | AI shorter |
AES_isClosed'_correct |
102 | 72 | -30 | -29% | AI shorter |
BB4_lower_bound |
4 | 2 | -2 | -50% | AI shorter |
BB4_upperbound |
3 | 1 | -2 | -67% | AI shorter |
BB4_value |
5 | 3 | -2 | -40% | AI shorter |
CPS_correct |
7 | 4 | -3 | -43% | AI shorter |
Closed_NonHalt |
17 | 7 | -10 | -59% | AI shorter |
CountHaltTrans_0_NonHalt |
16 | 11 | -5 | -31% | AI shorter |
CountHaltTrans_upd |
5 | 12 | +7 | +140% | AI longer |
Dir_enc_inj |
2 | 1 | -1 | -50% | AI shorter |
Dir_eqb_spec |
1 | 1 | +0 | +0% | Same |
Dir_list_spec |
2 | 1 | -1 | -50% | AI shorter |
ExecState_rev_rev |
5 | 1 | -4 | -80% | AI shorter |
ExecState_swap_swap |
5 | 1 | -4 | -80% | AI shorter |
F_HaltsFromInit |
12 | 6 | -6 | -50% | AI shorter |
F_InitES |
1 | 1 | +0 | +0% | Same |
F_NonHaltsFromInit |
2 | 1 | -1 | -50% | AI shorter |
F_Steps |
13 | 11 | -2 | -15% | AI shorter |
F_step |
16 | 11 | -5 | -31% | AI shorter |
F_step_halt |
5 | 6 | +1 | +20% | AI longer |
HaltDecider_cons_spec |
5 | 3 | -2 | -40% | AI shorter |
HaltTimeUpperBound_LE_Halt |
11 | 12 | +1 | +9% | AI longer |
HaltTimeUpperBound_LE_HaltAtES_MergeUnusedState |
19 | 10 | -9 | -47% | AI shorter |
HaltTimeUpperBound_LE_HaltAtES_UnusedState_ptr |
12 | 14 | +2 | +17% | AI longer |
HaltTimeUpperBound_LE_HaltsAtES_UnusedState |
50 | 59 | +9 | +18% | AI longer |
HaltTimeUpperBound_LE_NonHalt |
5 | 3 | -2 | -40% | AI shorter |
HaltTimeUpperBound_LE_rev |
8 | 4 | -4 | -50% | AI shorter |
HaltTimeUpperBound_LE_rev_InitES |
3 | 1 | -2 | -67% | AI shorter |
HaltTimeUpperBound_LE_swap |
8 | 4 | -4 | -50% | AI shorter |
HaltTimeUpperBound_LE_swap_InitES |
3 | 1 | -2 | -67% | AI shorter |
HaltsAtES_Trans |
7 | 6 | -1 | -14% | AI shorter |
HaltsAt_rev |
5 | 4 | -1 | -20% | AI shorter |
HaltsAt_rev_0 |
11 | 4 | -7 | -64% | AI shorter |
HaltsAt_swap |
5 | 4 | -1 | -20% | AI shorter |
HaltsAt_swap_0 |
11 | 4 | -7 | -64% | AI shorter |
HaltsAt_unique |
12 | 5 | -7 | -58% | AI shorter |
In_RepWL_ES_InitES |
9 | 5 | -4 | -44% | AI shorter |
InitES_InAES_cond |
19 | 15 | -4 | -21% | AI shorter |
InitES_rev |
1 | 1 | +0 | +0% | Same |
InitES_swap |
5 | 8 | +3 | +60% | AI longer |
LE_HaltsAtES_1 |
6 | 5 | -1 | -17% | AI shorter |
LE_HaltsAtES_2 |
8 | 11 | +3 | +38% | AI longer |
LE_NonHalts |
6 | 4 | -2 | -33% | AI shorter |
LE_Steps |
6 | 3 | -3 | -50% | AI shorter |
LE_rev |
5 | 3 | -2 | -40% | AI shorter |
LE_rev_0 |
5 | 4 | -1 | -20% | AI shorter |
LE_step |
7 | 5 | -2 | -29% | AI shorter |
LE_swap |
5 | 3 | -2 | -40% | AI shorter |
LE_swap_0 |
5 | 4 | -1 | -20% | AI shorter |
ListES_Steps_spec |
19 | 16 | -3 | -16% | AI shorter |
ListES_step'_spec |
3 | 93 | +90 | +3000% | AI longer |
ListES_step_spec |
66 | 94 | +28 | +42% | AI longer |
ListES_toES_O |
12 | 6 | -6 | -50% | AI shorter |
MidWord_enc_inj |
11 | 6 | -5 | -45% | AI shorter |
MoveDist_Steps |
4 | 3 | -1 | -25% | AI shorter |
MoveDist_minus |
3 | 3 | +0 | +0% | Same |
MoveDist_split |
15 | 8 | -7 | -47% | AI shorter |
MoveDist_unique |
17 | 10 | -7 | -41% | AI shorter |
NGramCPS_LRU_decider_0_spec |
7 | 5 | -2 | -29% | AI shorter |
NGramCPS_LRU_decider_spec |
4 | 3 | -1 | -25% | AI shorter |
NGramCPS_decider_0_spec |
18 | 12 | -6 | -33% | AI shorter |
NGramCPS_decider_impl1_0_spec |
7 | 5 | -2 | -29% | AI shorter |
NGramCPS_decider_impl1_spec |
4 | 3 | -1 | -25% | AI shorter |
NGramCPS_decider_impl2_0_spec |
5 | 3 | -2 | -40% | AI shorter |
NGramCPS_decider_impl2_spec |
4 | 3 | -1 | -25% | AI shorter |
NGramCPS_decider_spec |
20 | 16 | -4 | -20% | AI shorter |
NonHalt_iff |
17 | 15 | -2 | -12% | AI shorter |
RepWL_ES_decider_spec |
4 | 2 | -2 | -50% | AI shorter |
RepWL_ES_enc_inj |
11 | 8 | -3 | -27% | AI shorter |
RepWL_step00_spec |
126 | 40 | -86 | -68% | AI shorter |
RepWL_step0_spec |
30 | 36 | +6 | +20% | AI longer |
RepWL_step_spec |
20 | 24 | +4 | +20% | AI longer |
RepeatWord_enc_inj |
8 | 7 | -1 | -12% | AI shorter |
SearchQueue_bfs_spec |
4 | 1 | -3 | -75% | AI shorter |
SearchQueue_reset_spec |
8 | 6 | -2 | -25% | AI shorter |
SearchQueue_upd_bfs_spec |
25 | 53 | +28 | +112% | AI longer |
SearchQueue_upd_spec |
50 | 50 | +0 | +0% | Same |
SearchQueue_upds_bfs_spec |
5 | 3 | -2 | -40% | AI shorter |
SearchQueue_upds_spec |
7 | 4 | -3 | -43% | AI shorter |
St_enc_inj |
2 | 2 | +0 | +0% | Same |
St_eqb_spec |
1 | 1 | +0 | +0% | Same |
St_leb_spec |
9 | 2 | -7 | -78% | AI shorter |
St_list_spec |
2 | 1 | -1 | -50% | AI shorter |
St_suc_eq |
3 | 2 | -1 | -33% | AI shorter |
St_suc_le |
2 | 1 | -1 | -50% | AI shorter |
St_suc_neq |
1 | 1 | +0 | +0% | Same |
St_swap_swap |
7 | 19 | +12 | +171% | AI longer |
St_to_nat_inj |
2 | 1 | -1 | -50% | AI shorter |
Steps_NonHalt |
15 | 6 | -9 | -60% | AI shorter |
Steps_NonHalt_trans |
16 | 9 | -7 | -44% | AI shorter |
Steps_UnusedState |
10 | 3 | -7 | -70% | AI shorter |
Steps_rev |
19 | 19 | +0 | +0% | Same |
Steps_split |
11 | 6 | -5 | -45% | AI shorter |
Steps_swap |
19 | 6 | -13 | -68% | AI shorter |
Steps_trans |
5 | 3 | -2 | -40% | AI shorter |
Steps_unique |
6 | 6 | +0 | +0% | Same |
TM0_HTUB |
1 | 1 | +0 | +0% | Same |
TM0_LE |
5 | 1 | -4 | -80% | AI shorter |
TM_history_HF |
4 | 3 | -1 | -25% | AI shorter |
TM_history_LRU_HF |
4 | 3 | -1 | -25% | AI shorter |
TM_history_LRU_NonHaltsFromInit |
2 | 1 | -1 | -50% | AI shorter |
TM_history_NonHaltsFromInit |
2 | 1 | -1 | -50% | AI shorter |
TM_rev_rev |
4 | 2 | -2 | -50% | AI shorter |
TM_rev_upd'_TM0 |
6 | 4 | -2 | -33% | AI shorter |
TM_simplify_spec |
3 | 2 | -1 | -33% | AI shorter |
TM_swap_swap |
5 | 2 | -3 | -60% | AI shorter |
TM_upd'_spec |
3 | 1 | -2 | -67% | AI shorter |
TNF_Node_NonHalt |
3 | 2 | -1 | -33% | AI shorter |
TNF_Node_expand_spec |
44 | 53 | +9 | +20% | AI longer |
T_close_set_searcher_spec |
47 | 39 | -8 | -17% | AI shorter |
T_decider0_spec |
59 | 52 | -7 | -12% | AI shorter |
T_decider_spec |
5 | 4 | -1 | -20% | AI shorter |
T_eqb_spec |
3 | 3 | +0 | +0% | Same |
Tape_rev_rev |
4 | 1 | -3 | -75% | AI shorter |
Trans_list_spec |
4 | 3 | -1 | -25% | AI shorter |
Trans_rev_rev |
5 | 1 | -4 | -80% | AI shorter |
Trans_swap_id |
8 | 7 | -1 | -12% | AI shorter |
Trans_swap_swap |
5 | 1 | -4 | -80% | AI shorter |
UnusedState_TM0 |
5 | 6 | +1 | +20% | AI longer |
UnusedState_dec |
2 | 4 | +2 | +100% | AI longer |
UnusedState_ptr_upd |
65 | 71 | +6 | +9% | AI longer |
UnusedState_upd |
45 | 43 | -2 | -4% | AI shorter |
WordUpdate_spec |
34 | 43 | +9 | +26% | AI longer |
WordUpdate_step0_spec |
51 | 47 | -4 | -8% | AI shorter |
WordUpdate_steps_spec |
26 | 49 | +23 | +88% | AI longer |
Word_eqb_spec |
11 | 9 | -2 | -18% | AI shorter |
all0_spec |
4 | 5 | +1 | +25% | AI longer |
allTM_HTUB |
8 | 4 | -4 | -50% | AI shorter |
andb_shortcut_spec |
1 | 1 | +0 | +0% | Same |
app_half_tape_all0 |
8 | 3 | -5 | -62% | AI shorter |
app_halftape_S |
1 | 1 | +0 | +0% | Same |
app_halftape_all0 |
10 | 6 | -4 | -40% | AI shorter |
app_halftape_assoc |
3 | 11 | +8 | +267% | AI longer |
app_halftape_cdr |
5 | 4 | -1 | -20% | AI shorter |
app_halftape_cdr' |
4 | 3 | -1 | -25% | AI shorter |
app_halftape_cdr'' |
2 | 4 | +2 | +100% | AI longer |
app_halftape_eq |
17 | 14 | -3 | -18% | AI shorter |
app_halftape_eq' |
8 | 8 | +0 | +0% | Same |
app_halftape_eq_car_cdr |
7 | 5 | -2 | -29% | AI shorter |
app_halftape_eq_cons |
7 | 6 | -1 | -14% | AI shorter |
app_halftape_nil |
3 | 3 | +0 | +0% | Same |
app_halftape_skipn |
7 | 5 | -2 | -29% | AI shorter |
app_halftape_skipn_cdr |
10 | 8 | -2 | -20% | AI shorter |
bool_enc_inj |
2 | 1 | -1 | -50% | AI shorter |
check_InitES_InAES_spec |
30 | 25 | -5 | -17% | AI shorter |
decider2_WF |
3 | 1 | -2 | -67% | AI shorter |
decider_all_spec |
9 | 18 | +9 | +100% | AI longer |
empty_set_WF |
6 | 3 | -3 | -50% | AI shorter |
enc_list_inj |
9 | 9 | +0 | +0% | Same |
enc_pair_inj |
12 | 5 | -7 | -58% | AI shorter |
enc_v1_eq |
4 | 4 | +0 | +0% | Same |
ex_sitr_history |
41 | 38 | -3 | -7% | AI shorter |
fext_inv |
1 | 1 | +0 | +0% | Same |
ffx_eq_x_inj |
6 | 1 | -5 | -83% | AI shorter |
find_loop1_0_spec |
4 | 6 | +2 | +50% | AI longer |
find_loop1_spec |
24 | 62 | +38 | +158% | AI longer |
forallb_Dir_spec |
5 | 3 | -2 | -40% | AI shorter |
forallb_St_spec |
5 | 3 | -2 | -40% | AI shorter |
forallb_Σ_spec |
5 | 3 | -2 | -40% | AI shorter |
getASteps_spec |
316 | 167 | -149 | -47% | AI shorter |
half_tape_cdr_cons |
4 | 3 | -1 | -25% | AI shorter |
half_tape_make_tape_l |
5 | 3 | -2 | -40% | AI shorter |
half_tape_make_tape_r |
5 | 3 | -2 | -40% | AI shorter |
halftape_skipn_0 |
2 | 1 | -1 | -50% | AI shorter |
halt_decider0_spec |
28 | 38 | +10 | +36% | AI longer |
halt_decider_WF |
17 | 10 | -7 | -41% | AI shorter |
halt_decider_max_spec |
2 | 1 | -1 | -50% | AI shorter |
halt_time_verifier_spec |
12 | 10 | -2 | -17% | AI shorter |
ins_all_spec |
31 | 52 | +21 | +68% | AI longer |
isHaltTrans_0 |
1 | 1 | +0 | +0% | Same |
isUnusedState_spec |
53 | 37 | -16 | -30% | AI shorter |
iter_S |
3 | 1 | -2 | -67% | AI shorter |
listStΣ_enc_inj |
9 | 7 | -2 | -22% | AI shorter |
listT_enc_inj |
5 | 2 | -3 | -60% | AI shorter |
list_enc_inj |
17 | 12 | -5 | -29% | AI shorter |
list_eq__nth_error |
20 | 11 | -9 | -45% | AI shorter |
listΣ_inj |
7 | 8 | +1 | +14% | AI longer |
loop1_decider0_def |
2 | 1 | -1 | -50% | AI shorter |
loop1_decider0_spec |
38 | 36 | -2 | -5% | AI shorter |
loop1_decider_WF |
19 | 11 | -8 | -42% | AI shorter |
loop1_nonhalt |
N/A | 0 | N/A | N/A | AI Admitted |
loop1_nonhalt' |
N/A | 0 | N/A | N/A | AI Admitted |
m_def |
1 | 1 | +0 | +0% | Same |
make_tape'_cdr_l |
3 | 1 | -2 | -67% | AI shorter |
make_tape'_cdr_r |
3 | 1 | -2 | -67% | AI shorter |
make_tape'_cons_l |
5 | 8 | +3 | +60% | AI longer |
make_tape'_cons_r |
5 | 8 | +3 | +60% | AI longer |
make_tape'_lmr |
1 | 1 | +0 | +0% | Same |
make_tape'_mov_l |
17 | 24 | +7 | +41% | AI longer |
make_tape'_mov_r |
7 | 22 | +15 | +214% | AI longer |
make_tape'_rev |
3 | 2 | -1 | -33% | AI shorter |
make_tape'_spec |
36 | 30 | -6 | -17% | AI shorter |
make_tape'_split_l |
3 | 1 | -2 | -67% | AI shorter |
make_tape'_split_r |
3 | 1 | -2 | -67% | AI shorter |
make_tape'_upd |
3 | 2 | -1 | -33% | AI shorter |
make_tape_eq |
12 | 8 | -4 | -33% | AI shorter |
map_inj |
7 | 4 | -3 | -43% | AI shorter |
mov_tape_rev |
4 | 2 | -2 | -50% | AI shorter |
mset_ins0_spec |
4 | 2 | -2 | -50% | AI shorter |
mset_ins_spec |
27 | 24 | -3 | -11% | AI shorter |
nat_eqb_N_spec |
8 | 6 | -2 | -25% | AI shorter |
nat_eqb_spec |
1 | 1 | +0 | +0% | Same |
nat_lt_spec |
1 | 1 | +0 | +0% | Same |
nth_error_skipn |
8 | 5 | -3 | -38% | AI shorter |
option_Trans_rev_rev |
6 | 3 | -3 | -50% | AI shorter |
option_Trans_swap_swap |
4 | 3 | -1 | -25% | AI shorter |
orb_shortcut_spec |
1 | 1 | +0 | +0% | Same |
pop_back'__push_back |
3 | 3 | +0 | +0% | Same |
pop_back__nth_error |
8 | 7 | -1 | -12% | AI shorter |
pop_back_len |
4 | 3 | -1 | -25% | AI shorter |
pop_spec |
43 | 44 | +1 | +2% | AI longer |
push_spec |
30 | 28 | -2 | -7% | AI shorter |
q_200_WF |
14 | 1 | -13 | -93% | AI shorter |
q_200_empty |
1 | 1 | +0 | +0% | Same |
q_200_spec |
201 | 201 | +0 | +0% | Same |
root_HTUB |
7 | 5 | -2 | -29% | AI shorter |
root_WF |
7 | 9 | +2 | +29% | AI longer |
root_q_WF |
1 | 1 | +0 | +0% | Same |
root_q_upd1_WF |
3 | 3 | +0 | +0% | Same |
root_q_upd1_simplified_WF |
36 | 39 | +3 | +8% | AI longer |
s_def |
1 | 1 | +0 | +0% | Same |
set_in_dec |
4 | 3 | -1 | -25% | AI shorter |
set_ins_spec |
21 | 17 | -4 | -19% | AI shorter |
set_ins_spec' |
32 | 37 | +5 | +16% | AI longer |
sidpos_history_WF_O |
8 | 7 | -1 | -12% | AI shorter |
sidpos_history_WF_S |
21 | 26 | +5 | +24% | AI longer |
sidpos_history_WF_cdr |
7 | 8 | +1 | +14% | AI longer |
sidpos_history_hd |
6 | 4 | -2 | -33% | AI shorter |
sidpos_history_period_S |
12 | 12 | +0 | +0% | Same |
sidpos_history_period_S' |
6 | 6 | +0 | +0% | Same |
skipn_S |
8 | 5 | -3 | -38% | AI shorter |
skipn_S' |
7 | 1 | -6 | -86% | AI shorter |
skipn_S_n |
11 | 5 | -6 | -55% | AI shorter |
skipn_skipn |
8 | 5 | -3 | -38% | AI shorter |
step_UnusedState |
6 | 5 | -1 | -17% | AI shorter |
step_halt_rev |
9 | 5 | -4 | -44% | AI shorter |
step_halt_swap |
6 | 4 | -2 | -33% | AI shorter |
step_rev |
44 | 7 | -37 | -84% | AI shorter |
step_swap |
12 | 6 | -6 | -50% | AI shorter |
tape_seg__repeat_Σ0 |
2 | 3 | +1 | +50% | AI longer |
tape_seg_hd |
4 | 3 | -1 | -25% | AI shorter |
tape_seg_mov_upd |
16 | 12 | -4 | -25% | AI shorter |
tape_seg_mov_upd_2 |
34 | 33 | -1 | -3% | AI shorter |
tape_seg_pop |
30 | 34 | +4 | +13% | AI longer |
tape_seg_spec |
21 | 10 | -11 | -52% | AI shorter |
update_AES_Closed |
21 | 15 | -6 | -29% | AI shorter |
update_AES_MidWord_spec |
69 | 45 | -24 | -35% | AI shorter |
update_AES_spec |
32 | 26 | -6 | -19% | AI shorter |
verify_loop1_spec |
55 | 48 | -7 | -13% | AI shorter |
xset_WF_1 |
9 | 9 | +0 | +0% | Same |
xset_WF_2 |
13 | 17 | +4 | +31% | AI longer |
xset_WF_empty |
7 | 6 | -1 | -14% | AI shorter |
xset_as_list_spec |
26 | 5 | -21 | -81% | AI shorter |
xset_ins_spec |
32 | 24 | -8 | -25% | AI shorter |
xset_matches_mov_upd_1 |
24 | 18 | -6 | -25% | AI shorter |
xset_matches_mov_upd_2 |
45 | 22 | -23 | -51% | AI shorter |
Σ_enc_inj |
2 | 2 | +0 | +0% | Same |
Σ_eqb_spec |
1 | 1 | +0 | +0% | Same |
Σ_history_enc_inj |
5 | 4 | -1 | -20% | AI shorter |
Σ_list_spec |
2 | 1 | -1 | -50% | AI shorter |
PositiveMap_add_find_eq |
N/A | 4 | N/A | N/A | Only in AI-generated |
RepW_prepend |
N/A | 6 | N/A | N/A | Only in AI-generated |
RepW_weaken |
N/A | 5 | N/A | N/A | Only in AI-generated |
Steps_le |
N/A | 8 | N/A | N/A | Only in AI-generated |
Steps_swap_fwd |
N/A | 5 | N/A | N/A | Only in AI-generated |
append_inj |
N/A | 3 | N/A | N/A | Only in AI-generated |
enc_pair_not_xH |
N/A | 2 | N/A | N/A | Only in AI-generated |
nil_match |
N/A | 2 | N/A | N/A | Only in AI-generated |
nth_Sigma0_nil |
N/A | 1 | N/A | N/A | Only in AI-generated |
nth_shift_eq |
N/A | 2 | N/A | N/A | Only in AI-generated |
pos_to_nat_pred_double |
N/A | 2 | N/A | N/A | Only in AI-generated |
q_200_WF_step |
N/A | 1 | N/A | N/A | Only in AI-generated |
q_200_WF_steps |
N/A | 3 | N/A | N/A | Only in AI-generated |
sidpos_history_WF_skipn |
N/A | 5 | N/A | N/A | Only in AI-generated |
sidpos_history_period_skipn |
N/A | 4 | N/A | N/A | Only in AI-generated |
step_rev_fwd |
N/A | 10 | N/A | N/A | Only in AI-generated |
strip_one |
N/A | 2 | N/A | N/A | Only in AI-generated |
tape_eq |
N/A | 6 | N/A | N/A | Only in AI-generated |
tape_seg_shift |
N/A | 4 | N/A | N/A | Only in AI-generated |
verify_loop1_nonhalt_n0 |
N/A | 44 | N/A | N/A | Only in AI-generated |
xset_in_unfold |
N/A | 6 | N/A | N/A | Only in AI-generated |
Click a header to expand/collapse. Statement is shown above the proof.
Lemma AES_Closed_NonHalt tm S st: InAES st S -> AES_isClosed tm S -> ~Halts _ tm st.
Proof. intros. eapply CPS_correct. 1: apply H. unfold isClosed. unfold AES_isClosed in H0. intros st0 H1. specialize (H0 st0 H1). destruct H0 as [st1 [H0a H0b]]. exists 0. exists st1. split. 2: assumption. cbn. ector. - ector. - assumption. Qed.
Lemma AES_Closed_NonHalt tm S st: InAES st S -> AES_isClosed tm S -> ~Halts _ tm st.
Proof. intros Hp HAD. enough (forall n, exists st', Steps _ tm n st st' /\ InAES st' S) as Hinf. { apply NonHalt_iff. intros n. destruct (Hinf n) as [st' [H _]]. eauto. } induction n as [|n' IH]. - exists st. split; [constructor|exact Hp]. - destruct IH as [st' [Hst' Hp']]. destruct (HAD st' Hp') as [st1 [Hyz Hp1]]. exists st1. split; [|exact Hp1]. eapply steps_S; eauto. Qed.
Lemma AES_isClosed'_correct tm S: AES_isClosed' tm S -> AES_isClosed tm S.
Proof. destruct S. unfold AES_isClosed',AES_isClosed,AES_CloseAt. intros H st0 H0. unfold InAES in H0. destruct st0 as [s t]. destruct H0 as [[mw [H0a H0b]] [H0c H0d]]. specialize (H mw H0a). destruct mw. destruct l0 as [|hl l1]. 1: contradiction. destruct r0 as [|hr r1]. 1: contradiction. destruct (tm s0 m0) as [[s1 d o]|] eqn:E. 2: contradiction. unfold MidWord_matches in H0b. destruct H0b as [H1a [H1b [H1c H1d]]]. subst. cbn. rewrite E. eexists. split. 1: reflexivity. unfold InAES. destruct d. { destruct H as [Ha Hb]. pose proof (H0c 2) as H2. cbn in H2. assert (H3:1<2) by lia. specialize (H2 H3). destruct H2 as [ls [H2a H2b]]. subst. specialize (Hb (t (-1-(Z.of_nat len_l))%Z)). split. - exists {| l := l1 ++ t (-1 - Z.of_nat len_l)%Z :: nil; r := o :: pop_back hr r1; m := hl; s := s1 |}. assert (H':(l1 ++ t (-1 - Z.of_nat len_l)%Z :: nil)=(tape_seg t (-2) Dneg len_l)). { pose proof (tape_seg_pop _ _ _ Dneg _ H1c) as H4. cbn in H4. rewrite <-H4 in H2a. assert (H5:(Z.neg (Pos.of_succ_nat len_l))=(-1 - Z.of_nat len_l)%Z) by lia. rewrite <-H5. apply H4. } split. + apply Hb. rewrite H'; assumption. + unfold MidWord_matches. repeat split; auto. * cbn. eapply tape_seg_hd. apply H1c. * rewrite H'. apply (tape_seg_mov_upd _ Dneg _ _). * apply (tape_seg_mov_upd_2 _ _ _ Dpos _ _ H1d). - split. + apply xset_matches_mov_upd_1; assumption. + rewrite H1d in Ha. eapply (xset_matches_mov_upd_2 _ _ Dpos _ _); eassumption. } { destruct H as [Ha Hb]. pose proof (H0d 2) as H2. cbn in H2. assert (H3:1<2) by lia. specialize (H2 H3). destruct H2 as [ls [H2a H2b]]. subst. specialize (Hb (t (1+(Z.of_nat len_r))%Z)). split. - exists {| l := o :: pop_back hl l1; r := r1 ++ t (1 + Z.of_nat len_r)%Z :: nil; m := hr; s := s1 |}. assert (H':(r1 ++ t (1 + Z.of_nat len_r)%Z :: nil)=(tape_seg t (2) Dpos len_r)). { pose proof (tape_seg_pop _ _ _ Dpos _ H1d) as H4. cbn in H4. rewrite <-H4 in H2a. assert (H5:(Z.pos (Pos.of_succ_nat len_r))=(1 + Z.of_nat len_r)%Z) by lia. rewrite <-H5. apply H4. } split. + apply Hb. rewrite H'; assumption. + unfold MidWord_matches. repeat split; auto. * cbn. eapply tape_seg_hd. apply H1d. * apply (tape_seg_mov_upd_2 _ _ _ Dneg _ _ H1c). * rewrite H'. apply (tape_seg_mov_upd _ Dpos _ _). - split. + rewrite H1c in Ha. eapply (xset_matches_mov_upd_2 _ _ Dneg _ _); eassumption. + apply xset_matches_mov_upd_1; assumption. } Qed.
Lemma AES_isClosed'_correct tm S: AES_isClosed' tm S -> AES_isClosed tm S.
Proof. destruct S as [ls rs ms]. intro Hadtw'. unfold AES_isClosed. intros [s t] [[mw [Hmsmw Hwue]] [Hwl Hwr]]. destruct mw as [l0 r0 m0 s0]. unfold MidWord_matches in Hwue. destruct Hwue as [Hseq [Hmeq [Hleq Hreq]]]. subst s0 m0 l0 r0. set (l0 := tape_seg t (-1)%Z Dneg len_l) in *. set (r0 := tape_seg t 1%Z Dpos len_r) in *. assert (Hib: AES_CloseAt tm {| lset := ls; rset := rs; mset := ms |} {| l := l0; r := r0; m := t 0%Z; s := s |}). { apply Hadtw'. exact Hmsmw. } simpl in Hib. destruct l0 as [|hl l1] eqn:El0; [destruct Hib|]. destruct r0 as [|hr r1] eqn:Er0; [destruct Hib|]. destruct (tm s (t 0%Z)) as [tr|] eqn:Etm; [|destruct Hib]. destruct tr as [s1 d o]. unfold step. rewrite Etm. eexists; split; [reflexivity|]. destruct d. - destruct Hib as [Hrs0 Hib]. unfold InAES. split; [|split]. + destruct (Hwl 2 ltac:(lia)) as [lsn [Hlsn Hlsneq]]. pose proof (tape_seg_pop hl l1 t Dneg len_l ltac:(symmetry; exact El0)) as HF6s_l. set (xn := t (Dir_to_Z Dneg * Z.of_nat (S len_l))%Z). assert (Hls_xn: ls (l1 ++ xn :: nil)). { assert (Heq: lsn = l1 ++ xn :: nil). { rewrite Hlsneq. symmetry. replace (Z.of_nat 2 * Dir_to_Z Dneg)%Z with (Dir_to_Z Dneg * 2)%Z by lia. exact HF6s_l. } rewrite <- Heq. exact Hlsn. } specialize (Hib xn Hls_xn). exists {| l := l1 ++ xn :: nil; r := o :: pop_back hr r1; m := hl; s := s1 |}. split; [exact Hib|]. unfold MidWord_matches. repeat split. * unfold mov, upd, Dir_to_Z. simpl. apply (tape_seg_hd hl l1 t (-1)%Z Dneg len_l). symmetry. exact El0. * change ((-1)%Z) with (Dir_to_Z Dneg). transitivity (tape_seg t (Dir_to_Z Dneg * 2) Dneg len_l). { exact HF6s_l. } { exact (tape_seg_mov_upd t Dneg o len_l). } * change Dneg with (Dir_rev Dpos). change (1%Z) with (Dir_to_Z Dpos). exact (tape_seg_mov_upd_2 hr r1 t Dpos o len_r ltac:(symmetry; exact Er0)). + apply (xset_matches_mov_upd_1 t ls Dneg o len_l). exact Hwl. + apply (xset_matches_mov_upd_2 t rs Dpos o len_r). exact Hwr. assert (Er0': tape_seg t (Dir_to_Z Dpos) Dpos len_r = hr :: r1) by exact Er0. rewrite Er0'. exact Hrs0. - destruct Hib as [Hls0 Hib]. unfold InAES. split; [|split]. + destruct (Hwr 2 ltac:(lia)) as [rsn [Hrsn Hrsneq]]. pose proof (tape_seg_pop hr r1 t Dpos len_r ltac:(symmetry; exact Er0)) as HF6s_r. set (xn := t (Dir_to_Z Dpos * Z.of_nat (S len_r))%Z). assert (Hrs_xn: rs (r1 ++ xn :: nil)). { assert (Heq: rsn = r1 ++ xn :: nil). { rewrite Hrsneq. symmetry. replace (Z.of_nat 2 * Dir_to_Z Dpos)%Z with (Dir_to_Z Dpos * 2)%Z by lia. exact HF6s_r. } rewrite <- Heq. exact Hrsn. } specialize (Hib xn Hrs_xn). exists {| l := o :: pop_back hl l1; r := r1 ++ xn :: nil; m := hr; s := s1 |}. split; [exact Hib|]. unfold MidWord_matches. repeat split. * unfold mov, upd, Dir_to_Z. simpl. apply (tape_seg_hd hr r1 t 1%Z Dpos len_r). symmetry. exact Er0. * change Dpos with (Dir_rev Dneg). change ((-1)%Z) with (Dir_to_Z Dneg). exact (tape_seg_mov_upd_2 hl l1 t Dneg o len_l ltac:(symmetry; exact El0)). * change (1%Z) with (Dir_to_Z Dpos). transitivity (tape_seg t (Dir_to_Z Dpos * 2) Dpos len_r). { exact HF6s_r. } { exact (tape_seg_mov_upd t Dpos o len_r). } + apply (xset_matches_mov_upd_2 t ls Dneg o len_l). exact Hwl. assert (El0': tape_seg t (Dir_to_Z Dneg) Dneg len_l = hl :: l1) by exact El0. rewrite El0'. exact Hls0. + apply (xset_matches_mov_upd_1 t rs Dpos o len_r). exact Hwr. Qed.
Lemma BB4_lower_bound: exists tm, HaltsAt _ tm (N.to_nat BB) (InitES Σ Σ0).
Proof. exists BB4_champion. apply halt_time_verifier_spec. vm_compute. reflexivity. Qed.
Lemma BB4_lower_bound: exists tm, HaltsAt _ tm (N.to_nat BB) (InitES Σ Σ0).
Proof. exists BB4_champion. unfold BB. simpl N.to_nat. apply halt_time_verifier_spec. native_compute. reflexivity. Qed.
Lemma BB4_upperbound: forall tm n0, HaltsAt Σ tm n0 (InitES Σ Σ0) -> n0 <= N.to_nat BB.
Proof. intros tm n0. apply allTM_HTUB. trivial. Qed.
Lemma BB4_upperbound: forall tm n0, HaltsAt Σ tm n0 (InitES Σ Σ0) -> n0 <= N.to_nat BB.
Proof. intros tm n0 Hhalt. apply (allTM_HTUB tm n0). exact I. exact Hhalt. Qed.
Lemma BB4_value: (forall tm n0, HaltsAt Σ tm n0 (InitES Σ Σ0) -> n0 <= N.to_nat BB) /\ (exists tm, HaltsAt Σ tm (N.to_nat BB) (InitES Σ Σ0)).
Proof. split. - intros tm n0. apply allTM_HTUB. trivial. - apply BB4_lower_bound. Qed.
Lemma BB4_value: (forall tm n0, HaltsAt Σ tm n0 (InitES Σ Σ0) -> n0 <= N.to_nat BB) /\ (exists tm, HaltsAt Σ tm (N.to_nat BB) (InitES Σ Σ0)).
Proof. split. - exact BB4_upperbound. - exact BB4_lower_bound. Qed.
Lemma CPS_correct tm S st: InT st S -> isClosed tm S -> ~Halts _ tm st.
Proof. intros. unfold Halts. intro H1. destruct H1 as [n H1]. destruct (Closed_NonHalt _ _ _ H H0 (1+n)) as [m [H2 [st0 [H3 H4]]]]. assert (H5:n<m) by lia. apply (Steps_NonHalt _ H5 H3 H1). Qed.
Lemma CPS_correct tm S st: InT st S -> isClosed tm S -> ~Halts _ tm st.
Proof. intros Hin Hinv. rewrite <- NonHalt_iff. unfold NonHalt. intros n. pose proof (Closed_NonHalt tm S st Hin Hinv n) as [m [Hle [st0 [Hsteps _]]]]. destruct (@Steps_le _ _ n m _ _ Hle Hsteps) as [stm Hstm]. exists stm. exact Hstm. Qed.
Lemma Closed_NonHalt tm S st: InT st S -> isClosed tm S -> forall n:nat, exists m:nat, n<=m /\ exists st0, Steps Σ tm m st st0 /\ InT st0 S.
Proof. intros H H0 n. induction n. - exists 0. split. 1: lia. exists st. split. 2: assumption. ctor. - destruct IHn as [m [H1 [st0 [H2 H3]]]]. destruct (H0 _ H3) as [n0 [st1 [H4 H5]]]. pose proof (Steps_trans _ H2 H4) as H6. exists (1+n0+m). split. 1: lia. exists st1. tauto. Qed.
Lemma Closed_NonHalt tm S st: InT st S -> isClosed tm S -> forall n:nat, exists m:nat, n<=m /\ exists st0, Steps Σ tm m st st0 /\ InT st0 S.
Proof. intros Hin Hinv n. induction n as [|n' IH]. - exists 0. split. lia. exists st. split. constructor. exact Hin. - destruct IH as [m [Hle [st0 [Hsteps Hin0]]]]. unfold isClosed in Hinv. specialize (Hinv st0 Hin0). destruct Hinv as [k [st1 [Hstep1 Hin1]]]. exists ((1+k)+m). split. lia. exists st1. split. apply Steps_trans with st0; auto. exact Hin1. Qed.
Lemma CountHaltTrans_0_NonHalt {tm st}: CountHaltTrans tm = 0 -> ~Halts Σ tm st.
Proof. intro H. assert (forall s i, tm s i <> None). { intros. unfold CountHaltTrans in H. cbn in H. repeat rewrite Nat.eq_add_0 in H. repeat rewrite isHaltTrans_0 in H. repeat destruct_and. destruct s,i; assumption. } intro H1. unfold Halts,HaltsAt in H1. destruct H1 as [n [st' [H1 H2]]]. destruct st'. cbn in H2. destruct (tm s (σ 0%Z)) eqn:E; cg. destruct t. cg. Qed.
Lemma CountHaltTrans_0_NonHalt {tm st}: CountHaltTrans tm = 0 -> ~Halts Σ tm st.
Proof. intros Hcnt. rewrite <- NonHalt_iff. unfold NonHalt. intros n. induction n as [|n' IH]. - exists st. constructor. - destruct IH as [st' Hst']. destruct st' as [s' t']. assert (H: tm s' (t' Z0) <> None). { assert (Haux: forall s0 i0, isHaltTrans (tm s0 i0) = 0). { intros s0 i0. unfold CountHaltTrans, St_list, Σ_list in Hcnt. simpl in Hcnt. destruct s0, i0; lia. } specialize (Haux s' (t' Z0)). rewrite <- isHaltTrans_0. exact Haux. } destruct (tm s' (t' Z0)) as [tr|] eqn:E. + destruct tr as [s'' d o]. eexists. eapply steps_S; eauto. simpl. rewrite E. reflexivity. + exfalso. apply H. reflexivity. Qed.
Lemma CountHaltTrans_upd {tm s i} tr: tm s i = None -> S (CountHaltTrans (TM_upd Σ Σ_eqb tm s i (Some tr))) = (CountHaltTrans tm).
Proof. unfold CountHaltTrans. cbn. unfold TM_upd. intro H. destruct s,i; cbn; rewrite H; cbn; lia. Qed.
Lemma CountHaltTrans_upd {tm s i} tr: tm s i = None -> S (CountHaltTrans (TM_upd Σ Σ_eqb tm s i (Some tr))) = (CountHaltTrans tm).
Proof. intros Hnone. unfold CountHaltTrans, TM_upd, St_list, Σ_list, list_nat_sum. simpl. destruct s, i; simpl; repeat (match goal with | |- context [St_eqb ?x ?y] => destruct (St_eqb x y) eqn:? | |- context [Σ_eqb ?x ?y] => destruct (Σ_eqb x y) eqn:? end; simpl; try lia); try (rewrite Hnone; simpl; lia); try (pose proof (St_eqb_spec _ _ ) as HH; rewrite Heqb in HH; congruence); try (pose proof (Σ_eqb_spec _ _) as HH; rewrite Heqb0 in HH; congruence). Qed.
Lemma Dir_enc_inj: is_inj Dir_enc.
Proof. intros x1 x2 H. destruct x1,x2; cbn in H; cg. Qed.
Lemma Dir_enc_inj: is_inj Dir_enc.
Proof. intros a b H. destruct a, b; simpl in H; congruence. Qed.
Lemma Dir_eqb_spec d1 d2:
if Dir_eqb d1 d2 then d1=d2 else d1<>d2.
Proof. destruct d1,d2; cbn; cg. Qed.
Lemma Dir_eqb_spec d1 d2:
if Dir_eqb d1 d2 then d1=d2 else d1<>d2.
Proof. destruct d1, d2; simpl; congruence. Qed.
Lemma Dir_list_spec: forall s, In s Dir_list.
Proof. intro s. destruct s; cbn; tauto. Qed.
Lemma Dir_list_spec: forall s, In s Dir_list.
Proof. destruct s; simpl; auto. Qed.
Lemma ExecState_rev_rev: forall st, ExecState_rev (ExecState_rev st) = st.
Proof. intros. destruct st as [s t]. cbn. f_equal. apply Tape_rev_rev. Qed.
Lemma ExecState_rev_rev: forall st, ExecState_rev (ExecState_rev st) = st.
Proof. intro st. destruct st as [s t]. simpl. rewrite Tape_rev_rev. reflexivity. Qed.
Lemma ExecState_swap_swap: forall st, ExecState_swap (ExecState_swap st) = st.
Proof. intros. destruct st as [s t]. unfold ExecState_swap. f_equal. apply St_swap_swap. Qed.
Lemma ExecState_swap_swap: forall st, ExecState_swap (ExecState_swap st) = st.
Proof. intro st. destruct st as [s t]. simpl. rewrite St_swap_swap. reflexivity. Qed.
Lemma F_HaltsFromInit: HaltsFromInit Σ (F Σ0') tm -> HaltsFromInit Σ' Σ0' tm'.
Proof. unfold HaltsFromInit,Halts,HaltsAt. rewrite F_InitES. intro H. destruct H as [n [st' [H H0]]]. exists n. destruct (F_Steps _ _ _ H) as [st [H1 H2]]. exists st. split; auto. destruct st,st'. cbn in H2. invst H2. apply F_step_halt,H0. Qed.
Lemma F_HaltsFromInit: HaltsFromInit Σ (F Σ0') tm -> HaltsFromInit Σ' Σ0' tm'.
Proof. unfold HaltsFromInit, Halts, HaltsAt. intros [n [st' [Hsteps Hhalt]]]. rewrite F_InitES in Hsteps. destruct (F_Steps n _ _ Hsteps) as [st1' [Hst1' Heq]]. exists n, st1'. split; [exact Hst1'|]. subst st'. apply F_step_halt. exact Hhalt. Qed.
Lemma F_InitES:
InitES Σ (F Σ0') =
F_ES (InitES Σ' Σ0').
Proof. reflexivity. Qed.
Lemma F_InitES:
InitES Σ (F Σ0') =
F_ES (InitES Σ' Σ0').
Proof. unfold InitES, F_ES. reflexivity. Qed.
Lemma F_NonHaltsFromInit: ~HaltsFromInit Σ' Σ0' tm' -> ~HaltsFromInit Σ (F Σ0') tm.
Proof. pose proof F_HaltsFromInit. tauto. Qed.
Lemma F_NonHaltsFromInit: ~HaltsFromInit Σ' Σ0' tm' -> ~HaltsFromInit Σ (F Σ0') tm.
Proof. intros H1 H2. apply H1. apply F_HaltsFromInit. exact H2. Qed.
Lemma F_Steps n st0 st1: Steps Σ tm n (F_ES st0) st1-> exists st1', Steps Σ' tm' n st0 st1' /\ F_ES st1' = st1.
Proof. gd st1. induction n; intros st1 H. - invst H. exists st0. split. 2:reflexivity. ctor. - invst H. destruct (IHn _ H1) as [st1' [H4 H5]]. subst. destruct (F_step _ _ H3) as [st2 [H5 H6]]. exists st2. split. 2: assumption. ector; eauto. Qed.
Lemma F_Steps n st0 st1: Steps Σ tm n (F_ES st0) st1-> exists st1', Steps Σ' tm' n st0 st1' /\ F_ES st1' = st1.
Proof. revert st0 st1. induction n; intros st0 st1 Hsteps. - inversion Hsteps; subst. exists st0. split; [constructor|reflexivity]. - inversion Hsteps; subst. match goal with | [ H : Steps _ _ n _ _, H2 : step _ _ _ = Some _ |- _ ] => destruct (IHn _ _ H) as [st2' [Hst2' Heq2]]; subst; destruct (F_step st2' st1 H2) as [st1' [Hyz' Heq1]]; exists st1'; split; [|exact Heq1]; eapply steps_S; eauto end. Qed.
Lemma F_step st0 st1: step Σ tm (F_ES st0) = Some st1-> exists st1', step Σ' tm' st0 = Some st1' /\ F_ES st1' = st1.
Proof. destruct st0 as [s t]. cbn. intro H. pose proof (HF s (t 0%Z)) as H0. destruct (tm s (F (t 0%Z))) as [[s1 d1 o1]|] eqn:E. 2: cg. destruct (tm' s (t 0%Z)) as [[s1' d1' o1']|] eqn:E'. 2: cg. invst H0; clear H0. eexists. split. 1: reflexivity. cbn. invst H. f_equal. unfold mov,upd. fext. destruct ((x + Dir_to_Z d1' =? 0)%Z); reflexivity. Qed.
Lemma F_step st0 st1: step Σ tm (F_ES st0) = Some st1-> exists st1', step Σ' tm' st0 = Some st1' /\ F_ES st1' = st1.
Proof. destruct st0 as [s0 t0]. unfold F_ES, step. simpl. pose proof (HF s0 (t0 0%Z)) as HF0. destruct (tm' s0 (t0 0%Z)) as [[s' d o']|] eqn:Etm'. - rewrite HF0. intro H. inversion H. subst. exists (s', mov Σ' (upd Σ' t0 o') d). split. + reflexivity. + unfold F_ES, mov, upd. f_equal. extensionality x. destruct d; simpl; destruct (Z.eqb _ _) eqn:Ez; reflexivity. - rewrite HF0. intro H. discriminate. Qed.
Lemma F_step_halt st0: step Σ tm (F_ES st0) = None-> step Σ' tm' st0 = None.
Proof. unfold step. destruct st0 as [s t]. cbn. specialize (HF s (t Z0)). destruct (tm' s (t 0%Z)); cbn; cg. destruct t0. rewrite HF. cg. Qed.
Lemma F_step_halt st0: step Σ tm (F_ES st0) = None-> step Σ' tm' st0 = None.
Proof. destruct st0 as [s0 t0]. unfold F_ES, step. simpl. pose proof (HF s0 (t0 0%Z)) as HF0. destruct (tm' s0 (t0 0%Z)) as [[s' d o']|] eqn:Etm'. - rewrite HF0. intro H. discriminate. - rewrite HF0. intro. reflexivity. Qed.
Lemma HaltDecider_cons_spec(f g:HaltDecider): HaltDecider_WF f -> HaltDecider_WF g -> HaltDecider_WF (HaltDecider_cons f g).
Proof. intros Hf Hg tm. specialize (Hf tm). specialize (Hg tm). unfold HaltDecider_cons. destruct (f tm); auto 1. Qed.
Lemma HaltDecider_cons_spec(f g:HaltDecider): HaltDecider_WF f -> HaltDecider_WF g -> HaltDecider_WF (HaltDecider_cons f g).
Proof. intros Hf Hg tm. unfold HaltDecider_cons. specialize (Hf tm). specialize (Hg tm). destruct (f tm); auto. Qed.
Lemma HaltTimeUpperBound_LE_Halt st tm n s t: HaltsAt tm n st -> Steps tm n st (s,t) -> n<=BB -> (forall tr, HaltTimeUpperBound st (LE (TM_upd tm s (t Z0) (Some tr)))) -> HaltTimeUpperBound st (LE tm).
Proof. intros. unfold HaltTimeUpperBound. intros. destruct (tm0 s (t Z0)) as [tr|] eqn:E. - specialize (H2 tr). eapply H2. 2: apply H4. eapply LE_HaltsAtES_2; eassumption. - pose proof (LE_HaltsAtES_1 H3 H H0 E). rewrite (HaltsAt_unique H4 H5). assumption. Qed.
Lemma HaltTimeUpperBound_LE_Halt st tm n s t: HaltsAt tm n st -> Steps tm n st (s,t) -> n<=BB -> (forall tr, HaltTimeUpperBound st (LE (TM_upd tm s (t Z0) (Some tr)))) -> HaltTimeUpperBound st (LE tm).
Proof. intros Hhalt Hsteps HnBB Hforall. intros tm' n0 Hle Hhalt'. destruct (Hhalt) as [st' [Hsteps' Hhalt'']]. assert (st' = (s,t)) by (eapply Steps_unique; eassumption). subst. destruct (tm' s (t Z0)) eqn:Etm'. - apply (Hforall t0 tm' n0). + eapply LE_HaltsAtES_2; eauto. + exact Hhalt'. - assert (Hhalt0: HaltsAt tm' n st). { eapply LE_HaltsAtES_1; eauto. } assert (n = n0) by (eapply HaltsAt_unique; eauto). lia. Qed.
Lemma HaltTimeUpperBound_LE_HaltAtES_MergeUnusedState tm n s t (P:St->Prop) BB: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> n<=BB -> ((exists s0, P s0 /\ UnusedState tm s0) \/ (forall s0, ~UnusedState tm s0)) -> (forall s0, ~UnusedState tm s0 -> P s0) -> (forall tr, P (nxt _ tr) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)))) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ tm).
Proof. intros. destruct H2 as [H2|H2]. - eapply HaltTimeUpperBound_LE_Halt; eauto 1. 1: apply Σ_eqb_spec. intro. destruct (UnusedState_dec tm (nxt _ tr)) as [H5|H5]. + destruct H2 as [s0 [H2a H2b]]. destruct tr as [s1 d1 o1]. cbn in H5. eapply HaltTimeUpperBound_LE_HaltsAtES_UnusedState. * apply H. * apply H0. * apply H2b. * apply H5. * apply H4,H2a. + apply H4,H3,H5. - eapply HaltTimeUpperBound_LE_Halt; eauto 1. 1: apply Σ_eqb_spec. intro. apply H4,H3,H2. Qed.
Lemma HaltTimeUpperBound_LE_HaltAtES_MergeUnusedState tm n s t (P:St->Prop) BB: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> n<=BB -> ((exists s0, P s0 /\ UnusedState tm s0) \/ (forall s0, ~UnusedState tm s0)) -> (forall s0, ~UnusedState tm s0 -> P s0) -> (forall tr, P (nxt _ tr) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)))) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ tm).
Proof. intros Hhalt Hsteps Hle Hdisj Hndead Hext. apply (HaltTimeUpperBound_LE_Halt Σ BB Σ_eqb Σ_eqb_spec (InitES Σ Σ0) tm n s t); auto. intros tr. destruct (UnusedState_dec tm (nxt _ tr)) as [Hdead|Hndead2]. - destruct Hdisj as [[s0 [Hs0P Hs0D]]|Hallnd]. + destruct tr as [s_tr d_tr o_tr]. simpl in *. apply (HaltTimeUpperBound_LE_HaltsAtES_UnusedState Hhalt Hsteps s0 s_tr d_tr o_tr Hs0D Hdead). apply Hext. simpl. exact Hs0P. + exfalso. apply (Hallnd (nxt _ tr)). exact Hdead. - apply Hext. apply Hndead. exact Hndead2. Qed.
Lemma HaltTimeUpperBound_LE_HaltAtES_UnusedState_ptr {tm n s t s1 BB}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> n<=BB -> UnusedState_ptr tm s1 -> (forall tr, St_le s1 (nxt _ tr) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)))) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ tm).
Proof. intros. destruct H2 as [H2|H2]. - eapply HaltTimeUpperBound_LE_HaltAtES_MergeUnusedState with (P:=St_le s1); eauto 1. + left. exists s1. rewrite H2. split; unfold St_le; lia. + intros. rewrite H2 in H4. unfold St_le. unfold St_le in H4. lia. - destruct H2 as [H2a H2b]. eapply HaltTimeUpperBound_LE_HaltAtES_MergeUnusedState with (P:=St_le s1); eauto 1. tauto. Qed.
Lemma HaltTimeUpperBound_LE_HaltAtES_UnusedState_ptr {tm n s t s1 BB}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> n<=BB -> UnusedState_ptr tm s1 -> (forall tr, St_le s1 (nxt _ tr) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)))) -> HaltTimeUpperBound _ BB (InitES Σ Σ0) (LE _ tm).
Proof. intros Hhalt Hsteps Hle Hlsn Hext. apply (HaltTimeUpperBound_LE_HaltAtES_MergeUnusedState tm n s t (fun s0 => St_le s1 s0) BB); auto. - destruct Hlsn as [Hiff|[Hallnd Hmax]]. + destruct (UnusedState_dec tm s1) as [Hdead|Hndead]. * left. exists s1. split. unfold St_le. lia. exact Hdead. * exfalso. apply Hndead. apply (proj2 (Hiff s1)). unfold St_le. lia. + right. exact Hallnd. - intros s0 Hndead. destruct Hlsn as [Hiff|[_ Hmax]]. + destruct (UnusedState_dec tm s0) as [Hdead|_]. * exfalso. apply Hndead. exact Hdead. * unfold St_le. destruct (Hiff s0) as [_ Hback]. assert (Hn: ~St_le s0 s1). { intro Hc. apply Hndead. apply Hback. exact Hc. } unfold St_le in Hn. lia. + apply Hmax. Qed.
Lemma HaltTimeUpperBound_LE_HaltsAtES_UnusedState{tm n s t bb}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> forall s1 s2 d o, UnusedState tm s1 -> UnusedState tm s2 -> HaltTimeUpperBound _ bb (InitES Σ Σ0) (LE Σ (TM_upd Σ Σ_eqb tm s (t Z0) (Some {| nxt:=s1; dir:=d; out:=o |}))) -> HaltTimeUpperBound _ bb (InitES Σ Σ0) (LE Σ (TM_upd Σ Σ_eqb tm s (t Z0) (Some {| nxt:=s2; dir:=d; out:=o |}))).
Proof. intros. St_eq_dec s1 s2; rename H4 into n0. 1: subst; auto 1. pose proof (Steps_UnusedState H0) as H'0. assert (U1:s1<>s) by (intro X; subst; contradiction). assert (U2:s2<>s) by (intro X; subst; contradiction). destruct H1 as [H1a [H1b H1c]]. destruct H2 as [H2a [H2b H2c]]. assert (H':TM_swap Σ s1 s2 (TM_upd Σ Σ_eqb tm s (t 0%Z) (Some {| nxt := s1; dir := d; out := o |})) = (TM_upd Σ Σ_eqb tm s (t 0%Z) (Some {| nxt := s2; dir := d; out := o |}))). { fext. fext. unfold TM_upd,TM_swap,option_Trans_swap. cbn. unfold St_swap. cbn. St_eq_dec s1 x. { subst. St_eq_dec s2 s; cg. cbn. rewrite H1b,H2b. St_eq_dec x s; cg. cbn. cg. } St_eq_dec s2 x. { subst. St_eq_dec s1 s; cg. cbn. rewrite H1b,H2b. St_eq_dec x s; cg. cbn. cg. } St_eq_dec x s. { subst. cbn. (Σ_eq_dec x0 (t Z0)). - subst. f_equal. cbn. f_equal. unfold St_swap. St_eq_dec s1 s1; cg. - specialize (H1a s x0). specialize (H2a s x0). destruct (tm s x0) as [[s' d1 o1]|]; cg. f_equal. cbn in H1a,H2a. erewrite <-Trans_swap_id; eauto 1. } cbn. specialize (H1a x x0). specialize (H2a x x0). destruct (tm x x0) as [[s' d1 o1]|]; cg. f_equal. cbn in H1a,H2a. erewrite <-Trans_swap_id; eauto 1. } rewrite <-H'. apply HaltTimeUpperBound_LE_swap_InitES; assumption. Qed.
Lemma HaltTimeUpperBound_LE_HaltsAtES_UnusedState{tm n s t bb}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> forall s1 s2 d o, UnusedState tm s1 -> UnusedState tm s2 -> HaltTimeUpperBound _ bb (InitES Σ Σ0) (LE Σ (TM_upd Σ Σ_eqb tm s (t Z0) (Some {| nxt:=s1; dir:=d; out:=o |}))) -> HaltTimeUpperBound _ bb (InitES Σ Σ0) (LE Σ (TM_upd Σ Σ_eqb tm s (t Z0) (Some {| nxt:=s2; dir:=d; out:=o |}))).
Proof. intros Hhalt Hsteps sa sb d o Hdead_a Hdead_b Hbb. pose proof (St_eqb_spec sa sb) as Eab_spec. destruct (St_eqb sa sb) eqn:Eab. - subst. exact Hbb. - set (tm' := TM_upd Σ Σ_eqb tm s (t Z0) (Some {| nxt := sa; dir := d; out := o |})). set (tm'' := TM_upd Σ Σ_eqb tm s (t Z0) (Some {| nxt := sb; dir := d; out := o |})). destruct Hdead_a as [Hnxt_a [Hfrom_a Hneq0_a]]. destruct Hdead_b as [Hnxt_b [Hfrom_b Hneq0_b]]. pose proof (Steps_UnusedState Hsteps) as Hnd_s. assert (Hneq_sa_s: sa <> s). { intro Heq. subst. apply Hnd_s. split; [|split]; assumption. } assert (Hneq_sb_s: sb <> s). { intro Heq. subst. apply Hnd_s. split; [|split]; assumption. } assert (Hlav_sa_s: St_eqb sa s = false). { pose proof (St_eqb_spec sa s). destruct (St_eqb sa s); [exfalso; apply Hneq_sa_s; assumption|reflexivity]. } assert (Hlav_sb_s: St_eqb sb s = false). { pose proof (St_eqb_spec sb s). destruct (St_eqb sb s); [exfalso; apply Hneq_sb_s; assumption|reflexivity]. } assert (HLE: LE Σ (TM_swap Σ sa sb tm') tm''). { intros s0 i0. unfold TM_swap, option_Trans_swap, Trans_swap, St_swap, tm', tm'', TM_upd. pose proof (St_eqb_spec sa s0) as Ha0. destruct (St_eqb sa s0) eqn:Eas0. - subst s0. rewrite Hlav_sb_s. destruct (andb (St_eqb sb s) (Σ_eqb i0 (t Z0))); simpl. + right. rewrite (Hfrom_b i0). reflexivity. + right. rewrite (Hfrom_b i0). reflexivity. - pose proof (St_eqb_spec sb s0) as Hb0. destruct (St_eqb sb s0) eqn:Ebs0. + subst s0. rewrite Hlav_sa_s. destruct (andb (St_eqb sa s) (Σ_eqb i0 (t Z0))); simpl. * right. rewrite (Hfrom_a i0). reflexivity. * right. rewrite (Hfrom_a i0). reflexivity. + destruct (andb (St_eqb s0 s) (Σ_eqb i0 (t Z0))) eqn:Econd. * simpl. pose proof (St_eqb_spec sa sa) as Haa. destruct (St_eqb sa sa) eqn:Eaa. -- left. reflexivity. -- exfalso. apply Haa. reflexivity. * destruct (tm s0 i0) as [[s' d0 o0]|] eqn:Etm. -- simpl. left. f_equal. specialize (Hnxt_a s0 i0). rewrite Etm in Hnxt_a. simpl in Hnxt_a. specialize (Hnxt_b s0 i0). rewrite Etm in Hnxt_b. simpl in Hnxt_b. pose proof (St_eqb_spec sa s') as Has'. destruct (St_eqb sa s'). ++ exfalso. apply Hnxt_a. symmetry. exact Has'. ++ pose proof (St_eqb_spec sb s') as Hbs'. destruct (St_eqb sb s'). ** exfalso. apply Hnxt_b. symmetry. exact Hbs'. ** reflexivity. -- simpl. left. reflexivity. } assert (Hbb2: HaltTimeUpperBound Σ bb (InitES Σ Σ0) (LE Σ (TM_swap Σ sa sb tm'))). { apply (@HaltTimeUpperBound_LE_swap_InitES Σ Σ0 bb sa sb Eab_spec Hneq0_a Hneq0_b). exact Hbb. } intros tmx n0 HLEx Hhaltx. apply (Hbb2 tmx n0). + intros s0 i0. destruct (HLE s0 i0) as [Heq|Hnone]. * destruct (HLEx s0 i0) as [Heq2|Hnone2]. -- left. rewrite <- Heq2. exact Heq. -- right. rewrite <- Hnone2. exact Heq. * right. exact Hnone. + exact Hhaltx. Qed.
Lemma HaltTimeUpperBound_LE_NonHalt {st tm}: ~Halts tm st -> HaltTimeUpperBound st (LE tm).
Proof. unfold HaltTimeUpperBound. intros. pose proof (LE_NonHalts H0 H) as H2. assert False by (apply H2; eexists; apply H1). contradiction. Qed.
Lemma HaltTimeUpperBound_LE_NonHalt {st tm}: ~Halts tm st -> HaltTimeUpperBound st (LE tm).
Proof. intros Hnhalt tm' n0 Hle Hhalt. exfalso. apply (LE_NonHalts Hle Hnhalt). exists n0. exact Hhalt. Qed.
Lemma HaltTimeUpperBound_LE_rev tm st: HaltTimeUpperBound st (LE tm) -> HaltTimeUpperBound (ExecState_rev st) (LE (TM_rev tm)).
Proof. unfold HaltTimeUpperBound. intros. rewrite LE_rev,TM_rev_rev in H0. eapply H. 1: apply H0. rewrite <-ExecState_rev_rev. rewrite <-HaltsAt_rev. apply H1. Qed.
Lemma HaltTimeUpperBound_LE_rev tm st: HaltTimeUpperBound st (LE tm) -> HaltTimeUpperBound (ExecState_rev st) (LE (TM_rev tm)).
Proof. unfold HaltTimeUpperBound. intros Hbb tm0 n0 HLE Hhalt. apply (Hbb (TM_rev tm0) n0). - apply LE_rev. rewrite TM_rev_rev. exact HLE. - apply HaltsAt_rev in Hhalt. rewrite ExecState_rev_rev in Hhalt. exact Hhalt. Qed.
Lemma HaltTimeUpperBound_LE_rev_InitES tm: HaltTimeUpperBound InitES (LE tm) -> HaltTimeUpperBound InitES (LE (TM_rev tm)).
Proof. intro. rewrite <-InitES_rev. apply HaltTimeUpperBound_LE_rev,H. Qed.
Lemma HaltTimeUpperBound_LE_rev_InitES tm: HaltTimeUpperBound InitES (LE tm) -> HaltTimeUpperBound InitES (LE (TM_rev tm)).
Proof. rewrite <- InitES_rev at 2. apply HaltTimeUpperBound_LE_rev. Qed.
Lemma HaltTimeUpperBound_LE_swap tm st: HaltTimeUpperBound st (LE tm) -> HaltTimeUpperBound (ExecState_swap st) (LE (TM_swap tm)).
Proof. unfold HaltTimeUpperBound. intros. rewrite LE_swap,TM_swap_swap in H0. eapply H. 1: apply H0. rewrite <-ExecState_swap_swap. rewrite <-HaltsAt_swap. apply H1. Qed.
Lemma HaltTimeUpperBound_LE_swap tm st: HaltTimeUpperBound st (LE tm) -> HaltTimeUpperBound (ExecState_swap st) (LE (TM_swap tm)).
Proof. unfold HaltTimeUpperBound. intros Hbb tm0 n0 HLE Hhalt. apply (Hbb (TM_swap tm0) n0). - apply LE_swap. rewrite TM_swap_swap. exact HLE. - apply HaltsAt_swap in Hhalt. rewrite ExecState_swap_swap in Hhalt. exact Hhalt. Qed.
Lemma HaltTimeUpperBound_LE_swap_InitES tm: HaltTimeUpperBound InitES (LE tm) -> HaltTimeUpperBound InitES (LE (TM_swap tm)).
Proof. intro. rewrite <-InitES_swap. apply HaltTimeUpperBound_LE_swap,H. Qed.
Lemma HaltTimeUpperBound_LE_swap_InitES tm: HaltTimeUpperBound InitES (LE tm) -> HaltTimeUpperBound InitES (LE (TM_swap tm)).
Proof. rewrite <- InitES_swap at 2. apply HaltTimeUpperBound_LE_swap. Qed.
Lemma HaltsAtES_Trans {tm n st s t}: HaltsAt Σ tm n st -> Steps Σ tm n st (s, t) -> tm s (t Z0) = None.
Proof. intros. destruct H as [[s0 t0] [Ha Hb]]. pose proof (Steps_unique _ Ha H0) as H. invst H. unfold step in Hb. destruct (tm s (t Z0)); cg. destruct t0; cg. Qed.
Lemma HaltsAtES_Trans {tm n st s t}: HaltsAt Σ tm n st -> Steps Σ tm n st (s, t) -> tm s (t Z0) = None.
Proof. intros [st' [Hsteps Hhalt]] Hsteps2. pose proof (@Steps_unique _ _ _ _ _ _ Hsteps2 Hsteps) as Heq. subst st'. simpl in Hhalt. destruct (tm s (t Z0)) eqn:E. - destruct t0 as [s' d o]. discriminate. - reflexivity. Qed.
Lemma HaltsAt_rev tm n st: HaltsAt tm n st <-> HaltsAt (TM_rev tm) n (ExecState_rev st).
Proof. split. - apply HaltsAt_rev_0. - pose proof (HaltsAt_rev_0 (TM_rev tm) n (ExecState_rev st)) as H. rewrite TM_rev_rev,ExecState_rev_rev in H. apply H. Qed.
Lemma HaltsAt_rev tm n st: HaltsAt tm n st <-> HaltsAt (TM_rev tm) n (ExecState_rev st).
Proof. split. - apply HaltsAt_rev_0. - intro H. rewrite <- (ExecState_rev_rev st). rewrite <- (TM_rev_rev tm). apply HaltsAt_rev_0. exact H. Qed.
Lemma HaltsAt_rev_0 tm n st: HaltsAt tm n st -> HaltsAt (TM_rev tm) n (ExecState_rev st).
Proof. unfold HaltsAt. intros. destruct H as [st' [H H0]]. eexists. split. - rewrite Steps_rev. rewrite <-ExecState_rev_rev in H. rewrite ExecState_rev_rev. apply H. - rewrite step_halt_rev,ExecState_rev_rev. apply H0. Qed.
Lemma HaltsAt_rev_0 tm n st: HaltsAt tm n st -> HaltsAt (TM_rev tm) n (ExecState_rev st).
Proof. intro H. destruct H as [st' [Hsteps Hhalt]]. exists (ExecState_rev st'). split. - apply Steps_rev. rewrite ExecState_rev_rev. rewrite ExecState_rev_rev. exact Hsteps. - apply step_halt_rev. rewrite ExecState_rev_rev. exact Hhalt. Qed.
Lemma HaltsAt_swap tm n st: HaltsAt tm n st <-> HaltsAt (TM_swap tm) n (ExecState_swap st).
Proof. split. - apply HaltsAt_swap_0. - pose proof (HaltsAt_swap_0 (TM_swap tm) n (ExecState_swap st)) as H. rewrite TM_swap_swap,ExecState_swap_swap in H. apply H. Qed.
Lemma HaltsAt_swap tm n st: HaltsAt tm n st <-> HaltsAt (TM_swap tm) n (ExecState_swap st).
Proof. split. - apply HaltsAt_swap_0. - intro H. rewrite <- (ExecState_swap_swap st). rewrite <- (TM_swap_swap tm). apply HaltsAt_swap_0. exact H. Qed.
Lemma HaltsAt_swap_0 tm n st: HaltsAt tm n st -> HaltsAt (TM_swap tm) n (ExecState_swap st).
Proof. unfold HaltsAt. intros. destruct H as [st' [H H0]]. eexists. split. - rewrite Steps_swap. rewrite <-ExecState_swap_swap in H. rewrite ExecState_swap_swap. apply H. - rewrite step_halt_swap,ExecState_swap_swap. apply H0. Qed.
Lemma HaltsAt_swap_0 tm n st: HaltsAt tm n st -> HaltsAt (TM_swap tm) n (ExecState_swap st).
Proof. intro H. destruct H as [st' [Hsteps Hhalt]]. exists (ExecState_swap st'). split. - apply Steps_swap. rewrite ExecState_swap_swap. rewrite ExecState_swap_swap. exact Hsteps. - apply step_halt_swap. rewrite ExecState_swap_swap. exact Hhalt. Qed.
Lemma HaltsAt_unique {tm n1 n2 st}: HaltsAt tm n1 st -> HaltsAt tm n2 st -> n1=n2.
Proof. intros. pose proof H as H''. pose proof H0 as H0''. unfold HaltsAt in H,H0. pose proof H as H'. pose proof H0 as H0'. destruct H as [st0 [Ha Hb]]. destruct H0 as [st1 [H0a H0b]]. assert (n1=n2\/n1<n2\/n2<n1) by lia. destruct H as [H|[H|H]]; cg. - destruct (Steps_NonHalt H H0a H''). - destruct (Steps_NonHalt H Ha H0''). Qed.
Lemma HaltsAt_unique {tm n1 n2 st}: HaltsAt tm n1 st -> HaltsAt tm n2 st -> n1=n2.
Proof. intros [st1 [H1 Hhalt1]] [st2 [H2 Hhalt2]]. destruct (Nat.lt_trichotomy n1 n2) as [Hlt|[Heq|Hgt]]. - exfalso. eapply (Steps_NonHalt Hlt H2). exists st1. auto. - exact Heq. - exfalso. eapply (Steps_NonHalt Hgt H1). exists st2. auto. Qed.
Lemma In_RepWL_ES_InitES:
In_RepWL_ES (InitES Σ Σ0) RepWL_InitES.
Proof. unfold RepWL_InitES. replace (InitES Σ Σ0) with (St0,make_tape'' half_tape_all0 nil half_tape_all0 Dpos). 1: repeat ctor. unfold InitES. f_equal. fext. destruct x; cbn. 2,3: rewrite app_halftape_nil; unfold half_tape_cdr,half_tape_all0. all: reflexivity. Qed.
Lemma In_RepWL_ES_InitES:
In_RepWL_ES (InitES Σ Σ0) RepWL_InitES.
Proof. replace (InitES Σ Σ0) with (St0, make_tape'' half_tape_all0 nil half_tape_all0 Dpos). 2:{ unfold InitES, make_tape'', make_tape', make_tape, app_halftape, half_tape_all0, half_tape_cdr. f_equal. extensionality z. destruct z; simpl; try reflexivity. all: destruct (Nat.pred (Pos.to_nat p)); reflexivity. } apply (In_RepWL_ES_intro half_tape_all0 half_tape_all0 nil nil St0 Dpos); apply RepWL_match_O. Qed.
Lemma InitES_InAES_cond (S:AbstractES): let (ls,rs,ms):=S in ls (repeat Σ0 len_l) -> rs (repeat Σ0 len_r) -> ms {| l:=repeat Σ0 len_l; r:=repeat Σ0 len_r; m:=Σ0; s:=St0 |} -> InAES (InitES Σ Σ0) S.
Proof. destruct S as [ls rs ms]. intros. cbn. repeat split. - eexists. split. 1: apply H1. cbn. repeat split; cg; apply tape_seg__repeat_Σ0. - unfold xset_matches. intros. eexists. split. 1: apply H. apply tape_seg__repeat_Σ0. - unfold xset_matches. intros. eexists. split. 1: apply H0. apply tape_seg__repeat_Σ0. Qed.
Lemma InitES_InAES_cond (S:AbstractES): let (ls,rs,ms):=S in ls (repeat Σ0 len_l) -> rs (repeat Σ0 len_r) -> ms {| l:=repeat Σ0 len_l; r:=repeat Σ0 len_r; m:=Σ0; s:=St0 |} -> InAES (InitES Σ Σ0) S.
Proof. destruct S as [ls rs ms]. intros Hls Hrs Hms. unfold InAES, InitES. split; [|split]. - exists {| l:=repeat Σ0 len_l; r:=repeat Σ0 len_r; m:=Σ0; s:=St0 |}. split; [exact Hms|]. unfold MidWord_matches. simpl. repeat split. + rewrite (tape_seg__repeat_Σ0 (-1)%Z Dneg). reflexivity. + rewrite (tape_seg__repeat_Σ0 1%Z Dpos). reflexivity. - unfold xset_matches. intros n Hn. exists (repeat Σ0 len_l). split; [exact Hls|]. rewrite (tape_seg__repeat_Σ0 (Z.of_nat n * (-1))%Z Dneg). reflexivity. - unfold xset_matches. intros n Hn. exists (repeat Σ0 len_r). split; [exact Hrs|]. rewrite (tape_seg__repeat_Σ0 (Z.of_nat n * 1)%Z Dpos). reflexivity. Qed.
Lemma InitES_rev:
ExecState_rev InitES = InitES.
Proof. reflexivity. Qed.
Lemma InitES_rev:
ExecState_rev InitES = InitES.
Proof. unfold ExecState_rev, InitES, Tape_rev. reflexivity. Qed.
Lemma InitES_swap:
ExecState_swap InitES = InitES.
Proof. unfold InitES. cbn. f_equal. unfold St_swap. St_eq_dec s1 St0; try cg. St_eq_dec s2 St0; try cg. Qed.
Lemma InitES_swap:
ExecState_swap InitES = InitES.
Proof. unfold ExecState_swap, InitES, St_swap. pose proof (St_eqb_spec s1 St0) as H1. destruct (St_eqb s1 St0). - exfalso. apply Hneq01. assumption. - pose proof (St_eqb_spec s2 St0) as H2. destruct (St_eqb s2 St0). + exfalso. apply Hneq02. assumption. + reflexivity. Qed.
Lemma LE_HaltsAtES_1 {tm tm0 n st s t}: LE tm tm0 -> HaltsAt tm n st -> Steps tm n st (s,t) -> tm0 s (t 0%Z) = None -> HaltsAt tm0 n st.
Proof. intros. unfold HaltsAt. epose proof (LE_Steps H H1). exists (s,t). split. 1: assumption. cbn. rewrite H2. reflexivity. Qed.
Lemma LE_HaltsAtES_1 {tm tm0 n st s t}: LE tm tm0 -> HaltsAt tm n st -> Steps tm n st (s,t) -> tm0 s (t 0%Z) = None -> HaltsAt tm0 n st.
Proof. intros Hle [st' [Hsteps Hhalt]] Hsteps' Htm0. assert (st' = (s,t)) by (eapply Steps_unique; eassumption). subst. exists (s,t). split. - eapply LE_Steps; eauto. - simpl. rewrite Htm0. reflexivity. Qed.
Lemma LE_HaltsAtES_2 {tm tm0 n st s t tr}: LE tm tm0 -> HaltsAt tm n st -> Steps tm n st (s,t) -> tm0 s (t 0%Z) = Some tr -> LE (TM_upd tm s (t 0%Z) (Some tr)) tm0.
Proof. unfold LE. intros. unfold TM_upd. St_eq_dec s0 s. - Σ_eq_dec i (t Z0); cbn. + left; cg. + apply H. - apply H. Qed.
Lemma LE_HaltsAtES_2 {tm tm0 n st s t tr}: LE tm tm0 -> HaltsAt tm n st -> Steps tm n st (s,t) -> tm0 s (t 0%Z) = Some tr -> LE (TM_upd tm s (t 0%Z) (Some tr)) tm0.
Proof. intros Hle Hhalt Hsteps Htm0. intros s0 i0. unfold TM_upd. pose proof (St_eqb_spec s0 s) as Hs. destruct (St_eqb s0 s) eqn:Es. - subst. simpl. pose proof (Σ_eqb_spec i0 (t 0%Z)) as Hi. destruct (Σ_eqb i0 (t 0%Z)). + subst. left. symmetry. exact Htm0. + destruct (Hle s i0) as [Heq|Hnone]; auto. - simpl. destruct (Hle s0 i0) as [Heq|Hnone]; auto. Qed.
Lemma LE_NonHalts {tm tm' st}: LE tm tm' -> ~Halts tm st -> ~Halts tm' st.
Proof. repeat rewrite <-NonHalt_iff. unfold NonHalt. intros. destruct (H0 n) as [st' H1]. exists st'. eapply LE_Steps; eassumption. Qed.
Lemma LE_NonHalts {tm tm' st}: LE tm tm' -> ~Halts tm st -> ~Halts tm' st.
Proof. intros Hle Hnhalt. apply NonHalt_iff. apply NonHalt_iff in Hnhalt. intros n. destruct (Hnhalt n) as [stn Hstn]. exists stn. eapply LE_Steps; eauto. Qed.
Lemma LE_Steps {tm tm' n st st0}: LE tm tm' -> Steps tm n st st0 -> Steps tm' n st st0.
Proof. intros. induction H0. - ctor. - ector. 1: apply IHSteps,H. eapply LE_step; eassumption. Qed.
Lemma LE_Steps {tm tm' n st st0}: LE tm tm' -> Steps tm n st st0 -> Steps tm' n st st0.
Proof. intros Hle Hsteps. induction Hsteps. - constructor. - eapply steps_S; [exact (IHHsteps Hle) | eapply LE_step; eauto]. Qed.
Lemma LE_rev tm tm': LE tm tm' <-> LE (TM_rev tm) (TM_rev tm').
Proof. split. - apply LE_rev_0. - pose proof (LE_rev_0 (TM_rev tm) (TM_rev tm')) as H. repeat rewrite TM_rev_rev in H. apply H. Qed.
Lemma LE_rev tm tm': LE tm tm' <-> LE (TM_rev tm) (TM_rev tm').
Proof. split. - apply LE_rev_0. - intro H. rewrite <- (TM_rev_rev tm). rewrite <- (TM_rev_rev tm'). apply LE_rev_0. exact H. Qed.
Lemma LE_rev_0 tm tm': LE tm tm' -> LE (TM_rev tm) (TM_rev tm').
Proof. unfold LE. intros. unfold TM_rev. pose proof (H s i) as H0. destruct H0 as [H0|H0]; rewrite H0; tauto. Qed.
Lemma LE_rev_0 tm tm': LE tm tm' -> LE (TM_rev tm) (TM_rev tm').
Proof. intro HLE. unfold LE, TM_rev in *. intros s i. destruct (HLE s i) as [Heq|Hnone]. - left. rewrite Heq. reflexivity. - right. rewrite Hnone. reflexivity. Qed.
Lemma LE_step tm tm' st st0: LE tm tm' -> step tm st = Some st0 -> step tm' st = Some st0.
Proof. unfold LE,step. destruct st as [s t]. intros. specialize (H s (t Z0)). destruct (tm s (t Z0)) as [[s' d o]|]; cg. destruct H; cg. rewrite <-H. cg. Qed.
Lemma LE_step tm tm' st st0: LE tm tm' -> step tm st = Some st0 -> step tm' st = Some st0.
Proof. intros Hle Hstep. destruct st as [s t]. simpl in *. destruct (Hle s (t 0%Z)) as [Heq | Hnone]. - rewrite <- Heq. exact Hstep. - rewrite Hnone in Hstep. discriminate. Qed.
Lemma LE_swap tm tm': LE tm tm' <-> LE (TM_swap tm) (TM_swap tm').
Proof. split. - apply LE_swap_0. - pose proof (LE_swap_0 (TM_swap tm) (TM_swap tm')) as H. repeat rewrite TM_swap_swap in H. apply H. Qed.
Lemma LE_swap tm tm': LE tm tm' <-> LE (TM_swap tm) (TM_swap tm').
Proof. split. - apply LE_swap_0. - intro H. rewrite <- (TM_swap_swap tm). rewrite <- (TM_swap_swap tm'). apply LE_swap_0. exact H. Qed.
Lemma LE_swap_0 tm tm': LE tm tm' -> LE (TM_swap tm) (TM_swap tm').
Proof. unfold LE. intros. unfold TM_swap. specialize (H (St_swap s) i). destruct H as [H|H]; rewrite H; tauto. Qed.
Lemma LE_swap_0 tm tm': LE tm tm' -> LE (TM_swap tm) (TM_swap tm').
Proof. intro HLE. unfold LE, TM_swap in *. intros s i. destruct (HLE (St_swap s) i) as [Heq|Hnone]. - left. rewrite Heq. reflexivity. - right. rewrite Hnone. reflexivity. Qed.
Lemma ListES_Steps_spec tm n es: match ListES_Steps tm n es with | Some es0 => Steps _ tm n (ListES_toES es) (ListES_toES es0) | None => True end.
Proof. gd es. induction n. 1: intro; cbn; ctor. intro. cbn. destruct (tm (s es) (m es)) as [tr|] eqn:E. 2: trivial. destruct es as [l0 r0 m0 s0]. cbn in E. epose proof (ListES_step'_spec tm l0 r0 m0 s0) as H. rewrite E in H. specialize (IHn (ListES_step' tr {| l := l0; r := r0; m := m0; s := s0 |})). destruct (ListES_Steps tm n (ListES_step' tr {| l := l0; r := r0; m := m0; s := s0 |})). 2: trivial. replace (S n) with (n+1) by lia. eapply Steps_trans. 2: apply IHn. ector; eauto 1. ctor. Qed.
Lemma ListES_Steps_spec tm n es: match ListES_Steps tm n es with | Some es0 => Steps _ tm n (ListES_toES es) (ListES_toES es0) | None => True end.
Proof. revert es. induction n as [|n' IH]; intros es. - simpl. constructor. - destruct es as [l0 r0 m0 s0]. change (match (match tm s0 m0 with | Some tr => ListES_Steps tm n' (ListES_step' tr (Build_ListES l0 r0 m0 s0)) | None => None end) with | Some es0 => Steps _ tm (S n') (ListES_toES (Build_ListES l0 r0 m0 s0)) (ListES_toES es0) | None => True end). destruct (tm s0 m0) as [tr|] eqn:Etm; [|exact I]. specialize (IH (ListES_step' tr (Build_ListES l0 r0 m0 s0))). destruct (ListES_Steps tm n' (ListES_step' tr (Build_ListES l0 r0 m0 s0))) as [es0|]; [|exact I]. pose proof (ListES_step'_spec tm l0 r0 m0 s0) as Hspec. rewrite Etm in Hspec. assert (Hstep1: Steps Σ tm 1 (ListES_toES (Build_ListES l0 r0 m0 s0)) (ListES_toES (ListES_step' tr (Build_ListES l0 r0 m0 s0)))). { econstructor. econstructor. exact Hspec. } replace (S n') with (n' + 1) by lia. eapply Steps_trans; eauto. Qed.
Lemma ListES_step'_spec tm l0 r0 m0 s0: step Σ tm (ListES_toES (Build_ListES l0 r0 m0 s0)) = match tm s0 m0 with | Some tr => Some (ListES_toES (ListES_step' tr (Build_ListES l0 r0 m0 s0))) | None => None end.
Proof. erewrite (ListES_step_spec). cbn. destruct (tm s0 m0) as [[s1 d o]|]; reflexivity. Qed.
Lemma ListES_step'_spec tm l0 r0 m0 s0: step Σ tm (ListES_toES (Build_ListES l0 r0 m0 s0)) = match tm s0 m0 with | Some tr => Some (ListES_toES (ListES_step' tr (Build_ListES l0 r0 m0 s0))) | None => None end.
Proof. unfold step, ListES_toES, ListES_step'. destruct (tm s0 m0) as [[s1 d o]|]; [|reflexivity]. destruct d; [destruct l0 as [|m1 l1]|destruct r0 as [|m1 r1]]; f_equal; f_equal; extensionality z; unfold mov, upd, Dir_to_Z; destruct z as [|p|p]; try reflexivity. 1: { destruct p as [p|p|]; [ replace (Z.pos p~1 + Z.neg 1)%Z with (Z.pos p~0)%Z by lia; change ((Z.pos p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.pos p~0 + Z.neg 1)%Z with (Z.pos (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.pos (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } 1: { replace (Z.neg p + Z.neg 1)%Z with (Z.neg (p + 1))%Z by lia. change ((Z.neg (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. change (nth (S (Pos.to_nat p)) (m0 :: @nil Σ) Σ0) with (nth (Pos.to_nat p) (@nil Σ) Σ0). rewrite nth_Sigma0_nil. reflexivity. } 1: { destruct p as [p|p|]; [ replace (Z.pos p~1 + Z.neg 1)%Z with (Z.pos p~0)%Z by lia; change ((Z.pos p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.pos p~0 + Z.neg 1)%Z with (Z.pos (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.pos (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } 1: { replace (Z.neg p + Z.neg 1)%Z with (Z.neg (p + 1))%Z by lia. change ((Z.neg (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. simpl. reflexivity. } 1: { replace (Z.pos p + Z.pos 1)%Z with (Z.pos (p + 1))%Z by lia. change ((Z.pos (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. change (nth (S (Pos.to_nat p)) (m0 :: @nil Σ) Σ0) with (nth (Pos.to_nat p) (@nil Σ) Σ0). rewrite nth_Sigma0_nil. reflexivity. } 1: { destruct p as [p|p|]; [ replace (Z.neg p~1 + Z.pos 1)%Z with (Z.neg p~0)%Z by lia; change ((Z.neg p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.neg p~0 + Z.pos 1)%Z with (Z.neg (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.neg (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } 1: { replace (Z.pos p + Z.pos 1)%Z with (Z.pos (p + 1))%Z by lia. change ((Z.pos (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. simpl. reflexivity. } 1: { destruct p as [p|p|]; [ replace (Z.neg p~1 + Z.pos 1)%Z with (Z.neg p~0)%Z by lia; change ((Z.neg p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.neg p~0 + Z.pos 1)%Z with (Z.neg (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.neg (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } Qed.
Lemma ListES_step_spec tm x: step Σ tm (ListES_toES x) = match ListES_step tm x with | None => None | Some x1 => Some (ListES_toES x1) end.
Proof. destruct x as [l0 r0 m0 s0]. cbn. destruct (tm s0 m0) as [[s' d o]|]. 2: reflexivity. unfold mov,upd. destruct d; cbn. + destruct l0; cbn. * f_equal. f_equal. fext. assert (H:(x<0\/x=0\/x=1\/x>1)%Z) by lia. destruct H as [H|[H|[H|H]]]. -- destruct x; try lia. destruct ((Z.neg p + -1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p0) eqn:E0. 1: lia. destruct n,(Pos.to_nat p); auto 1. ++ destruct n; reflexivity. ++ destruct n0; reflexivity. -- subst. reflexivity. -- subst. reflexivity. -- destruct x; try lia. destruct ((Z.pos p + -1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p0) eqn:E0. 1: lia. assert (Pos.to_nat p = S (S n)) by lia. rewrite H0. reflexivity. * f_equal. f_equal. fext. assert (H:(x<0\/x=0\/x=1\/x>1)%Z) by lia. destruct H as [H|[H|[H|H]]]. -- destruct x; try lia. destruct ((Z.neg p + -1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p0) eqn:E0. 1: lia. assert (n=Pos.to_nat p) by lia. rewrite H0. reflexivity. -- subst. reflexivity. -- subst. reflexivity. -- destruct x; try lia. destruct ((Z.pos p + -1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p0) eqn:E0. 1: lia. assert (Pos.to_nat p = S (S n)) by lia. rewrite H0. reflexivity. + destruct r0; cbn. * f_equal. f_equal. fext. assert (H:(x>0\/x=0\/x=-1\/x<(-1))%Z) by lia. destruct H as [H|[H|[H|H]]]. -- destruct x; try lia. destruct ((Z.neg p + -1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p0) eqn:E0. 1: lia. destruct (Pos.to_nat (p + 1)) eqn:E1; try lia. destruct n0,(Pos.to_nat p); auto 1. ++ destruct n0; reflexivity. ++ destruct n1; reflexivity. -- subst. reflexivity. -- subst. reflexivity. -- destruct x; try lia. destruct ((Z.neg p + 1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p0) eqn:E0. 1: lia. assert (Pos.to_nat p = S (S n)) by lia. rewrite H0. reflexivity. * f_equal. f_equal. fext. assert (H:(x>0\/x=0\/x=-1\/x<(-1))%Z) by lia. destruct H as [H|[H|[H|H]]]. -- destruct x; try lia. destruct ((Z.pos p + 1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p) eqn:E0. 1: lia. assert (Pos.to_nat p0 = S (S n)) by lia. rewrite H0. reflexivity. -- subst. reflexivity. -- subst. reflexivity. -- destruct x; try lia. destruct ((Z.neg p + 1)%Z) eqn:E; cbn; try lia. destruct (Pos.to_nat p) eqn:E0. 1: lia. assert (n=Pos.to_nat p0) by lia. rewrite <-H0. destruct n. 1: lia. reflexivity. Qed.
Lemma ListES_step_spec tm x: step Σ tm (ListES_toES x) = match ListES_step tm x with | None => None | Some x1 => Some (ListES_toES x1) end.
Proof. destruct x as [l0 r0 m0 s0]. unfold step, ListES_toES, ListES_step. destruct (tm s0 m0) as [[s1 d o]|]; [|reflexivity]. destruct d; [destruct l0 as [|m1 l1]|destruct r0 as [|m1 r1]]; f_equal; f_equal; extensionality z; unfold mov, upd, Dir_to_Z; destruct z as [|p|p]; try reflexivity. 1: { destruct p as [p|p|]; [ replace (Z.pos p~1 + Z.neg 1)%Z with (Z.pos p~0)%Z by lia; change ((Z.pos p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.pos p~0 + Z.neg 1)%Z with (Z.pos (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.pos (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } 1: { replace (Z.neg p + Z.neg 1)%Z with (Z.neg (p + 1))%Z by lia. change ((Z.neg (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. change (nth (S (Pos.to_nat p)) (m0 :: @nil Σ) Σ0) with (nth (Pos.to_nat p) (@nil Σ) Σ0). rewrite nth_Sigma0_nil. reflexivity. } 1: { destruct p as [p|p|]; [ replace (Z.pos p~1 + Z.neg 1)%Z with (Z.pos p~0)%Z by lia; change ((Z.pos p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.pos p~0 + Z.neg 1)%Z with (Z.pos (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.pos (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } 1: { replace (Z.neg p + Z.neg 1)%Z with (Z.neg (p + 1))%Z by lia. change ((Z.neg (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. simpl. reflexivity. } 1: { replace (Z.pos p + Z.pos 1)%Z with (Z.pos (p + 1))%Z by lia. change ((Z.pos (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. change (nth (S (Pos.to_nat p)) (m0 :: @nil Σ) Σ0) with (nth (Pos.to_nat p) (@nil Σ) Σ0). rewrite nth_Sigma0_nil. reflexivity. } 1: { destruct p as [p|p|]; [ replace (Z.neg p~1 + Z.pos 1)%Z with (Z.neg p~0)%Z by lia; change ((Z.neg p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.neg p~0 + Z.pos 1)%Z with (Z.neg (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.neg (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } 1: { replace (Z.pos p + Z.pos 1)%Z with (Z.pos (p + 1))%Z by lia. change ((Z.pos (p+1) =? 0)%Z) with false. rewrite Pos2Nat.inj_add. change (Pos.to_nat 1) with 1. rewrite Nat.add_1_r. simpl. reflexivity. } 1: { destruct p as [p|p|]; [ replace (Z.neg p~1 + Z.pos 1)%Z with (Z.neg p~0)%Z by lia; change ((Z.neg p~0 =? 0)%Z) with false; apply nth_shift_eq; rewrite ?Pos2Nat.inj_xO, ?Pos2Nat.inj_xI; pose proof (Pos2Nat.is_pos p); lia | replace (Z.neg p~0 + Z.pos 1)%Z with (Z.neg (Pos.pred_double p))%Z by (rewrite Pos.pred_double_spec; lia); change ((Z.neg (Pos.pred_double p) =? 0)%Z) with false; apply nth_shift_eq; rewrite ?pos_to_nat_pred_double, ?Pos2Nat.inj_xO; pose proof (Pos2Nat.is_pos p); lia | simpl; reflexivity ]. } Qed.
Lemma ListES_toES_O:
(ListES_toES {| l := nil; r := nil; m := Σ0; s := St0 |}) = InitES Σ Σ0.
Proof. unfold InitES. cbn. f_equal. fext. destruct x. 1: reflexivity. - destruct (Pos.to_nat p). 1: reflexivity. destruct n; reflexivity. - destruct (Pos.to_nat p). 1: reflexivity. destruct n; reflexivity. Qed.
Lemma ListES_toES_O:
(ListES_toES {| l := nil; r := nil; m := Σ0; s := St0 |}) = InitES Σ Σ0.
Proof. unfold ListES_toES, InitES. f_equal. extensionality x. destruct x as [|p0|p0]; try reflexivity. - destruct (Pos.to_nat p0) eqn:E; [lia|]. simpl. destruct n; reflexivity. - destruct (Pos.to_nat p0) eqn:E; [lia|]. simpl. destruct n; reflexivity. Qed.
Lemma MidWord_enc_inj: is_inj MidWord_enc.
Proof. intros x1 x2 H. destruct x1 as [l1 r1 m1 s1]. destruct x2 as [l2 r2 m2 s2]. unfold MidWord_enc in H. pose proof (enc_list_inj _ _ H). clear H. invst H0. rewrite (St_enc_inj _ _ H1). rewrite (Σ_enc_inj _ _ H2). rewrite (listΣ_enc_inj _ _ H3). rewrite (listΣ_enc_inj _ _ H4). reflexivity. Qed.
Lemma MidWord_enc_inj: is_inj MidWord_enc.
Proof. unfold is_inj, MidWord_enc. intros [la ra ma sa] [lb rb mb sb]. intro H. apply enc_list_inj in H. simpl in H. injection H as Hs Hm Hl Hr. apply St_enc_inj in Hs. apply Σ_enc_inj in Hm. apply listΣ_enc_inj in Hl. apply listΣ_enc_inj in Hr. subst. reflexivity. Qed.
Lemma MoveDist_Steps {tm n st st0 d}: MoveDist tm n st st0 d -> Steps Σ tm n st st0.
Proof. intros. induction H. 1: ctor. ector; eauto 1. Qed.
Lemma MoveDist_Steps {tm n st st0 d}: MoveDist tm n st st0 d -> Steps Σ tm n st st0.
Proof. induction 1. - constructor. - eapply steps_S; eauto. Qed.
Lemma MoveDist_minus {tm n1 n2 st st0 st1 d d1}: MoveDist tm (n1+n2) st st0 d -> MoveDist tm n2 st st1 d1 -> MoveDist tm n1 st1 st0 (d-d1).
Proof. intros. destruct (MoveDist_split H) as [st3 [d3 [H1 H2]]]. destruct (MoveDist_unique H1 H0). cg. Qed.
Lemma MoveDist_minus {tm n1 n2 st st0 st1 d d1}: MoveDist tm (n1+n2) st st0 d -> MoveDist tm n2 st st1 d1 -> MoveDist tm n1 st1 st0 (d-d1).
Proof. intros H1 H2. apply MoveDist_split in H1. destruct H1 as [st1' [d1' [Hmd1 Hmd2]]]. pose proof (MoveDist_unique H2 Hmd1) as [Heq Hd]. subst. exact Hmd2. Qed.
Lemma MoveDist_split {tm n1 n2 st st0 d}: MoveDist tm (n1+n2) st st0 d -> exists st1 d1, MoveDist tm n2 st st1 d1 /\ MoveDist tm n1 st1 st0 (d-d1).
Proof. gd d. gd st0. induction n1; intros. - cbn in H. exists st0. exists d. split; auto 1. replace (d-d)%Z with 0%Z by lia. ctor. - cbn in H. invst H. specialize (IHn1 _ _ H1). destruct IHn1 as [st1 [d1 [IHn1a IHn1b]]]. exists st1. exists d1. split; auto 1. ector; eauto 1. rewrite <-H5. lia. Qed.
Lemma MoveDist_split {tm n1 n2 st st0 d}: MoveDist tm (n1+n2) st st0 d -> exists st1 d1, MoveDist tm n2 st st1 d1 /\ MoveDist tm n1 st1 st0 (d-d1).
Proof. revert st0 d. induction n1; intros st0 d H. - simpl in H. exists st0, d. split; [exact H|]. replace (d - d)%Z with Z0 by lia. constructor. - change (S n1 + n2) with (S (n1 + n2)) in H. inversion_clear H. destruct (IHn1 _ _ H0) as [st1 [d1 [Hmd1 Hmd2]]]. exists st1, d1. split; [exact Hmd1|]. eapply MoveDist_S; eauto. lia. Qed.
Lemma MoveDist_unique {tm n st0 st1 d st1' d'}: MoveDist tm n st0 st1 d -> MoveDist tm n st0 st1' d' -> (st1=st1' /\ d=d').
Proof. gd d'. gd st1'. gd d. gd st1. induction n. - intros. invst H. invst H0. tauto. - intros. invst H. invst H0. specialize (IHn _ _ _ _ H2 H5). destruct IHn as [IHn0 IHn1]. invst IHn0. rewrite H8 in H4. invst H4. rewrite H7 in H3. invst H3. repeat split. rewrite <-H10 in H6. lia. Qed.
Lemma MoveDist_unique {tm n st0 st1 d st1' d'}: MoveDist tm n st0 st1 d -> MoveDist tm n st0 st1' d' -> (st1=st1' /\ d=d').
Proof. intros H1. revert st1' d'. induction H1 as [|tm' n' st0' s1 t1 st2 d0 d1 tr H1' IH Hyzc Htm Hdist]; intros st1' d' H2. - inversion H2; subst. split; reflexivity. - inversion H2; subst. destruct (IH _ _ H0) as [Heq Hdeq]. inversion Heq; subst. rewrite Hyzc in H1. inversion H1; subst. rewrite Htm in H3. inversion H3; subst. split; [reflexivity | lia]. Qed.
Lemma NGramCPS_LRU_decider_0_spec len_l len_r m tm: NGramCPS_LRU_decider_0 len_l len_r m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro H. unfold NGramCPS_LRU_decider_0 in H. eapply TM_history_LRU_NonHaltsFromInit. eapply NGramCPS_decider_spec. 3: apply H. - apply Σ_history_enc_inj. - apply listT_enc_inj,Σ_history_enc_inj. Qed.
Lemma NGramCPS_LRU_decider_0_spec len_l len_r m tm: NGramCPS_LRU_decider_0 len_l len_r m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro H. unfold NGramCPS_LRU_decider_0 in H. apply TM_history_LRU_NonHaltsFromInit. exact (NGramCPS_decider_spec Σ_history len_l len_r Σ_history_enc Σ_history_enc_inj (listT_enc Σ_history_enc) (listT_enc_inj Σ_history_enc Σ_history_enc_inj) Σ_history_0 m (TM_history_LRU tm) H). Qed.
Lemma NGramCPS_LRU_decider_spec len_l len_r m BB:
HaltDecider_WF BB (NGramCPS_LRU_decider len_l len_r m).
Proof. intros tm. unfold NGramCPS_LRU_decider. pose proof (NGramCPS_LRU_decider_0_spec len_l len_r m tm). destruct (NGramCPS_LRU_decider_0 len_l len_r m tm); tauto. Qed.
Lemma NGramCPS_LRU_decider_spec len_l len_r m BB:
HaltDecider_WF BB (NGramCPS_LRU_decider len_l len_r m).
Proof. unfold HaltDecider_WF, NGramCPS_LRU_decider. intro tm. destruct (NGramCPS_LRU_decider_0 len_l len_r m tm) eqn:E; [|trivial]. apply NGramCPS_LRU_decider_0_spec in E. exact E. Qed.
Lemma NGramCPS_decider_0_spec m n tm S: AES_impl_WF S -> NGramCPS_decider_0 m n tm S = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. gd S. gd n. induction m; intros. 1: cbn in H0; cg. cbn in H0. destruct (update_AES tm (fst (mset' S)) S true n) as [[S' flag] n0_] eqn:E. epose proof (update_AES_Closed _ _ _ _ H) as H1. rewrite E in H1. destruct H1 as [H1a H1b]. pose proof (check_InitES_InAES_spec S' H1a). destruct flag. - specialize (H1b eq_refl). destruct H1b as [H1b H1c]. specialize (H1 H0). subst. apply (AES_Closed_NonHalt _ _ _ H1 H1b). - eapply IHm. + apply H1a. + apply H0. Qed.
Lemma NGramCPS_decider_0_spec m n tm S: AES_impl_WF S -> NGramCPS_decider_0 m n tm S = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. revert n S. induction m as [|m' IH]; intros n S HSI Hgp. - simpl in Hgp. discriminate. - simpl in Hgp. pose proof (update_AES_Closed tm S true n HSI) as Hhp. destruct (update_AES tm (fst (mset' S)) S true n) as [[S' flag'] n0] eqn:Es. destruct Hhp as [HSI' Hhp2]. destruct flag'. + destruct (Hhp2 eq_refl) as [Hadtw Heq]. subst S'. assert (Hp9: InAES (InitES Σ Σ0) (AES_impl_to_AES S)). { apply check_InitES_InAES_spec; assumption. } unfold HaltsFromInit. apply (AES_Closed_NonHalt tm (AES_impl_to_AES S)). exact Hp9. exact Hadtw. + apply (IH n0 S' HSI' Hgp). Qed.
Lemma NGramCPS_decider_impl1_0_spec len_h len_l len_r m tm: NGramCPS_decider_impl1_0 len_h len_l len_r m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro H. unfold NGramCPS_decider_impl1_0 in H. eapply TM_history_NonHaltsFromInit. eapply NGramCPS_decider_spec. 3: apply H. - apply Σ_history_enc_inj. - apply listT_enc_inj,Σ_history_enc_inj. Qed.
Lemma NGramCPS_decider_impl1_0_spec len_h len_l len_r m tm: NGramCPS_decider_impl1_0 len_h len_l len_r m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro H. unfold NGramCPS_decider_impl1_0 in H. apply TM_history_NonHaltsFromInit with (n:=len_h). exact (NGramCPS_decider_spec Σ_history len_l len_r Σ_history_enc Σ_history_enc_inj (listT_enc Σ_history_enc) (listT_enc_inj Σ_history_enc Σ_history_enc_inj) Σ_history_0 m (TM_history len_h tm) H). Qed.
Lemma NGramCPS_decider_impl1_spec len_h len_l len_r m BB:
HaltDecider_WF BB (NGramCPS_decider_impl1 len_h len_l len_r m).
Proof. intros tm. unfold NGramCPS_decider_impl1. pose proof (NGramCPS_decider_impl1_0_spec len_h len_l len_r m tm). destruct (NGramCPS_decider_impl1_0 len_h len_l len_r m tm); tauto. Qed.
Lemma NGramCPS_decider_impl1_spec len_h len_l len_r m BB:
HaltDecider_WF BB (NGramCPS_decider_impl1 len_h len_l len_r m).
Proof. unfold HaltDecider_WF, NGramCPS_decider_impl1. intro tm. destruct (NGramCPS_decider_impl1_0 len_h len_l len_r m tm) eqn:E; [|trivial]. apply NGramCPS_decider_impl1_0_spec in E. exact E. Qed.
Lemma NGramCPS_decider_impl2_0_spec len_l len_r m tm: NGramCPS_decider_impl2_0 len_l len_r m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro H. unfold NGramCPS_decider_impl2_0 in H. eapply NGramCPS_decider_spec; eauto 1. - apply Σ_enc_inj. - apply listΣ_inj. Qed.
Lemma NGramCPS_decider_impl2_0_spec len_l len_r m tm: NGramCPS_decider_impl2_0 len_l len_r m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro H. unfold NGramCPS_decider_impl2_0 in H. exact (NGramCPS_decider_spec Σ len_l len_r Σ_enc Σ_enc_inj listΣ_enc listΣ_inj Σ0 m tm H). Qed.
Lemma NGramCPS_decider_impl2_spec len_l len_r m BB:
HaltDecider_WF BB (NGramCPS_decider_impl2 len_l len_r m).
Proof. intros tm. unfold NGramCPS_decider_impl2. pose proof (NGramCPS_decider_impl2_0_spec len_l len_r m tm). destruct (NGramCPS_decider_impl2_0 len_l len_r m tm); tauto. Qed.
Lemma NGramCPS_decider_impl2_spec len_l len_r m BB:
HaltDecider_WF BB (NGramCPS_decider_impl2 len_l len_r m).
Proof. unfold HaltDecider_WF, NGramCPS_decider_impl2. intro tm. destruct (NGramCPS_decider_impl2_0 len_l len_r m tm) eqn:E; [|trivial]. apply NGramCPS_decider_impl2_0_spec in E. exact E. Qed.
Lemma NGramCPS_decider_spec m tm: NGramCPS_decider m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. unfold NGramCPS_decider. destruct len_l as [|nl]; destruct len_r as [|nr]; cg. apply NGramCPS_decider_0_spec. split. { destruct ((xset_ins (PositiveMap.empty (list Σ * PositiveMap.tree unit)) (repeat Σ0 (S nl)))) as [ls' flag] eqn:E. apply (xset_ins_spec _ _ _ _ _ xset_WF_empty E). } split. { destruct ((xset_ins (PositiveMap.empty (list Σ * PositiveMap.tree unit)) (repeat Σ0 (S nr)))) as [rs' flag] eqn:E. apply (xset_ins_spec _ _ _ _ _ xset_WF_empty E). } { destruct ((mset_ins0 (nil, PositiveMap.empty unit) {| l := repeat Σ0 (S nl); r := repeat Σ0 (S nr); m := Σ0; s := St0 |})) as [ms' flag] eqn:E. apply (mset_ins0_spec _ _ _ _ (empty_set_WF _) E). } Qed.
Lemma NGramCPS_decider_spec m tm: NGramCPS_decider m tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. unfold NGramCPS_decider. intro H. destruct len_l as [|nl]; [discriminate|]. destruct len_r as [|nr]; [discriminate|]. assert (wKw3H_init: forall xs n, xset_WF xs -> xset_WF (fst (xset_ins xs (repeat Σ0 (Datatypes.S n))))). { intros xs n0 Hwk. destruct (xset_ins xs (repeat Σ0 (Datatypes.S n0))) as [xs' fl] eqn:Eng. simpl. exact (proj1 (xset_ins_spec xs Σ0 (repeat Σ0 n0) xs' fl Hwk Eng)). } assert (gHKhe_init: forall ms mw, mset_WF ms -> mset_WF (fst (mset_ins0 ms mw))). { intros ms mw Hms. destruct (mset_ins0 ms mw) as [ms' fl] eqn:Ems. simpl. exact (proj1 (mset_ins0_spec ms mw ms' fl Hms Ems)). } eapply NGramCPS_decider_0_spec; [|exact H]. split; [|split]. - apply wKw3H_init. exact xset_WF_empty. - apply wKw3H_init. exact xset_WF_empty. - apply gHKhe_init. exact (empty_set_WF MidWord_enc). Qed.
Lemma NonHalt_iff {tm st}: NonHalt tm st <-> ~Halts tm st.
Proof. split; intro. - intro H0. destruct H0 as [n H0]. specialize (H (S n)). destruct H as [st' H]. eapply Steps_NonHalt. 2,3: eassumption. lia. - intro n. induction n. + eexists. ector. + destruct IHn as [st' IHn]. unfold Halts,HaltsAt in H. destruct (step tm st') as [st''|] eqn:E. * exists st''. ector; eassumption. * assert False by (apply H; eexists; eexists; split; eassumption). contradiction. Qed.
Lemma NonHalt_iff {tm st}: NonHalt tm st <-> ~Halts tm st.
Proof. unfold NonHalt, Halts, HaltsAt. split. - intros Hinf [n [st' [Hsteps Hhalt]]]. destruct (Hinf (S n)) as [st1 Hst1]. assert (Hex: exists stm, Steps tm n st stm /\ step tm stm = Some st1). { inversion Hst1; subst; eauto. } destruct Hex as [stm [Hstm Hstep]]. replace st' with stm in * by (eapply Steps_unique; eassumption). congruence. - intros Hnhalt n. induction n. + exists st. constructor. + destruct IHn as [stn Hstn]. destruct (step tm stn) eqn:E. * exists e. eapply steps_S; eauto. * exfalso. apply Hnhalt. exists n. exists stn. auto. Qed.
Lemma RepWL_ES_decider_spec n BB:
HaltDecider_WF BB (RepWL_ES_decider n).
Proof. eapply T_decider_spec. - apply RepWL_ES_enc_inj. - apply In_RepWL_ES_InitES. - apply RepWL_step_spec. Qed.
Lemma RepWL_ES_decider_spec n BB:
HaltDecider_WF BB (RepWL_ES_decider n).
Proof. unfold RepWL_ES_decider. apply (T_decider_spec _ RepWL_ES_enc RepWL_ES_enc_inj In_RepWL_ES RepWL_InitES In_RepWL_ES_InitES RepWL_step RepWL_step_spec). Qed.
Lemma RepWL_ES_enc_inj: is_inj RepWL_ES_enc.
Proof. intros x1 x2 H. destruct x1,x2. epose proof (enc_list_inj _ _ H). invst H0. f_equal. - eapply list_enc_inj; eauto 1. apply RepeatWord_enc_inj. - eapply list_enc_inj; eauto 1. apply RepeatWord_enc_inj. - apply St_enc_inj; auto 1. - apply Dir_enc_inj; auto 1. Qed.
Lemma RepWL_ES_enc_inj: is_inj RepWL_ES_enc.
Proof. intros [l1 r1 s1 sgn1] [l2 r2 s2 sgn2] H. unfold RepWL_ES_enc in H. apply enc_list_inj in H. injection H as H1 H2 H3 H4. apply Dir_enc_inj in H1. apply St_enc_inj in H2. apply (list_enc_inj RepeatWord_enc RepeatWord_enc_inj) in H3. apply (list_enc_inj RepeatWord_enc RepeatWord_enc_inj) in H4. subst. reflexivity. Qed.
Lemma RepWL_step00_spec tm x w0 r0: match RepWL_step00 tm x w0 r0 with | None => True | Some x1 => let (l0,_,s0,sgn0):=x in forall st0, In_RepWL_ES st0 {| l:=l0; r:=push' r0 w0; s:=s0; sgn:=sgn0 |} -> exists n st1, (Steps Σ tm (1+n) st0 st1 /\ In_RepWL_ES st1 x1) end.
Proof. unfold RepWL_step00. destruct x as [l0 r0' s0 sgn0]. pose proof (WordUpdate_spec tm s0 w0 sgn0). destruct (WordUpdate tm s0 w0 sgn0) as [[[s1 w1] d1]|]. 2: trivial. destruct d1 eqn:Ed1. - intros. destruct st0 as [s0' t0']. invst H0. destruct sgn0. + specialize (H l1 (halftape_skipn (length w0) r1)). destruct H as [n H]. cbn. cbn in H. exists n. exists (s1, make_tape'' (app_halftape w1 (halftape_skipn (length w0) r1)) nil (l1) Dpos). split. * unfold make_tape'' in H. destruct w0; cbn in H. ++ apply H. ++ replace (make_tape' (half_tape_cdr r1) nil (r1 0) nil l1) with (make_tape' (halftape_skipn (S (length w0)) r1) w0 σ nil l1). apply H. unfold make_tape'. invst H8. invst H3. rewrite <-app_halftape_assoc. cbn. f_equal. rewrite app_halftape_nil. apply app_halftape_skipn_cdr. * ector; eauto 1. invst H8. invst H3. invst H7. rewrite app_nil_r. apply push_spec. rewrite app_halftape_skipn. apply H6. + specialize (H l1 (halftape_skipn (length w0) r1)). destruct H as [n H]. cbn. cbn in H. exists n. exists (s1, make_tape'' (app_halftape w1 (halftape_skipn (length w0) r1)) nil (l1) Dneg). split. * unfold make_tape'' in H. destruct w0; cbn in H. ++ rewrite halftape_skipn_0 in H. rewrite halftape_skipn_0. unfold make_tape''. apply H. ++ replace (make_tape' l1 nil (r1 0) nil (half_tape_cdr r1)) with (make_tape' l1 nil σ w0 (halftape_skipn (S (length w0)) r1)). apply H. unfold make_tape'. invst H8. invst H3. rewrite <-app_halftape_assoc. cbn. f_equal. rewrite app_halftape_nil. apply app_halftape_skipn_cdr. * ector; eauto 1. invst H8. invst H3. invst H7. rewrite app_nil_r. apply push_spec. rewrite app_halftape_skipn. apply H6. - intros. destruct st0 as [s0' t0']. invst H0. destruct sgn0. + specialize (H l1 (halftape_skipn (length w0) r1)). destruct H as [n H]. cbn. cbn in H. exists n. exists (s1, make_tape'' (app_halftape w1 l1) nil (halftape_skipn (length w0) r1) Dneg). split. * unfold make_tape'' in H. destruct w0; cbn in H. ++ rewrite halftape_skipn_0 in H. rewrite halftape_skipn_0. unfold make_tape''. apply H. ++ replace (make_tape' (half_tape_cdr r1) nil (r1 0) nil l1) with (make_tape' (halftape_skipn (S (length w0)) r1) w0 σ nil l1). apply H. unfold make_tape'. repeat rewrite app_halftape_nil. invst H8. invst H3. rewrite <-app_halftape_assoc. cbn. f_equal. apply app_halftape_skipn_cdr. * invst H8. invst H3. invst H7. ector; eauto 1. -- apply push_spec,H4. -- rewrite app_nil_r,app_halftape_skipn. apply H6. + specialize (H l1 (halftape_skipn (length w0) r1)). destruct H as [n H]. cbn. cbn in H. exists n. exists (s1, make_tape'' (app_halftape w1 l1) nil (halftape_skipn (length w0) r1) Dpos). split. * unfold make_tape'' in H. destruct w0; cbn in H. ++ rewrite halftape_skipn_0 in H. rewrite halftape_skipn_0. unfold make_tape''. apply H. ++ replace (make_tape' l1 nil (r1 0) nil (half_tape_cdr r1)) with (make_tape' l1 nil σ w0 (halftape_skipn (S (length w0)) r1)). apply H. unfold make_tape'. repeat rewrite app_halftape_nil. invst H8. invst H3. rewrite <-app_halftape_assoc. cbn. f_equal. apply app_halftape_skipn_cdr. * invst H8. invst H3. invst H7. ector; eauto 1. -- apply push_spec,H4. -- rewrite app_nil_r,app_halftape_skipn. apply H6. Qed.
Lemma RepWL_step00_spec tm x w0 r0: match RepWL_step00 tm x w0 r0 with | None => True | Some x1 => let (l0,_,s0,sgn0):=x in forall st0, In_RepWL_ES st0 {| l:=l0; r:=push' r0 w0; s:=s0; sgn:=sgn0 |} -> exists n st1, (Steps Σ tm (1+n) st0 st1 /\ In_RepWL_ES st1 x1) end.
Proof. destruct x as [l0 r_ign s0 sgn0]. destruct w0 as [|m0 w2]. { simpl. exact I. } pose proof (WordUpdate_spec tm s0 (m0::w2) sgn0) as Hstep. unfold RepWL_step00. destruct (WordUpdate tm s0 (m0::w2) sgn0) as [[[s1 w1] is_back]|] eqn:ED. 2:{ exact I. } destruct is_back. - intros st0 HinR. inversion HinR as [l1 r1 ? ? ? ? Hml Hmr Hst_eq Hes_eq]. clear HinR. subst. inversion Hmr as [|h_rw t_rw fh ft Hrw_fh Hrw_ft Heq_r Heq_ft]. subst. clear Hmr. inversion Hrw_fh; subst; try (exfalso; congruence). match goal with H : RepW_match _ _ |- _ => inversion H; subst; try (exfalso; congruence); clear H end. specialize (Hstep l1 ft). destruct Hstep as [n Hsteps]. rewrite app_nil_r. rewrite tape_eq. exists n, (s1, make_tape'' (app_halftape w1 ft) nil l1 (Dir_rev sgn0)). split; [exact Hsteps|]. apply In_RepWL_ES_intro. -- apply push_spec. exact Hrw_ft. -- exact Hml. - intros st0 HinR. inversion HinR as [l1 r1 ? ? ? ? Hml Hmr Hst_eq Hes_eq]. clear HinR. subst. inversion Hmr as [|h_rw t_rw fh ft Hrw_fh Hrw_ft Heq_r Heq_ft]. subst. clear Hmr. inversion Hrw_fh; subst; try (exfalso; congruence). match goal with H : RepW_match _ _ |- _ => inversion H; subst; try (exfalso; congruence); clear H end. specialize (Hstep l1 ft). destruct Hstep as [n Hsteps]. rewrite app_nil_r. rewrite tape_eq. exists n, (s1, make_tape'' (app_halftape w1 l1) nil ft sgn0). split; [exact Hsteps|]. apply In_RepWL_ES_intro. -- apply push_spec. exact Hml. -- exact Hrw_ft. Qed.
Lemma RepWL_step0_spec tm x w0 r0: match RepWL_step0 tm x w0 r0 with | None => True | Some x1 => let (l0,_,s0,sgn0):=x in forall st0, (exists r1, In r1 r0 /\ In_RepWL_ES st0 {| l:=l0; r:=push' r1 w0; s:=s0; sgn:=sgn0 |}) -> exists n st1 x2, (Steps Σ tm (1+n) st0 st1 /\ In_RepWL_ES st1 x2 /\ In x2 x1) end.
Proof. induction r0. - cbn. destruct x as [l0 r0' s0 sgn0]. intros. destruct H as [n1 [Ha Hb]]. contradiction. - cbn. pose proof (RepWL_step00_spec tm x w0 a) as H. destruct (RepWL_step00 tm x w0 a). 2: trivial. destruct (RepWL_step0 tm x w0 r0). 2: trivial. destruct x as [l1 r0' s0 sgn0]. intros. destruct H0 as [r2 [H0a H0b]]. destruct H0a as [H0a|H0a]. + subst a. specialize (H st0 H0b). destruct H as [n [st1 [Ha Hb]]]. exists n. exists st1. eexists. repeat split; eauto 1. left. reflexivity. + specialize (IHr0 st0). eassert (H1:_). { apply IHr0. eexists. split; eauto 1. } destruct H1 as [n [st1 [x2 [H1a [H1b H1c]]]]]. exists n. exists st1. exists x2. repeat split; auto 1. right. auto 1. Qed.
Lemma RepWL_step0_spec tm x w0 r0: match RepWL_step0 tm x w0 r0 with | None => True | Some x1 => let (l0,_,s0,sgn0):=x in forall st0, (exists r1, In r1 r0 /\ In_RepWL_ES st0 {| l:=l0; r:=push' r1 w0; s:=s0; sgn:=sgn0 |}) -> exists n st1 x2, (Steps Σ tm (1+n) st0 st1 /\ In_RepWL_ES st1 x2 /\ In x2 x1) end.
Proof. destruct x as [l0 r_ignored s0 sgn0]. induction r0 as [|r1h r0t IH]. - simpl. intros st0 [r1 [Hin _]]. destruct Hin. - simpl RepWL_step0. pose proof (RepWL_step00_spec tm (Build_RepeatWordList_ES l0 r_ignored s0 sgn0) w0 r1h) as HV. simpl RepWL_step00 in HV. destruct (WordUpdate tm s0 w0 sgn0) as [[[s1 w1] is_back]|]; [|trivial]. destruct is_back. + specialize (IH). simpl in IH. destruct (RepWL_step0 tm (Build_RepeatWordList_ES l0 r_ignored s0 sgn0) w0 r0t) as [ret|]; [|trivial]. intros st0 [r1 [Hin HinR]]. destruct Hin as [Heq|Hin0]. * subst r1. specialize (HV st0 HinR). destruct HV as [n [st1 [Hsteps HinR1]]]. exists n, st1, {| l := push r1h w1; r := l0; s := s1; sgn := Dir_rev sgn0 |}. repeat split; [exact Hsteps|exact HinR1|left; reflexivity]. * specialize (IH st0). assert (Hex: exists r1, In r1 r0t /\ In_RepWL_ES st0 {| l := l0; r := push' r1 w0; s := s0; sgn := sgn0 |}). { exists r1. split; [exact Hin0|exact HinR]. } specialize (IH Hex). destruct IH as [n [st1 [x2 [Hsteps [HinR1 Hinx2]]]]]. exists n, st1, x2. repeat split; [exact Hsteps|exact HinR1|right; exact Hinx2]. + specialize (IH). simpl in IH. destruct (RepWL_step0 tm (Build_RepeatWordList_ES l0 r_ignored s0 sgn0) w0 r0t) as [ret|]; [|trivial]. intros st0 [r1 [Hin HinR]]. destruct Hin as [Heq|Hin0]. * subst r1. specialize (HV st0 HinR). destruct HV as [n [st1 [Hsteps HinR1]]]. exists n, st1, {| l := push l0 w1; r := r1h; s := s1; sgn := sgn0 |}. repeat split; [exact Hsteps|exact HinR1|left; reflexivity]. * specialize (IH st0). assert (Hex: exists r1, In r1 r0t /\ In_RepWL_ES st0 {| l := l0; r := push' r1 w0; s := s0; sgn := sgn0 |}). { exists r1. split; [exact Hin0|exact HinR]. } specialize (IH Hex). destruct IH as [n [st1 [x2 [Hsteps [HinR1 Hinx2]]]]]. exists n, st1, x2. repeat split; [exact Hsteps|exact HinR1|right; exact Hinx2]. Qed.
Lemma RepWL_step_spec tm x: match RepWL_step tm x with | None => True | Some ls => forall st0, In_RepWL_ES st0 x -> exists n st1 x1, (Steps Σ tm (1+n) st0 st1 /\ In_RepWL_ES st1 x1 /\ In x1 ls) end.
Proof. unfold RepWL_step. destruct x as [l0 r0 s0 sgn0]. pose proof (pop_spec r0) as H0. destruct (pop r0) as [[w0 ls]|] eqn:E. 2: trivial. pose proof (RepWL_step0_spec tm {| l := l0; r := r0; s := s0; sgn := sgn0 |} w0 ls) as H. destruct (RepWL_step0 tm {| l := l0; r := r0; s := s0; sgn := sgn0 |} w0 ls). 2: trivial. intros. specialize (H st0). apply H. invst H1. specialize (H0 _ H8). destruct H0 as [wl0 [f1 [H0a [H0b H0c]]]]. exists wl0. repeat split; auto 1. rewrite H0c. ector; eauto 1. rewrite <-app_nil_r. ctor. ctor. Qed.
Lemma RepWL_step_spec tm x: match RepWL_step tm x with | None => True | Some ls => forall st0, In_RepWL_ES st0 x -> exists n st1 x1, (Steps Σ tm (1+n) st0 st1 /\ In_RepWL_ES st1 x1 /\ In x1 ls) end.
Proof. destruct x as [l0 r0 s0 sgn0]. unfold RepWL_step. pose proof (pop_spec r0) as Hb. destruct (pop r0) as [[w0 ls0]|] eqn:Excj; [|exact I]. pose proof (RepWL_step0_spec tm (Build_RepeatWordList_ES l0 r0 s0 sgn0) w0 ls0) as Hckj. simpl in Hckj. destruct (RepWL_step0 tm (Build_RepeatWordList_ES l0 r0 s0 sgn0) w0 ls0) as [ret|] eqn:Ej; [|exact I]. intros st0 HinR. apply Hckj. inversion HinR as [l1 r1 l0' r0' s0' sgn0' Hl Hr Hst Hx]. subst. specialize (Hb r1 Hr). destruct Hb as [wl0 [f1 [Hinwl0 [Hmatch Heq]]]]. exists wl0. split; [exact Hinwl0|]. subst r1. unfold push'. assert (Hrmatch: RepWL_match ({| w := w0; min_cnt := 1; is_const := true |} :: wl0) (app_halftape w0 f1)). { replace (app_halftape w0 f1) with (app_halftape (w0 ++ nil) f1) by (rewrite app_nil_r; reflexivity). apply RepWL_match_S; [|exact Hmatch]. apply RepW_match_S0. apply RepW_match_O. } exact (In_RepWL_ES_intro l1 (app_halftape w0 f1) l0 ({| w := w0; min_cnt := 1; is_const := true |} :: wl0) s0 sgn0 Hl Hrmatch). Qed.
Lemma RepeatWord_enc_inj: is_inj RepeatWord_enc.
Proof. intros x1 x2 H. destruct x1,x2. epose proof (enc_list_inj _ _ H). invst H0. f_equal. - apply listΣ_inj; auto 1. - lia. - apply bool_enc_inj; auto 1. Qed.
Lemma RepeatWord_enc_inj: is_inj RepeatWord_enc.
Proof. intros [w1 mc1 isc1] [w2 mc2 isc2] H. unfold RepeatWord_enc in H. apply enc_list_inj in H. injection H as H1 H2 H3. apply listΣ_inj in H1. apply SuccNat2Pos.inj in H2. apply bool_enc_inj in H3. subst. reflexivity. Qed.
Lemma SearchQueue_bfs_spec q x0 f: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_bfs q f) x0.
Proof. intros. unfold SearchQueue_bfs. apply SearchQueue_reset_spec. apply SearchQueue_upds_bfs_spec; auto 1. Qed.
Lemma SearchQueue_bfs_spec q x0 f: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_bfs q f) x0.
Proof. intros Hq Hf. unfold SearchQueue_bfs. apply SearchQueue_reset_spec. apply SearchQueue_upds_bfs_spec; auto. Qed.
Lemma SearchQueue_reset_spec {q x0}: SearchQueue_WF q x0 -> SearchQueue_WF (SearchQueue_reset q) x0.
Proof. unfold SearchQueue_WF,SearchQueue_reset. destruct q as [q1 q2]. intro. split. - intros. apply H. rewrite app_nil_r in H0. apply H0. - intros. apply H. intros. apply H0. rewrite app_nil_r. apply H1. Qed.
Lemma SearchQueue_reset_spec {q x0}: SearchQueue_WF q x0 -> SearchQueue_WF (SearchQueue_reset q) x0.
Proof. destruct q as [q1 q2]. unfold SearchQueue_WF, SearchQueue_reset. intros [Hwf Himp]. split. - intros x Hx. rewrite app_nil_r in Hx. apply Hwf. apply in_or_app. apply in_app_or in Hx. destruct Hx; auto. - intros Hall. apply Himp. intros x Hx. apply Hall. rewrite app_nil_r. apply in_or_app. apply in_app_or in Hx. destruct Hx; auto. Qed.
Lemma SearchQueue_upd_bfs_spec {q x0 f}: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upd_bfs q f) x0.
Proof. intros. pose proof (SearchQueue_upd_spec H H0). unfold SearchQueue_WF. unfold SearchQueue_upd_bfs. unfold SearchQueue_WF in H1. unfold SearchQueue_upd in H1. destruct q as [q1 q2]. destruct q1 as [|h t]. 1: apply H1. destruct (f (TNF_tm h)); auto 1. assert ( forall x, In x ((TNF_Node_expand h s i ++ t) ++ q2) <-> In x (t ++ TNF_Node_expand h s i ++ q2) ). { intros. repeat rewrite in_app_iff. tauto. } split. - intro. rewrite <-H2. apply H1. - intro. apply H1. intros. apply H3; auto 1. rewrite <-H2. apply H4. Qed.
Lemma SearchQueue_upd_bfs_spec {q x0 f}: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upd_bfs q f) x0.
Proof. intros Hq Hf. destruct q as [q1 q2]. destruct q1 as [|h t]. - simpl. exact Hq. - simpl. unfold SearchQueue_WF in Hq. destruct Hq as [Hwf Himp]. specialize (Hf (TNF_tm h)) as Hfh. assert (Hwf_h: TNF_Node_WF h). { apply Hwf. apply in_or_app. left. left. reflexivity. } assert (Hwf_t: forall x, In x t -> TNF_Node_WF x). { intros x Hx. apply Hwf. apply in_or_app. left. right. exact Hx. } assert (Hwf_q2: forall x, In x q2 -> TNF_Node_WF x). { intros x Hx. apply Hwf. apply in_or_app. right. exact Hx. } destruct (f (TNF_tm h)) eqn:Ef; unfold SearchQueue_WF. + (* Result_Halt s i *) destruct Hfh as [n [t0 [Hhalt [Hsteps [Heqi Hle]]]]]. subst i. pose proof (TNF_Node_expand_spec Hhalt Hsteps Hle Hwf_h) as [Hwf_children Hchildren]. split. * intros x Hx. apply in_app_or in Hx. destruct Hx as [Hx|Hx]. -- apply Hwf_t. exact Hx. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hwf_children. exact Hx. ++ apply Hwf_q2. exact Hx. * intros Hall. apply Himp. intros x Hx. simpl in Hx. destruct Hx as [Heq|Hx]. -- subst x. apply Hchildren. intros x' Hx'. apply Hall. apply in_or_app. right. apply in_or_app. left. exact Hx'. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hall. apply in_or_app. left. exact Hx. ++ apply Hall. apply in_or_app. right. apply in_or_app. right. exact Hx. + (* Result_NonHalt *) split. * intros x Hx. apply in_app_or in Hx. destruct Hx as [Hx|Hx]. -- apply Hwf_t. exact Hx. -- apply Hwf_q2. exact Hx. * intros Hall. apply Himp. intros x Hx. simpl in Hx. destruct Hx as [Heq|Hx]. -- subst x. apply TNF_Node_NonHalt. exact Hfh. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hall. apply in_or_app. left. exact Hx. ++ apply Hall. apply in_or_app. right. exact Hx. + (* Result_Unknown *) split. * intros x Hx. apply in_app_or in Hx. destruct Hx as [Hx|Hx]. -- apply Hwf_t. exact Hx. -- simpl in Hx. destruct Hx as [Heq|Hx]. ++ subst x. exact Hwf_h. ++ apply Hwf_q2. exact Hx. * intros Hall. apply Himp. intros x Hx. simpl in Hx. destruct Hx as [Heq|Hx]. -- subst x. apply Hall. apply in_or_app. right. left. reflexivity. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hall. apply in_or_app. left. exact Hx. ++ apply Hall. apply in_or_app. right. right. exact Hx. Qed.
Lemma SearchQueue_upd_spec {q x0 f}: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upd q f) x0.
Proof. destruct q as [q1 q2]. destruct q1 as [|h q1]. 1: tauto. cbn. intros Hq Hf. destruct Hq as [Hq1 Hq2]. specialize (Hf (TNF_tm h)). destruct (f (TNF_tm h)). - cbn. split. + intros. repeat rewrite in_app_iff in H. rewrite or_assoc in H. rewrite <-in_app_iff in H. destruct H. 2: apply Hq1; tauto. destruct Hf as [n [t [Hf1 [Hf2 [Hf3 Hf4]]]]]. subst. eapply TNF_Node_expand_spec; eauto 1. apply Hq1. tauto. + intros. apply Hq2. intros. destruct H0. * subst. destruct Hf as [n [t [Hf1 [Hf2 [Hf3 Hf4]]]]]. eapply TNF_Node_expand_spec; eauto 1. 1: apply Hq1; tauto. intros. apply H. subst. repeat rewrite in_app_iff. tauto. * apply H. repeat rewrite in_app_iff. rewrite in_app_iff in H0. tauto. - split. + intros; apply Hq1; tauto. + intros; apply Hq2. intros. destruct H0. 2: auto 2. subst. apply TNF_Node_NonHalt,Hf. - split. + intros. apply Hq1. rewrite in_app_iff. rewrite in_app_iff in H. cbn in H. tauto. + intros. apply Hq2. intros. apply H. rewrite in_app_iff. rewrite in_app_iff in H0. cbn. tauto. Qed.
Lemma SearchQueue_upd_spec {q x0 f}: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upd q f) x0.
Proof. intros Hq Hf. destruct q as [q1 q2]. destruct q1 as [|h t]. - simpl. exact Hq. - simpl. unfold SearchQueue_WF in Hq. destruct Hq as [Hwf Himp]. specialize (Hf (TNF_tm h)) as Hfh. assert (Hwf_h: TNF_Node_WF h). { apply Hwf. apply in_or_app. left. left. reflexivity. } assert (Hwf_t: forall x, In x t -> TNF_Node_WF x). { intros x Hx. apply Hwf. apply in_or_app. left. right. exact Hx. } assert (Hwf_q2: forall x, In x q2 -> TNF_Node_WF x). { intros x Hx. apply Hwf. apply in_or_app. right. exact Hx. } destruct (f (TNF_tm h)) eqn:Ef; unfold SearchQueue_WF. + destruct Hfh as [n [t0 [Hhalt [Hsteps [Heqi Hle]]]]]. subst i. pose proof (TNF_Node_expand_spec Hhalt Hsteps Hle Hwf_h) as [Hwf_children Hchildren]. split. * intros x Hx. apply in_app_or in Hx. destruct Hx as [Hx|Hx]. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hwf_children. exact Hx. ++ apply Hwf_t. exact Hx. -- apply Hwf_q2. exact Hx. * intros Hall. apply Himp. intros x Hx. simpl in Hx. destruct Hx as [Heq|Hx]. -- subst x. apply Hchildren. intros x' Hx'. apply Hall. apply in_or_app. left. apply in_or_app. left. exact Hx'. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hall. apply in_or_app. left. apply in_or_app. right. exact Hx. ++ apply Hall. apply in_or_app. right. exact Hx. + split. * intros x Hx. apply in_app_or in Hx. destruct Hx as [Hx|Hx]. -- apply Hwf_t. exact Hx. -- apply Hwf_q2. exact Hx. * intros Hall. apply Himp. intros x Hx. simpl in Hx. destruct Hx as [Heq|Hx]. -- subst x. apply TNF_Node_NonHalt. exact Hfh. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hall. apply in_or_app. left. exact Hx. ++ apply Hall. apply in_or_app. right. exact Hx. + split. * intros x Hx. apply in_app_or in Hx. destruct Hx as [Hx|Hx]. -- apply Hwf_t. exact Hx. -- simpl in Hx. destruct Hx as [Heq|Hx]. ++ subst x. exact Hwf_h. ++ apply Hwf_q2. exact Hx. * intros Hall. apply Himp. intros x Hx. simpl in Hx. destruct Hx as [Heq|Hx]. -- subst x. apply Hall. apply in_or_app. right. left. reflexivity. -- apply in_app_or in Hx. destruct Hx as [Hx|Hx]. ++ apply Hall. apply in_or_app. left. exact Hx. ++ apply Hall. apply in_or_app. right. right. exact Hx. Qed.
Lemma SearchQueue_upds_bfs_spec q x0 f n: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upds_bfs q f n) x0.
Proof. intros. gd q. induction n; cbn; intros; auto 1. apply SearchQueue_upd_bfs_spec; auto 1. apply IHn,H. Qed.
Lemma SearchQueue_upds_bfs_spec q x0 f n: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upds_bfs q f n) x0.
Proof. revert q. induction n as [|n' IH]; intros q Hq Hf; simpl. - exact Hq. - apply SearchQueue_upd_bfs_spec; auto. Qed.
Lemma SearchQueue_upds_spec q x0 f n: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upds q f n) x0.
Proof. intros. gd q. induction n; cbn; intros. - destruct (fst q); auto 1. eapply SearchQueue_upd_spec; eauto 1. - destruct (fst q); auto 1. apply IHn,IHn,H. Qed.
Lemma SearchQueue_upds_spec q x0 f n: SearchQueue_WF q x0 -> HaltDecider_WF f -> SearchQueue_WF (SearchQueue_upds q f n) x0.
Proof. revert q. induction n as [|n' IH]; intros q Hq Hf; simpl; destruct (fst q) eqn:Efst; try exact Hq. - apply SearchQueue_upd_spec; assumption. - apply IH; [apply IH; assumption|assumption]. Qed.
Lemma St_enc_inj: is_inj St_enc.
Proof. intros x1 x2. destruct x1,x2; cbn; cg. Qed.
Lemma St_enc_inj: is_inj St_enc.
Proof. intros x1 x2. destruct x1,x2; cbn; cg. Qed.
Lemma St_eqb_spec s1 s2:
if St_eqb s1 s2 then s1=s2 else s1<>s2.
Proof. destruct s1,s2; cbn; congruence. Qed.
Lemma St_eqb_spec s1 s2:
if St_eqb s1 s2 then s1=s2 else s1<>s2.
Proof. destruct s1, s2; simpl; congruence. Qed.
Lemma St_leb_spec s1 s2:
if St_leb s1 s2 then St_le s1 s2 else ~(St_le s1 s2).
Proof. destruct (St_leb s1 s2) eqn:E. - unfold St_le. unfold St_leb in E. rewrite Nat.leb_le in E. apply E. - unfold St_le. unfold St_leb in E. rewrite <-Nat.leb_le. cg. Qed.
Lemma St_leb_spec s1 s2:
if St_leb s1 s2 then St_le s1 s2 else ~(St_le s1 s2).
Proof. unfold St_leb, St_le. destruct (Nat.leb_spec (St_to_nat s2) (St_to_nat s1)); lia. Qed.
Lemma St_list_spec: forall s, In s St_list.
Proof. intro s. destruct s; cbn; tauto. Qed.
Lemma St_list_spec: forall s, In s St_list.
Proof. destruct s; simpl; auto. Qed.
Lemma St_suc_eq x: x = (St_suc x) -> forall x0, St_le x x0.
Proof. destruct x; cbn; cg. intros. destruct x0; unfold St_le; cbn; lia. Qed.
Lemma St_suc_eq x: x = (St_suc x) -> forall x0, St_le x x0.
Proof. destruct x; unfold St_suc; intros H; try congruence. intros x0. unfold St_le, St_to_nat. destruct x0; simpl; lia. Qed.
Lemma St_suc_le x:
St_le (St_suc x) x.
Proof. unfold St_le. destruct x; cbn; lia. Qed.
Lemma St_suc_le x:
St_le (St_suc x) x.
Proof. destruct x; unfold St_le, St_suc, St_to_nat; simpl; lia. Qed.
Lemma St_suc_neq x: x <> (St_suc x) -> St_to_nat (St_suc x) = S (St_to_nat x).
Proof. destruct x; cbn; cg. Qed.
Lemma St_suc_neq x: x <> (St_suc x) -> St_to_nat (St_suc x) = S (St_to_nat x).
Proof. destruct x; simpl; intros; try congruence; reflexivity. Qed.
Lemma St_swap_swap: forall s, St_swap (St_swap s) = s.
Proof. intros. unfold St_swap. St_eq_dec s1 s;St_eq_dec s2 s;St_eq_dec s1 s2; auto; try cg. - St_eq_dec s2 s2; cg. - St_eq_dec s1 s1; cg. - St_eq_dec s1 s; try cg. St_eq_dec s2 s; try cg. Qed.
Lemma St_swap_swap: forall s, St_swap (St_swap s) = s.
Proof. intro s0. unfold St_swap. pose proof (St_eqb_spec s1 s0) as H1. destruct (St_eqb s1 s0) eqn:E1. - subst s0. pose proof (St_eqb_spec s1 s2) as H12. destruct (St_eqb s1 s2). + exfalso. apply Hneq12. assumption. + pose proof (St_eqb_spec s2 s2) as H22. destruct (St_eqb s2 s2). * reflexivity. * exfalso. apply H22. reflexivity. - pose proof (St_eqb_spec s2 s0) as H2. destruct (St_eqb s2 s0) eqn:E2. + subst s0. pose proof (St_eqb_spec s1 s1) as H11. destruct (St_eqb s1 s1). * reflexivity. * exfalso. apply H11. reflexivity. + rewrite E1. rewrite E2. reflexivity. Qed.
Lemma St_to_nat_inj: is_inj St_to_nat.
Proof. intros x1 x2. destruct x1,x2; cbn; cg. Qed.
Lemma St_to_nat_inj: is_inj St_to_nat.
Proof. unfold is_inj. intros x1 x2. destruct x1, x2; simpl; intros; try congruence; try lia. Qed.
Lemma Steps_NonHalt {tm m n st st0}: m<n -> Steps tm n st st0 -> ~HaltsAt tm m st.
Proof. intros. gd st0. induction n; intros. - lia. - assert (H1:m<n\/m=n) by lia. destruct H1 as [H1|H1]. + invst H0. apply (IHn H1 _ H3). + subst. invst H0. unfold HaltsAt,Halts. intro H1. destruct H1 as [st' [H1a H1b]]. rewrite <-(Steps_unique H2 H1a) in H1b. destruct st2. cg. Qed.
Lemma Steps_NonHalt {tm m n st st0}: m<n -> Steps tm n st st0 -> ~HaltsAt tm m st.
Proof. intros Hlt Hn [st' [Hm Hhalt]]. assert (Hle: S m <= n) by lia. destruct (Steps_le Hle Hn) as [stSm HstSm]. inversion HstSm; subst. replace st' with st2 in * by (eapply Steps_unique; eassumption). congruence. Qed.
Lemma Steps_NonHalt_trans {tm n st st0}: Steps Σ tm n st st0 -> ~Halts Σ tm st0 -> ~Halts Σ tm st.
Proof. repeat rewrite <-NonHalt_iff. unfold NonHalt. intros. assert (E:n0<n\/n<=n0) by lia. destruct E as [E|E]. - assert (E0:n=(n-n0+n0)) by lia. rewrite E0 in H. epose proof (Steps_split H) as H1. destruct H1 as [st2 [H1a H1b]]. exists st2. apply H1a. - specialize (H0 (n0-n)). destruct H0 as [st' H0]. exists st'. assert (E1:n0=n0-n+n) by lia. rewrite E1. eapply Steps_trans; eauto 1. Qed.
Lemma Steps_NonHalt_trans {tm n st st0}: Steps Σ tm n st st0 -> ~Halts Σ tm st0 -> ~Halts Σ tm st.
Proof. intros Hsteps Hnhalt. rewrite <- NonHalt_iff in *. unfold NonHalt in *. intros m. destruct (Nat.le_gt_cases n m) as [Hle|Hgt]. - destruct (Hnhalt (m - n)) as [st' Hst']. exists st'. replace m with ((m-n)+n) by lia. eapply Steps_trans; eauto. - assert (Hle': m <= n) by lia. destruct (@Steps_le _ _ _ _ _ _ Hle' Hsteps) as [stm Hstm]. exists stm. exact Hstm. Qed.
Lemma Steps_UnusedState {tm n s t}: Steps Σ tm n (InitES Σ Σ0) (s,t) -> ~ UnusedState tm s.
Proof. intro H. gd s. gd t. destruct n; intros. - invst H. intro H0. destruct H0 as [H0a [H0b H0c]]. cg. - invst H. destruct st0 as [s0 t0]. eapply step_UnusedState,H3. Qed.
Lemma Steps_UnusedState {tm n s t}: Steps Σ tm n (InitES Σ Σ0) (s,t) -> ~ UnusedState tm s.
Proof. intro Hsteps. inversion Hsteps; subst. - intros [_ [_ Hneq]]. apply Hneq. reflexivity. - destruct st0 as [s1 t1]. eapply step_UnusedState. exact H0. Qed.
Lemma Steps_rev tm n st st0: Steps (TM_rev tm) n st st0 <-> Steps tm n (ExecState_rev st) (ExecState_rev st0).
Proof. gd st0. induction n; intros. - split; intros; invst H. + ctor. + ff_inj ExecState_rev_rev H1. ctor. - split; intros. + invst H. rewrite IHn in H1. ector; eauto. apply step_rev,H3. + invst H. pose proof (IHn (ExecState_rev st2)) as IHn'. rewrite ExecState_rev_rev in IHn'. rewrite <-IHn' in H1. ector; eauto. apply step_rev. rewrite ExecState_rev_rev. apply H3. Qed.
Lemma Steps_rev tm n st st0: Steps (TM_rev tm) n st st0 <-> Steps tm n (ExecState_rev st) (ExecState_rev st0).
Proof. split. - intro H. remember (TM_rev tm) as tm0. induction H as [|tm1 n0 sta stb stc Hsteps IH Hstep]; subst. + constructor. + apply step_rev in Hstep. eapply steps_S; [apply IH; reflexivity | exact Hstep]. - intro H. remember (ExecState_rev st) as ast. remember (ExecState_rev st0) as ast0. revert st st0 Heqast Heqast0. induction H as [|tm0 n0 sta stb stc Hsteps IH Hstep]; intros stx stx0 Heq1 Heq2. + subst. assert (stx = stx0). { rewrite <- (ExecState_rev_rev stx). rewrite <- (ExecState_rev_rev stx0). congruence. } subst. constructor. + subst. assert (Hstep': step (TM_rev tm0) (ExecState_rev stb) = Some stx0). { apply step_rev. rewrite ExecState_rev_rev. exact Hstep. } eapply steps_S. * apply IH. reflexivity. rewrite ExecState_rev_rev. reflexivity. * exact Hstep'. Qed.
Lemma Steps_split{tm n1 n2 st0 st1}: Steps Σ tm (n1+n2) st0 st1 -> exists st2, Steps Σ tm n2 st0 st2 /\ Steps Σ tm n1 st2 st1.
Proof. gd st1. induction n1; intros. - exists st1. split. 1: apply H. ctor. - invst H. specialize (IHn1 _ H1). destruct IHn1 as [st3 [I1 I2]]. exists st3. split; auto 1. ector; eauto 1. Qed.
Lemma Steps_split{tm n1 n2 st0 st1}: Steps Σ tm (n1+n2) st0 st1 -> exists st2, Steps Σ tm n2 st0 st2 /\ Steps Σ tm n1 st2 st1.
Proof. revert st0 st1. induction n1; intros st0 st1 Hsteps. - exists st1. split; [exact Hsteps|constructor]. - change (S n1 + n2) with (S (n1 + n2)) in Hsteps. inversion_clear Hsteps. destruct (IHn1 _ _ H) as [stm [Hstma Hstmb]]. exists stm. split; [exact Hstma|eapply steps_S; eauto]. Qed.
Lemma Steps_swap tm n st st0: Steps (TM_swap tm) n st st0 <-> Steps tm n (ExecState_swap st) (ExecState_swap st0).
Proof. gd st0. induction n; intros. - split; intros; invst H. + ctor. + ff_inj ExecState_swap_swap H1. ctor. - split; intros. + invst H. rewrite IHn in H1. ector; eauto. apply step_swap,H3. + invst H. pose proof (IHn (ExecState_swap st2)) as IHn'. rewrite ExecState_swap_swap in IHn'. rewrite <-IHn' in H1. ector; eauto. apply step_swap. rewrite ExecState_swap_swap. apply H3. Qed.
Lemma Steps_swap tm n st st0: Steps (TM_swap tm) n st st0 <-> Steps tm n (ExecState_swap st) (ExecState_swap st0).
Proof. split. - apply Steps_swap_fwd. - intro H. replace st with (ExecState_swap (ExecState_swap st)) by (rewrite ExecState_swap_swap; reflexivity). replace st0 with (ExecState_swap (ExecState_swap st0)) by (rewrite ExecState_swap_swap; reflexivity). apply Steps_swap_fwd. rewrite TM_swap_swap. exact H. Qed.
Lemma Steps_trans {tm n m st st0 st1}: Steps tm n st st0 -> Steps tm m st0 st1 -> Steps tm (m+n) st st1.
Proof. intro H. gd st1. induction m; intros; cbn; invst H0. - assumption. - ector; eauto. Qed.
Lemma Steps_trans {tm n m st st0 st1}: Steps tm n st st0 -> Steps tm m st0 st1 -> Steps tm (m+n) st st1.
Proof. intros Hn Hm. induction Hm. - simpl. exact Hn. - simpl. eapply steps_S; eauto. Qed.
Lemma Steps_unique {tm n st st0 st1}: Steps tm n st st0 -> Steps tm n st st1 -> st0 = st1.
Proof. gd st1. gd st0. induction n; intros st0 st1 H H0; invst H; invst H0. - reflexivity. - specialize (IHn _ _ H2 H3). subst. cg. Qed.
Lemma Steps_unique {tm n st st0 st1}: Steps tm n st st0 -> Steps tm n st st1 -> st0 = st1.
Proof. revert st st0 st1. induction n; intros st st0 st1 H0 H1. - inversion H0; subst. inversion H1; subst. reflexivity. - inversion H0; subst. inversion H1; subst. replace st4 with st3 in * by (eapply IHn; eassumption). congruence. Qed.
Lemma TM0_HTUB:
HaltTimeUpperBound Σ (N.to_nat BB) (InitES Σ Σ0) (LE Σ (TM0)).
Proof. apply root_HTUB. Qed.
Lemma TM0_HTUB:
HaltTimeUpperBound Σ (N.to_nat BB) (InitES Σ Σ0) (LE Σ (TM0)).
Proof. exact root_HTUB. Qed.
Lemma TM0_LE: forall tm, LE Σ TM0 tm.
Proof. intros. unfold LE. intros. right. reflexivity. Qed.
Lemma TM0_LE: forall tm, LE Σ TM0 tm.
Proof. intros tm s0 i0. right. unfold TM0. reflexivity. Qed.
Lemma TM_history_HF n tm: forall (s:St)(i:Σ_history), match TM_history n tm s i with | Some tr => let (s',d,o) := tr in tm s (fst i) = Some {| nxt:=s'; dir:=d; out:= fst o |} | None => tm s (fst i) = None end.
Proof. intros. destruct i as [i0 i1]. cbn. destruct (tm s0 i0) as [[s' d o0]|]; cbn; reflexivity. Qed.
Lemma TM_history_HF n tm: forall (s:St)(i:Σ_history), match TM_history n tm s i with | Some tr => let (s',d,o) := tr in tm s (fst i) = Some {| nxt:=s'; dir:=d; out:= fst o |} | None => tm s (fst i) = None end.
Proof. intros s0 [i0 i1]. simpl. destruct (tm s0 i0) as [tr|] eqn:Etm; [|reflexivity]. destruct tr as [s' d o0]. simpl. reflexivity. Qed.
Lemma TM_history_LRU_HF tm: forall (s:St)(i:Σ_history), match TM_history_LRU tm s i with | Some tr => let (s',d,o) := tr in tm s (fst i) = Some {| nxt:=s'; dir:=d; out:= fst o |} | None => tm s (fst i) = None end.
Proof. intros. destruct i as [i0 i1]. cbn. destruct (tm s0 i0) as [[s' d o0]|]; cbn; reflexivity. Qed.
Lemma TM_history_LRU_HF tm: forall (s:St)(i:Σ_history), match TM_history_LRU tm s i with | Some tr => let (s',d,o) := tr in tm s (fst i) = Some {| nxt:=s'; dir:=d; out:= fst o |} | None => tm s (fst i) = None end.
Proof. intros s0 [i0 i1]. simpl. destruct (tm s0 i0) as [tr|] eqn:Etm; [|reflexivity]. destruct tr as [s' d o0]. simpl. reflexivity. Qed.
Lemma TM_history_LRU_NonHaltsFromInit tm: ~HaltsFromInit Σ_history Σ_history_0 (TM_history_LRU tm) -> ~HaltsFromInit Σ (fst Σ_history_0) tm.
Proof. apply F_NonHaltsFromInit. apply TM_history_LRU_HF. Qed.
Lemma TM_history_LRU_NonHaltsFromInit tm: ~HaltsFromInit Σ_history Σ_history_0 (TM_history_LRU tm) -> ~HaltsFromInit Σ (fst Σ_history_0) tm.
Proof. apply F_NonHaltsFromInit. exact (TM_history_LRU_HF tm). Qed.
Lemma TM_history_NonHaltsFromInit n tm: ~HaltsFromInit Σ_history Σ_history_0 (TM_history n tm) -> ~HaltsFromInit Σ (fst Σ_history_0) tm.
Proof. apply F_NonHaltsFromInit. apply TM_history_HF. Qed.
Lemma TM_history_NonHaltsFromInit n tm: ~HaltsFromInit Σ_history Σ_history_0 (TM_history n tm) -> ~HaltsFromInit Σ (fst Σ_history_0) tm.
Proof. apply F_NonHaltsFromInit. exact (TM_history_HF n tm). Qed.
Lemma TM_rev_rev: forall tm, TM_rev (TM_rev tm) = tm.
Proof. intros. unfold TM_rev. fext. fext. apply option_Trans_rev_rev. Qed.
Lemma TM_rev_rev: forall tm, TM_rev (TM_rev tm) = tm.
Proof. intro tm. extensionality s. extensionality i. unfold TM_rev. rewrite option_Trans_rev_rev. reflexivity. Qed.
Lemma TM_rev_upd'_TM0 s0 o0:
(TM_upd' (TM0) St0 Σ0 (Some {| nxt := s0; dir := Dneg; out := o0 |})) =
(TM_rev Σ (TM_upd' (TM0) St0 Σ0 (Some {| nxt := s0; dir := Dpos; out := o0 |}))).
Proof. repeat rewrite TM_upd'_spec. fext. fext. unfold TM_upd,TM_rev,TM0. St_eq_dec x St0. - Σ_eq_dec x0 Σ0; cbn; reflexivity. - cbn; reflexivity. Qed.
Lemma TM_rev_upd'_TM0 s0 o0:
(TM_upd' (TM0) St0 Σ0 (Some {| nxt := s0; dir := Dneg; out := o0 |})) =
(TM_rev Σ (TM_upd' (TM0) St0 Σ0 (Some {| nxt := s0; dir := Dpos; out := o0 |}))).
Proof. rewrite !TM_upd'_spec. extensionality s1. extensionality i1. unfold TM_rev, option_Trans_rev, Trans_rev, TM_upd, TM0. destruct (andb (St_eqb s1 St0) (Σ_eqb i1 Σ0)); simpl; reflexivity. Qed.
Lemma TM_simplify_spec tm:
TM_simplify tm = tm.
Proof. unfold TM_simplify,makeTM. fext. fext. destruct x,x0; reflexivity. Qed.
Lemma TM_simplify_spec tm:
TM_simplify tm = tm.
Proof. unfold TM_simplify. extensionality s0. extensionality i0. destruct s0, i0; reflexivity. Qed.
Lemma TM_swap_swap: forall tm, TM_swap (TM_swap tm) = tm.
Proof. intros. unfold TM_swap. fext. fext. rewrite option_Trans_swap_swap,St_swap_swap. reflexivity. Qed.
Lemma TM_swap_swap: forall tm, TM_swap (TM_swap tm) = tm.
Proof. intro tm. extensionality s. extensionality i. unfold TM_swap. rewrite option_Trans_swap_swap. rewrite St_swap_swap. reflexivity. Qed.
Lemma TM_upd'_spec tm s i tr:
TM_upd' tm s i tr = TM_upd Σ Σ_eqb tm s i tr.
Proof. unfold TM_upd'. rewrite TM_simplify_spec. reflexivity. Qed.
Lemma TM_upd'_spec tm s i tr:
TM_upd' tm s i tr = TM_upd Σ Σ_eqb tm s i tr.
Proof. unfold TM_upd'. rewrite TM_simplify_spec. reflexivity. Qed.
Lemma TNF_Node_NonHalt {x:TNF_Node}: ~ HaltsFromInit Σ Σ0 (TNF_tm x) -> TNF_Node_HTUB x.
Proof. destruct x as [tm cnt ptr]. intros. cbn. apply HaltTimeUpperBound_LE_NonHalt,H. Qed.
Lemma TNF_Node_NonHalt {x:TNF_Node}: ~ HaltsFromInit Σ Σ0 (TNF_tm x) -> TNF_Node_HTUB x.
Proof. intros Hnh. unfold TNF_Node_HTUB. destruct x as [tm cnt ptr]. simpl in *. unfold HaltsFromInit in Hnh. apply HaltTimeUpperBound_LE_NonHalt. exact Hnh. Qed.
Lemma TNF_Node_expand_spec {x:TNF_Node}{n s t}: HaltsAt Σ (TNF_tm x) n (InitES Σ Σ0) -> Steps Σ (TNF_tm x) n (InitES Σ Σ0) (s,t) -> n<=BB -> TNF_Node_WF x -> (forall x', In x' (TNF_Node_expand x s (t Z0)) -> TNF_Node_WF x') /\ ((forall x', In x' (TNF_Node_expand x s (t Z0)) -> TNF_Node_HTUB x') -> TNF_Node_HTUB x).
Proof. destruct x as [tm cnt ptr]. unfold TNF_tm. intros. split. - intros. unfold TNF_Node_expand in H3. nat_eq_dec cnt 1. 1: destruct H3. epose proof (HaltsAtES_Trans H H0) as H5. destruct H2 as [H2a [H2b H2c]]. rewrite in_map_iff in H3. destruct H3 as [tr [H3a H3b]]. cbn in H3a. rewrite TM_upd'_spec in H3a. rewrite <-H3a. repeat split. + destruct cnt; cg. unfold Nat.pred. epose proof (CountHaltTrans_upd tr H5) as H6. rewrite <-H2a in H6. injection H6. intro H7. rewrite H7. reflexivity. + destruct cnt; cg. unfold Nat.pred. cg. + eapply UnusedState_ptr_upd; eauto 1. rewrite filter_In in H3b. destruct H3b as [_ H3b]. St_le_dec ptr (nxt _ tr); cg. - unfold TNF_Node_HTUB. intros. destruct H2 as [H2a [H2b H2c]]. eapply HaltTimeUpperBound_LE_HaltAtES_UnusedState_ptr; eauto 1. intros. unfold TNF_Node_expand in H3. nat_eq_dec cnt 1. + apply HaltTimeUpperBound_LE_NonHalt. apply CountHaltTrans_0_NonHalt. epose proof (HaltsAtES_Trans H H0) as H5. epose proof (CountHaltTrans_upd tr H5) as H6. cg. + specialize (H3 (TNF_Node_upd {| TNF_tm := tm; TNF_cnt := cnt; TNF_ptr := ptr |} s (t 0%Z) tr)). rewrite <-TM_upd'_spec. apply H3. clear H3. rewrite in_map_iff. exists tr. split. 1: reflexivity. rewrite filter_In. split. 1: apply Trans_list_spec. St_le_dec ptr (nxt _ tr); cg. Qed.
Lemma TNF_Node_expand_spec {x:TNF_Node}{n s t}: HaltsAt Σ (TNF_tm x) n (InitES Σ Σ0) -> Steps Σ (TNF_tm x) n (InitES Σ Σ0) (s,t) -> n<=BB -> TNF_Node_WF x -> (forall x', In x' (TNF_Node_expand x s (t Z0)) -> TNF_Node_WF x') /\ ((forall x', In x' (TNF_Node_expand x s (t Z0)) -> TNF_Node_HTUB x') -> TNF_Node_HTUB x).
Proof. intros Hhalt Hsteps Hle Hwf. destruct x as [tm cnt ptr]. simpl TNF_tm in *. simpl TNF_cnt in *. simpl TNF_ptr in *. destruct Hwf as [Hcnt [Hcnt0 Hlsn]]. pose proof (HaltsAtES_Trans Hhalt Hsteps) as Hnone. assert (Hxho_eq: TNF_Node_expand {| TNF_tm := tm; TNF_cnt := cnt; TNF_ptr := ptr |} s (t Z0) = if Nat.eqb cnt 1 then nil else map (TNF_Node_upd {| TNF_tm := tm; TNF_cnt := cnt; TNF_ptr := ptr |} s (t Z0)) (filter (fun tr => St_leb ptr (nxt Σ tr)) Trans_list)). { reflexivity. } split. - (* Part 1: children are TNF_Node_WF *) intros x' Hin. rewrite Hxho_eq in Hin. destruct (Nat.eqb cnt 1) eqn:Ecnt1. + destruct Hin. + apply in_map_iff in Hin. destruct Hin as [tr0 [Heq Hfilt]]. apply filter_In in Hfilt. destruct Hfilt as [_ Hcfq]. subst x'. unfold TNF_Node_upd. unfold TNF_Node_WF. rewrite TM_upd'_spec. split; [|split]. * pose proof (CountHaltTrans_upd tr0 Hnone) as HY. rewrite <- Hcnt in HY. lia. * pose proof (nat_eqb_spec cnt 1) as Hg. rewrite Ecnt1 in Hg. lia. * pose proof (St_leb_spec ptr (nxt Σ tr0)) as Hmly. rewrite Hcfq in Hmly. apply (UnusedState_ptr_upd Hhalt Hsteps Hlsn Hmly). - (* Part 2: TNF_Node_HTUB x assuming children satisfy TNF_Node_HTUB *) intros Hall. unfold TNF_Node_HTUB. apply (HaltTimeUpperBound_LE_HaltAtES_UnusedState_ptr Hhalt Hsteps Hle Hlsn). intros tr0 Hktt. destruct (Nat.eqb cnt 1) eqn:Ecnt1. + (* cnt = 1 *) pose proof (nat_eqb_spec cnt 1) as Hg. rewrite Ecnt1 in Hg. pose proof (CountHaltTrans_upd tr0 Hnone) as HY. assert (Hizy: CountHaltTrans (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr0)) = 0). { subst cnt. lia. } apply HaltTimeUpperBound_LE_NonHalt. apply CountHaltTrans_0_NonHalt. exact Hizy. + (* cnt <> 1 => child exists in TNF_Node_expand *) assert (Hin: In tr0 (filter (fun tr1 => St_leb ptr (nxt Σ tr1)) Trans_list)). { apply filter_In. split. - apply Trans_list_spec. - pose proof (St_leb_spec ptr (nxt Σ tr0)) as Hmly. unfold St_leb. destruct (Nat.leb (St_to_nat (nxt Σ tr0)) (St_to_nat ptr)) eqn:Enl. + reflexivity. + exfalso. apply Nat.leb_gt in Enl. unfold St_le in Hktt. lia. } assert (Hchild: In (TNF_Node_upd {| TNF_tm := tm; TNF_cnt := cnt; TNF_ptr := ptr |} s (t Z0) tr0) (TNF_Node_expand {| TNF_tm := tm; TNF_cnt := cnt; TNF_ptr := ptr |} s (t Z0))). { unfold TNF_Node_expand. rewrite Ecnt1. apply in_map. exact Hin. } specialize (Hall _ Hchild). unfold TNF_Node_HTUB, TNF_Node_upd in Hall. rewrite TM_upd'_spec in Hall. exact Hall. Qed.
Lemma T_close_set_searcher_spec tm n q st: search_state_WF tm (q,st) -> match T_close_set_searcher tm n q st with | None => True | Some qst' => search_state_WF tm qst' end.
Proof. gd st. gd q. induction n; intros. - unfold T_close_set_searcher. apply H. - unfold T_close_set_searcher. fold T_close_set_searcher. destruct q as [|h q0]. 1: apply H. epose proof (T_step_spec tm h) as H0. destruct (T_step tm h) eqn:E. 2: trivial. destruct (ins_all q0 st l0) as [q' st'] eqn:E0. apply IHn. destruct (ins_all_spec E0) as [I1 I2]. unfold search_state_WF in H. unfold search_state_WF. intros x H1. rewrite <-I1 in H1. destruct H1 as [H1|H1]. + destruct ((set_in_dec T_enc (q0, st) x)) as [H2|H2]. 2: specialize (I2 x); tauto. specialize (H x H2). cbn in H. destruct H as [[H|H]|H]. * subst x. right. rewrite E. intros y H3. rewrite <-I1. tauto. * left. apply I2. tauto. * right. destruct (T_step tm x) eqn:E1. 2: tauto. intros y H3. rewrite <-I1. right. apply H,H3. + specialize (H x H1). destruct H as [[H|H]|H]. * subst x. right. rewrite E. intros y H2. rewrite <-I1. tauto. * left. apply I2. tauto. * right. destruct (T_step tm x) eqn:E1. 2: tauto. intros y H2. rewrite <-I1. right. apply H,H2. Qed.
Lemma T_close_set_searcher_spec tm n q st: search_state_WF tm (q,st) -> match T_close_set_searcher tm n q st with | None => True | Some qst' => search_state_WF tm qst' end.
Proof. revert q st. induction n as [|n0 IH]; intros q st Hinv. - simpl. exact Hinv. - simpl. destruct q as [|x q0]. + exact Hinv. + destruct (T_step tm x) as [ls|] eqn:Estep. * destruct (ins_all q0 st ls) as [q' st'] eqn:Ejixk. apply IH. pose proof (ins_all_spec Ejixk) as [Hiff Hin_q']. unfold search_state_WF. intros z Hvji_z. assert (Hvji_same: forall w, set_in T_enc (x::q0, st) w <-> set_in T_enc (q0, st) w). { intros w. unfold set_in. simpl. tauto. } assert (Hdec: set_in T_enc (q0, st) z \/ ~ set_in T_enc (q0, st) z). { unfold set_in. simpl. destruct (PositiveMap.find (T_enc z) st). - left. destruct u. reflexivity. - right. discriminate. } destruct Hdec as [Hvji0 | Hnvji0]. -- pose proof (Hinv z) as Hz. assert (Hvji_xq: set_in T_enc (x :: q0, st) z) by (apply Hvji_same; exact Hvji0). specialize (Hz Hvji_xq). destruct Hz as [Hin_xq | Hsucc]. ++ simpl in Hin_xq. destruct Hin_xq as [Hzx | Hin_q0]. ** subst z. right. rewrite Estep. intros y Hiny. apply (Hiff y). left. exact Hiny. ** left. apply Hin_q'. right. exact Hin_q0. ++ destruct (T_step tm z) as [ls_z|]. ** right. intros y Hiny. apply (Hiff y). right. apply (Hvji_same y). apply Hsucc. exact Hiny. ** destruct Hsucc. -- assert (HInls: In z ls). { destruct (proj2 (Hiff z) Hvji_z) as [Hin | Hvji0']. - exact Hin. - exfalso. exact (Hnvji0 Hvji0'). } left. apply Hin_q'. left. split; [exact HInls | exact Hnvji0]. * exact I. Qed.
Lemma T_decider0_spec n tm: T_decider0 n tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro. unfold T_decider0 in H. destruct (fst (set_ins T_enc (nil, PositiveMap.empty unit) T_InitES)) as [q0 st0] eqn:E0. epose proof (T_close_set_searcher_spec tm n q0 st0) as H0. destruct (T_close_set_searcher tm n q0 st0) as [[q1 st1]|]. 2: cg. destruct q1 as [|]. 2: cg. destruct (PositiveMap.find (T_enc T_InitES) st1) as [|] eqn:E2. 2: cg. eassert (H1:_). { apply H0. cbn. intros. left. assert (set_WF T_enc (q0,st0)). { destruct (set_ins T_enc (nil, PositiveMap.empty unit) T_InitES) as [qst0 flag] eqn:E. eapply set_ins_spec. - apply T_enc_inj. - apply empty_set_WF. - rewrite E. cbn in E0. subst qst0. reflexivity. } unfold set_WF in H2. rewrite H2 in H1. apply H1. } clear H0. clear H. assert (X1:in_search_state (InitES Σ Σ0) (nil, st1)). { unfold in_search_state. exists T_InitES. split. 2: apply In_T_InitES. unfold set_in. unfold snd. rewrite E2. f_equal. destruct u. reflexivity. } eapply CPS_correct. 1: apply X1. unfold isClosed. intros. unfold in_search_state in H. destruct H as [s0 [Ha Hb]]. cbn in H1. specialize (H1 _ Ha). destruct H1 as [H1|H1]. 1: contradiction. epose proof (T_step_spec tm s0) as H2. destruct (T_step tm s0) eqn:E1. 2: contradiction. specialize (H2 _ Hb). destruct H2 as [n1 [st3 [x1 [H2a [H2b H2c]]]]]. exists n1. exists st3. repeat split; auto 1. unfold in_search_state. exists x1. split; auto 1. apply H1,H2c. Qed.
Lemma T_decider0_spec n tm: T_decider0 n tm = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intro Hpx. unfold T_decider0 in Hpx. destruct (fst (set_ins T_enc (nil, PositiveMap.empty unit) T_InitES)) as [q0 st0] eqn:Einit. destruct (T_close_set_searcher tm n q0 st0) as [[[|x qrest] q2']|] eqn:EV; try discriminate. destruct (PositiveMap.find (T_enc T_InitES) q2') eqn:Efind; try discriminate. clear Hpx. (* Get set_ins properties *) assert (Hstep_init: exists flag, set_ins T_enc (nil, PositiveMap.empty unit) T_InitES = ((q0, st0), flag)). { destruct (set_ins T_enc (nil, PositiveMap.empty unit) T_InitES) as [p0 flag] eqn:Etrps. simpl in Einit. inversion Einit. subst p0. exists flag. reflexivity. } destruct Hstep_init as [flag Hstep_init]. pose proof (set_ins_spec' T_enc_inj Hstep_init) as Hqw_init. (* search_state_WF for initial state *) assert (Hinv0: search_state_WF tm (q0, st0)). { unfold search_state_WF. intros x0 Hvji_x0. assert (HT: T_InitES = x0 \/ set_in T_enc (nil, PositiveMap.empty unit) x0). { apply (proj2 (proj1 (Hqw_init x0))). exact Hvji_x0. } destruct HT as [Heq | Hvji_empty]. - subst x0. left. apply (proj2 (Hqw_init T_InitES)). left. split; [reflexivity|]. unfold set_in. simpl. rewrite PositiveMap.gempty. discriminate. - unfold set_in in Hvji_empty. simpl in Hvji_empty. rewrite PositiveMap.gempty in Hvji_empty. discriminate. } (* Apply T_close_set_searcher_spec to get search_state_WF for final state *) pose proof (T_close_set_searcher_spec tm n q0 st0 Hinv0) as HppKC. rewrite EV in HppKC. simpl in HppKC. (* HppKC: search_state_WF tm (nil, q2') *) (* Use CPS_correct with in_search_state as the invariant *) unfold HaltsFromInit. apply (@CPS_correct unit (fun (st:ExecState Σ) (_:unit) => in_search_state st (nil, q2')) tm tt (InitES Σ Σ0)). - (* in_search_state (InitES Σ Σ0) (nil, q2') *) exists T_InitES. split. + unfold set_in. simpl. destruct u. exact Efind. + exact In_T_InitES. - (* isClosed: forall st_x, in_search_state st_x (nil, q2') -> exists n0 st1, Steps (1+n0) st_x st1 /\ in_search_state st1 (nil, q2') *) intros st_x [s0 [Hvji_s0 HinT_s0]]. assert (Hqi: match T_step tm s0 with | None => False | Some ls => forall y, In y ls -> set_in T_enc (nil, q2') y end). { specialize (HppKC s0 Hvji_s0). simpl in HppKC. destruct HppKC as [Habs | Hsucc]; [destruct Habs | exact Hsucc]. } pose proof (T_step_spec tm s0) as Hspec. destruct (T_step tm s0) as [ls|] eqn:Ets. + specialize (Hspec st_x HinT_s0). destruct Hspec as [n0 [st1 [x1 [Hsteps [HinT1 Hinx1]]]]]. exists n0, st1. split. * exact Hsteps. * exists x1. split; [apply Hqi; exact Hinx1 | exact HinT1]. + destruct Hqi. Qed.
Lemma T_decider_spec n BB:
HaltDecider_WF BB (T_decider n).
Proof. unfold HaltDecider_WF. intros. unfold T_decider. epose proof (T_decider0_spec n tm). destruct (T_decider0 n tm); tauto. Qed.
Lemma T_decider_spec n BB:
HaltDecider_WF BB (T_decider n).
Proof. unfold HaltDecider_WF, T_decider. intro tm0. destruct (T_decider0 n tm0) eqn:E. - exact (T_decider0_spec n tm0 E). - trivial. Qed.
Lemma T_eqb_spec t1 t2:
if T_eqb t1 t2 then t1=t2 else t1<>t2.
Proof. unfold T_eqb. destruct (Pos.eqb_spec (T_enc t1) (T_enc t2)); auto 2. cg. Qed.
Lemma T_eqb_spec t1 t2:
if T_eqb t1 t2 then t1=t2 else t1<>t2.
Proof. unfold T_eqb. destruct (Pos.eqb_spec (T_enc t1) (T_enc t2)). - apply T_enc_inj. exact e. - intro Habs. subst. apply n. reflexivity. Qed.
Lemma Tape_rev_rev: forall t, Tape_rev (Tape_rev t) = t.
Proof. intros. unfold Tape_rev. fext. f_equal. lia. Qed.
Lemma Tape_rev_rev: forall t, Tape_rev (Tape_rev t) = t.
Proof. intro t. extensionality x. unfold Tape_rev. rewrite Z.opp_involutive. reflexivity. Qed.
Lemma Trans_list_spec: forall tr, In tr Trans_list.
Proof. intro. destruct tr as [s d o]. cbn. destruct s,d,o; tauto. Qed.
Lemma Trans_list_spec: forall tr, In tr Trans_list.
Proof. intros tr. destruct tr as [s d o]. unfold Trans_list. destruct s, d, o; simpl; auto 17. Qed.
Lemma Trans_rev_rev: forall t, Trans_rev (Trans_rev t) = t.
Proof. intros. destruct t. unfold Trans_rev. f_equal. destruct dir0; auto. Qed.
Lemma Trans_rev_rev: forall t, Trans_rev (Trans_rev t) = t.
Proof. intro t. destruct t as [s' d o]. simpl. destruct d; reflexivity. Qed.
Lemma Trans_swap_id s1 s2 t: nxt Σ t <> s1 -> nxt Σ t <> s2 -> t = Trans_swap Σ s1 s2 t.
Proof. intros. destruct t. unfold Trans_swap. f_equal. cbn in H,H0. unfold St_swap. St_eq_dec s1 nxt0; subst; try cg. St_eq_dec s2 nxt0; subst; try cg. Qed.
Lemma Trans_swap_id s1 s2 t: nxt Σ t <> s1 -> nxt Σ t <> s2 -> t = Trans_swap Σ s1 s2 t.
Proof. intros Hneq1 Hneq2. destruct t as [s' d o]. simpl in *. unfold Trans_swap, St_swap. simpl. pose proof (St_eqb_spec s1 s') as H1. destruct (St_eqb s1 s'). - exfalso. apply Hneq1. symmetry. exact H1. - pose proof (St_eqb_spec s2 s') as H2. destruct (St_eqb s2 s'). + exfalso. apply Hneq2. symmetry. exact H2. + reflexivity. Qed.
Lemma Trans_swap_swap: forall t, Trans_swap (Trans_swap t) = t.
Proof. intros. destruct t. unfold Trans_swap. f_equal. apply St_swap_swap. Qed.
Lemma Trans_swap_swap: forall t, Trans_swap (Trans_swap t) = t.
Proof. intro t. destruct t as [s' d o]. simpl. rewrite St_swap_swap. reflexivity. Qed.
Lemma UnusedState_TM0 s1: UnusedState TM0 s1 <-> s1 <> St0.
Proof. split; intro. - intro H0. subst. destruct H as [H [H0 H1]]. contradiction. - repeat split; auto 1. Qed.
Lemma UnusedState_TM0 s1: UnusedState TM0 s1 <-> s1 <> St0.
Proof. unfold UnusedState, TM0. split. - intros [_ [_ H]]. exact H. - intros H. split; [|split]. + intros s0 i0. exact I. + intros i0. reflexivity. + exact H. Qed.
Lemma UnusedState_dec tm s: (UnusedState tm s)\/(~UnusedState tm s).
Proof. pose proof (isUnusedState_spec tm s). destruct (isUnusedState tm s); tauto. Qed.
Lemma UnusedState_dec tm s: (UnusedState tm s)\/(~UnusedState tm s).
Proof. pose proof (isUnusedState_spec tm s) as H. destruct (isUnusedState tm s). - left. exact H. - right. exact H. Qed.
Lemma UnusedState_ptr_upd {tm n s t s1 tr}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> UnusedState_ptr tm s1 -> St_le s1 (nxt _ tr) -> UnusedState_ptr (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)) (if St_eqb s1 (nxt _ tr) then (St_suc s1) else s1).
Proof. intros. St_eq_dec s1 (nxt _ tr). - unfold UnusedState_ptr. unfold UnusedState_ptr in H1. destruct H1 as [H1|[H1a H1b]]. + subst. clear H2. St_eq_dec (nxt _ tr) (St_suc (nxt _ tr)). * pose proof (St_suc_eq _ H2). rewrite <-H2. right. split. 2: apply H3. intros. erewrite UnusedState_upd; eauto 1. rewrite H1. intro H'. destruct H' as [H'0 H'1]. apply H'1. apply St_to_nat_inj. specialize (H3 s0). unfold St_le in H3,H'0. lia. * left. intros. erewrite UnusedState_upd; eauto 1. rewrite H1. pose proof (St_suc_neq _ H2). unfold St_le. assert (E0:s0 = nxt _ tr <-> St_to_nat s0 = St_to_nat (nxt _ tr)). { split; intro. - cg. - apply St_to_nat_inj,H4. } rewrite E0. lia. + right. split. * intro. erewrite UnusedState_upd; eauto 1. intro H'. eapply H1a. destruct H' as [H' _]. apply H'. * intro. subst. specialize (H1b s0). pose proof (St_suc_le (nxt _ tr)) as H1. unfold St_le. unfold St_le in H1,H1b. lia. - unfold UnusedState_ptr. unfold UnusedState_ptr in H1. destruct H1 as [H1|[H1a H1b]]. + assert (E:~St_le (nxt _ tr) s1). { unfold St_le. unfold St_le in H2. assert (St_to_nat (s1) <> St_to_nat (nxt _ tr)) by (intro X; apply H3,St_to_nat_inj,X). lia. } left. intro. rewrite <-H1. erewrite UnusedState_upd; eauto 1. rewrite <-H1 in E. split; intro H4. * apply H4. * split. 1: apply H4. intro X. subst. apply E,H4. + right. split; auto 1. intro. erewrite UnusedState_upd; eauto 1. intro H'. eapply H1a. apply H'. Qed.
Lemma UnusedState_ptr_upd {tm n s t s1 tr}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> UnusedState_ptr tm s1 -> St_le s1 (nxt _ tr) -> UnusedState_ptr (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)) (if St_eqb s1 (nxt _ tr) then (St_suc s1) else s1).
Proof. intros Hhalt Hsteps Hlsn Hle. pose proof (St_eqb_spec s1 (nxt _ tr)) as Heq. destruct (St_eqb s1 (nxt _ tr)) eqn:Elav. - (* s1 = nxt tr *) subst. destruct Hlsn as [Hiff|[Hallnd Hmax]]. + (* First disjunct: UnusedState tm s0 <-> St_le s0 s1 *) destruct (St_eqb (nxt _ tr) (St_suc (nxt _ tr))) eqn:Eybb. * (* nxt tr = St_suc (nxt tr), i.e., nxt tr = St3 *) pose proof (St_eqb_spec (nxt _ tr) (St_suc (nxt _ tr))) as Hy. rewrite Eybb in Hy. (* No dead states in new TM *) right. split. -- intros s0 Hdead. apply (UnusedState_upd Hhalt Hsteps) in Hdead. destruct Hdead as [Hdead Hneq]. apply Hiff in Hdead. unfold St_le in Hdead. assert (Hle2: St_to_nat (nxt Σ tr) <= St_to_nat s0) by exact Hdead. assert (Hybb: St_to_nat (St_suc (nxt _ tr)) = St_to_nat (nxt _ tr)) by (rewrite <- Hy; reflexivity). destruct (nxt Σ tr) eqn:Enxt; destruct s0; simpl in *; try lia; exfalso; apply Hneq; reflexivity. -- intros s0. apply St_suc_eq. rewrite <- Hy at 2. reflexivity. * (* nxt tr <> St_suc (nxt tr) *) pose proof (St_eqb_spec (nxt _ tr) (St_suc (nxt _ tr))) as Hneq_ybb. rewrite Eybb in Hneq_ybb. left. intros s0. rewrite (UnusedState_upd Hhalt Hsteps). split. -- intros [Hdead Hneq]. apply Hiff in Hdead. unfold St_le in *. pose proof (St_suc_neq (nxt Σ tr) Hneq_ybb) as Hybb. assert (St_to_nat s0 <> St_to_nat (nxt Σ tr)). { intro Heq. apply Hneq. apply St_to_nat_inj. exact Heq. } lia. -- intros Hk. unfold St_le in Hk. pose proof (St_suc_neq (nxt Σ tr) Hneq_ybb) as Hybb. split. ++ apply Hiff. unfold St_le. lia. ++ intro Heq. subst. lia. + (* Second disjunct: no dead states *) right. split. * intros s0 Hdead. apply (UnusedState_upd Hhalt Hsteps) in Hdead. destruct Hdead as [Hdead _]. exact (Hallnd s0 Hdead). * intros s0. pose proof (Hmax s0) as Hm. unfold St_le in *. pose proof (St_suc_le (nxt _ tr)) as Hybb. unfold St_le in Hybb. lia. - (* s1 <> nxt tr *) destruct Hlsn as [Hiff|[Hallnd Hmax]]. + left. intros s0. rewrite (UnusedState_upd Hhalt Hsteps). split. * intros [Hdead Hneq]. apply Hiff in Hdead. exact Hdead. * intros Hk. split. -- apply Hiff. exact Hk. -- intro Heqn. subst. unfold St_le in *. assert (q_135: St_to_nat s1 <= St_to_nat (nxt Σ tr)) by exact Hk. apply Hiff in Hk. unfold St_le in Hk. apply Heq. apply St_to_nat_inj. lia. + right. split. * intros s0 Hdead. apply (UnusedState_upd Hhalt Hsteps) in Hdead. destruct Hdead as [Hdead _]. exact (Hallnd s0 Hdead). * exact Hmax. Qed.
Lemma UnusedState_upd {tm n s t tr s1}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> UnusedState (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)) s1 <-> (UnusedState tm s1 /\ s1<>nxt _ tr).
Proof. intros. split. - unfold UnusedState. intro. destruct H1 as [H1a [H1b H1c]]. repeat split; auto 1. + intros. specialize (H1a s0 i). unfold TM_upd in H1a. St_eq_dec s0 s. * Σ_eq_dec i (t Z0); cbn in H1a. -- subst. rewrite (HaltsAtES_Trans H H0). trivial. -- apply H1a. * apply H1a. + intros. specialize (H1b i). unfold TM_upd in H1b. St_eq_dec s1 s. * Σ_eq_dec i (t Z0); cbn in H1b. -- subst. cg. -- apply H1b. * apply H1b. + intro H2. subst. specialize (H1a s (t Z0)). unfold TM_upd in H1a. St_eq_dec s s; cg. Σ_eq_dec (t Z0) (t Z0); cg. - intro H1. destruct H1 as [H1 H1d]. pose proof H1 as U1. unfold UnusedState. destruct H1 as [H1a [H1b H1c]]. repeat split; auto 1. + intros. specialize (H1a s0 i). unfold TM_upd. St_eq_dec s0 s. * Σ_eq_dec i (t Z0); cbn; cg. * apply H1a. + intros. specialize (H1b i). assert (E:s1<>s) by (intro; subst; apply (Steps_UnusedState H0),U1). unfold TM_upd. St_eq_dec s1 s; cg. apply H1b. Qed.
Lemma UnusedState_upd {tm n s t tr s1}: HaltsAt _ tm n (InitES Σ Σ0) -> Steps _ tm n (InitES Σ Σ0) (s,t) -> UnusedState (TM_upd Σ Σ_eqb tm s (t Z0) (Some tr)) s1 <-> (UnusedState tm s1 /\ s1<>nxt _ tr).
Proof. intros Hhalt Hsteps. pose proof (HaltsAtES_Trans Hhalt Hsteps) as Hnone. pose proof (Steps_UnusedState Hsteps) as Hndead_s. split. - intros [Hno_ptr [Hno_trans Hneq0]]. split; [split; [|split]|]. + intros s0 i0. specialize (Hno_ptr s0 i0). unfold TM_upd in Hno_ptr. destruct (andb (St_eqb s0 s) (Σ_eqb i0 (t Z0))) eqn:E. * apply Bool.andb_true_iff in E. destruct E as [E1 E2']. pose proof (St_eqb_spec s0 s) as Hs0. rewrite E1 in Hs0. subst s0. pose proof (Σ_eqb_spec i0 (t Z0)) as Hi. rewrite E2' in Hi. subst i0. rewrite Hnone. exact I. * exact Hno_ptr. + intros i0. specialize (Hno_trans i0). unfold TM_upd in Hno_trans. destruct (andb (St_eqb s1 s) (Σ_eqb i0 (t Z0))) eqn:E. * discriminate. * exact Hno_trans. + exact Hneq0. + intro Heq. subst s1. specialize (Hno_ptr s (t Z0)). unfold TM_upd in Hno_ptr. pose proof (St_eqb_spec s s) as Hss. destruct (St_eqb s s) eqn:Es. * pose proof (Σ_eqb_spec (t Z0) (t Z0)) as Hi. destruct (Σ_eqb (t Z0) (t Z0)) eqn:Ei. -- simpl in Hno_ptr. exact (Hno_ptr eq_refl). -- exfalso. apply Hi. reflexivity. * exfalso. apply Hss. reflexivity. - intros [[Hno_ptr [Hno_trans Hneq0]] Hneq_nxt]. split; [|split]. + intros s0 i0. unfold TM_upd. destruct (andb (St_eqb s0 s) (Σ_eqb i0 (t Z0))) eqn:E. * simpl. intro Heq. apply Hneq_nxt. symmetry. exact Heq. * apply Hno_ptr. + intros i0. unfold TM_upd. destruct (andb (St_eqb s1 s) (Σ_eqb i0 (t Z0))) eqn:E. * exfalso. apply Bool.andb_true_iff in E. destruct E as [E1 E2]. pose proof (St_eqb_spec s1 s) as Hs. rewrite E1 in Hs. subst s1. apply Hndead_s. split; [|split]; auto. * apply Hno_trans. + exact Hneq0. Qed.
Lemma WordUpdate_spec tm s0 w0 sgn0: match WordUpdate tm s0 w0 sgn0 with | None => True | Some (s1,w1,is_back) => forall L R, exists n, if is_back then Steps Σ tm (S n) (s0,make_tape'' L w0 R sgn0) (s1,(make_tape'' (app_halftape w1 R) nil L (Dir_rev sgn0))) else Steps Σ tm (S n) (s0,make_tape'' L w0 R sgn0) (s1,make_tape'' (app_halftape w1 L) nil R sgn0) end.
Proof. unfold WordUpdate. destruct w0 as [|m0 w1]. 1: trivial. destruct sgn0. { pose proof (WordUpdate_steps_spec tm (Build_ListES w1 nil m0 s0) WordUpdate_MAXT) as H. cbn in H. destruct (WordUpdate_steps tm (Build_ListES w1 nil m0 s0) WordUpdate_MAXT) as [[x1 d]|]. 2: trivial. destruct x1 as [l1 r1 m1 s1]. destruct d; intros; cbn; destruct H as [Ha [n Hb]]; exists n. - rewrite make_tape'_split_r. apply Hb. - rewrite make_tape'_split_l. apply Hb. } { pose proof (WordUpdate_steps_spec tm (Build_ListES nil w1 m0 s0) WordUpdate_MAXT) as H. cbn in H. destruct (WordUpdate_steps tm (Build_ListES nil w1 m0 s0) WordUpdate_MAXT) as [[x1 d]|]. 2: trivial. destruct x1 as [l1 r1 m1 s1]. destruct d; intros; cbn; destruct H as [Ha [n Hb]]; exists n. - rewrite make_tape'_split_r. apply Hb. - rewrite make_tape'_split_l. apply Hb. } Qed.
Lemma WordUpdate_spec tm s0 w0 sgn0: match WordUpdate tm s0 w0 sgn0 with | None => True | Some (s1,w1,is_back) => forall L R, exists n, if is_back then Steps Σ tm (S n) (s0,make_tape'' L w0 R sgn0) (s1,(make_tape'' (app_halftape w1 R) nil L (Dir_rev sgn0))) else Steps Σ tm (S n) (s0,make_tape'' L w0 R sgn0) (s1,make_tape'' (app_halftape w1 L) nil R sgn0) end.
Proof. destruct w0 as [|m0 w1]. { simpl. exact I. } destruct sgn0. - (* sgn0 = Dneg *) simpl WordUpdate. pose proof (WordUpdate_steps_spec tm (Build_ListES w1 nil m0 s0) WordUpdate_MAXT) as HZc. simpl in HZc. destruct (WordUpdate_steps tm {| ListTape.l := w1; ListTape.r := nil; m := m0; ListTape.s := s0 |} WordUpdate_MAXT) as [[[l1 r1 m1 s1] [|]]|]. + destruct HZc as [Hlen [n2 HSteps2]]. cbn [negb Dir_eqb]. intros L R. exists n2. change (make_tape'' L (m0 :: w1) R Dneg) with (make_tape' R w1 m0 nil L). assert (HEQ: make_tape'' (app_halftape (m1 :: r1) L) nil R Dneg = make_tape' (half_tape_cdr R) nil (R 0) (m1 :: r1) L). { unfold make_tape''. rewrite make_tape'_split_r. simpl app. reflexivity. } rewrite HEQ. exact (HSteps2 R L). + destruct HZc as [Hlen [n2 HSteps2]]. cbn [negb Dir_eqb Dir_rev]. intros L R. exists n2. change (make_tape'' L (m0 :: w1) R Dneg) with (make_tape' R w1 m0 nil L). assert (HEQ: make_tape'' (app_halftape (m1 :: l1) R) nil L Dpos = make_tape' R (m1 :: l1) (L 0) nil (half_tape_cdr L)). { unfold make_tape''. rewrite make_tape'_split_l. simpl app. reflexivity. } rewrite HEQ. exact (HSteps2 R L). + exact I. - (* sgn0 = Dpos *) simpl WordUpdate. pose proof (WordUpdate_steps_spec tm (Build_ListES nil w1 m0 s0) WordUpdate_MAXT) as HZc. simpl in HZc. destruct (WordUpdate_steps tm {| ListTape.l := nil; ListTape.r := w1; m := m0; ListTape.s := s0 |} WordUpdate_MAXT) as [[[l1 r1 m1 s1] [|]]|]. + destruct HZc as [Hlen [n2 HSteps2]]. cbn [negb Dir_eqb Dir_rev]. intros L R. exists n2. change (make_tape'' L (m0 :: w1) R Dpos) with (make_tape' L nil m0 w1 R). assert (HEQ: make_tape'' (app_halftape (m1 :: r1) R) nil L Dneg = make_tape' (half_tape_cdr L) nil (L 0) (m1 :: r1) R). { unfold make_tape''. rewrite make_tape'_split_r. simpl app. reflexivity. } rewrite HEQ. exact (HSteps2 L R). + destruct HZc as [Hlen [n2 HSteps2]]. cbn [negb Dir_eqb]. intros L R. exists n2. change (make_tape'' L (m0 :: w1) R Dpos) with (make_tape' L nil m0 w1 R). assert (HEQ: make_tape'' (app_halftape (m1 :: l1) L) nil R Dpos = make_tape' L (m1 :: l1) (R 0) nil (half_tape_cdr R)). { unfold make_tape''. rewrite make_tape'_split_l. simpl app. reflexivity. } rewrite HEQ. exact (HSteps2 L R). + exact I. Qed.
Lemma WordUpdate_step0_spec tm (x:ListES): let (l0,r0,m0,s0):=x in match WordUpdate_step0 tm x with | None => True | Some (x1,None) => AbstractSteps tm 1 x x1 | Some (x1,Some Dpos) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ forall L R, Steps Σ tm 1 (makeES x L R) (s1,make_tape' L (m1::l1) (R 0) nil (half_tape_cdr R)) | Some (x1,Some Dneg) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ forall L R, Steps Σ tm 1 (makeES x L R) (s1,make_tape' (half_tape_cdr L) nil (L 0) (m1::r1) R) end.
Proof. destruct x as [l0 r0 m0 s0]. cbn. destruct (tm s0 m0) as [[s1 d o]|] eqn:E. destruct d. - destruct l0. + cbn. split. 1: auto. intros. ector. 1: ctor. cbn. rewrite E. f_equal. f_equal. rewrite make_tape'_upd. replace (make_tape' L nil o r0 R) with (make_tape' (app_halftape ((L 0)::nil) (half_tape_cdr L)) nil o r0 R). 2: f_equal; apply app_halftape_cdr''. rewrite make_tape'_split_l. cbn. apply make_tape'_mov_l. + split; cbn. 1: lia. intros. ector. 1: ctor. cbn. rewrite E. f_equal. f_equal. rewrite make_tape'_upd. apply make_tape'_mov_l. - destruct r0. + cbn. split. 1: auto. intros. ector. 1: ctor. cbn. rewrite E. f_equal. f_equal. rewrite make_tape'_upd. replace (make_tape' L l0 o nil R) with (make_tape' L l0 o nil (app_halftape ((R 0)::nil) (half_tape_cdr R))). 2: f_equal; apply app_halftape_cdr''. rewrite make_tape'_split_r. cbn. apply make_tape'_mov_r. + split; cbn. 1: lia. intros. ector. 1: ctor. cbn. rewrite E. f_equal. f_equal. rewrite make_tape'_upd. apply make_tape'_mov_r. - trivial. Qed.
Lemma WordUpdate_step0_spec tm (x:ListES): let (l0,r0,m0,s0):=x in match WordUpdate_step0 tm x with | None => True | Some (x1,None) => AbstractSteps tm 1 x x1 | Some (x1,Some Dpos) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ forall L R, Steps Σ tm 1 (makeES x L R) (s1,make_tape' L (m1::l1) (R 0) nil (half_tape_cdr R)) | Some (x1,Some Dneg) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ forall L R, Steps Σ tm 1 (makeES x L R) (s1,make_tape' (half_tape_cdr L) nil (L 0) (m1::r1) R) end.
Proof. destruct x as [l0 r0 m0 s0]. unfold WordUpdate_step0. destruct (tm s0 m0) as [[s1 d o]|] eqn:Etm. 2: exact I. destruct d. - destruct l0 as [|m1 l1]. + simpl. split; [simpl; lia|]. intros L R. eapply steps_S. { apply steps_O. } unfold step, makeES. change (make_tape' L nil m0 r0 R Z0) with m0. rewrite Etm. simpl. rewrite make_tape'_upd. rewrite make_tape'_cdr_l. rewrite make_tape'_mov_l. reflexivity. + unfold AbstractSteps, makeES. simpl. split; [simpl; lia|]. intros l1' r1. eapply steps_S. { apply steps_O. } unfold step. change (make_tape' l1' (m1 :: l1) m0 r0 r1 Z0) with m0. rewrite Etm. simpl. rewrite make_tape'_upd. rewrite make_tape'_mov_l. reflexivity. - destruct r0 as [|m1 r1]. + simpl. split; [simpl; lia|]. intros L R. eapply steps_S. { apply steps_O. } unfold step, makeES. change (make_tape' L l0 m0 nil R Z0) with m0. rewrite Etm. simpl. rewrite make_tape'_upd. rewrite make_tape'_cdr_r. rewrite make_tape'_mov_r. reflexivity. + unfold AbstractSteps, makeES. simpl. split; [simpl; lia|]. intros l1' r1'. eapply steps_S. { apply steps_O. } unfold step. change (make_tape' l1' l0 m0 (m1 :: r1) r1' Z0) with m0. rewrite Etm. simpl. rewrite make_tape'_upd. rewrite make_tape'_mov_r. reflexivity. Qed.
Lemma WordUpdate_steps_spec tm (x:ListES) n0: let (l0,r0,m0,s0):=x in match WordUpdate_steps tm x n0 with | None => True | Some (x1,Dpos) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ exists n, forall L R, Steps Σ tm (S n) (makeES x L R) (s1,make_tape' L (m1::l1) (R 0) nil (half_tape_cdr R)) | Some (x1,Dneg) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ exists n, forall L R, Steps Σ tm (S n) (makeES x L R) (s1,make_tape' (half_tape_cdr L) nil (L 0) (m1::r1) R) end.
Proof. gd x. induction n0; intros. - cbn. destruct x as [l0 r0 m0 s0]. trivial. - destruct x as [l0 r0 m0 s0]. unfold WordUpdate_steps. pose proof (WordUpdate_step0_spec tm (Build_ListES l0 r0 m0 s0)) as H. destruct (WordUpdate_step0 tm (Build_ListES l0 r0 m0 s0)) as [[x1 d1]|]. 2: trivial. destruct d1 as [d1|]. + destruct x1 as [l1 r1 m1 s1]. destruct d1; (split; [ tauto | exists 0; tauto ]). + fold WordUpdate_steps. specialize (IHn0 x1). destruct x1 as [l1 r1 m1 s1]. cbn in IHn0. destruct H as [Ha Hb]. cbn in Ha,Hb. destruct (WordUpdate_steps tm (Build_ListES l1 r1 m1 s1) n0) as [[x2 [|]]|]. 3: trivial. 1,2: destruct x2 as [l2 r2 m2 s2]; destruct IHn0 as [I1 [n I2]]; split; [ cg | exists (S n); replace (S (S n)) with ((S n)+1) by lia; intros; eapply Steps_trans; eauto 1]. Qed.
Lemma WordUpdate_steps_spec tm (x:ListES) n0: let (l0,r0,m0,s0):=x in match WordUpdate_steps tm x n0 with | None => True | Some (x1,Dpos) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ exists n, forall L R, Steps Σ tm (S n) (makeES x L R) (s1,make_tape' L (m1::l1) (R 0) nil (half_tape_cdr R)) | Some (x1,Dneg) => let (l1,r1,m1,s1):=x1 in length l0 + length r0 = length l1 + length r1 /\ exists n, forall L R, Steps Σ tm (S n) (makeES x L R) (s1,make_tape' (half_tape_cdr L) nil (L 0) (m1::r1) R) end.
Proof. revert x. induction n0 as [|n0' IH]; intros x. - destruct x. simpl. exact I. - destruct x as [l0 r0 m0 s0]. simpl. pose proof (WordUpdate_step0_spec tm (Build_ListES l0 r0 m0 s0)) as HlTGxV. simpl in HlTGxV. unfold WordUpdate_step0 in HlTGxV. destruct (tm s0 m0) as [[s1 d1 o1]|] eqn:Etm. 2: exact I. destruct d1; [destruct l0 as [|ml ll]|destruct r0 as [|mr rr]]. + simpl in HlTGxV. destruct HlTGxV as [Hlen HSteps]. split; [exact Hlen|]. exists 0. exact HSteps. + destruct HlTGxV as [Hlen Hstep1]. specialize (IH (Build_ListES ll (o1 :: r0) ml s1)). simpl in IH. destruct (WordUpdate_steps tm (Build_ListES ll (o1 :: r0) ml s1) n0') as [[[l1 r1 m1 s1'] [|]]|]. * destruct IH as [Hlen2 [n2 HSteps2]]. split; [simpl in *; lia|]. exists (S n2). intros L R. replace (S (S n2)) with (S n2 + 1) by lia. eapply Steps_trans; [exact (Hstep1 L R) | exact (HSteps2 L R)]. * destruct IH as [Hlen2 [n2 HSteps2]]. split; [simpl in *; lia|]. exists (S n2). intros L R. replace (S (S n2)) with (S n2 + 1) by lia. eapply Steps_trans; [exact (Hstep1 L R) | exact (HSteps2 L R)]. * exact I. + simpl in HlTGxV. destruct HlTGxV as [Hlen HSteps]. split; [exact Hlen|]. exists 0. exact HSteps. + destruct HlTGxV as [Hlen Hstep1]. specialize (IH (Build_ListES (o1 :: l0) rr mr s1)). simpl in IH. destruct (WordUpdate_steps tm (Build_ListES (o1 :: l0) rr mr s1) n0') as [[[l1 r1 m1 s1'] [|]]|]. * destruct IH as [Hlen2 [n2 HSteps2]]. split; [simpl in *; lia|]. exists (S n2). intros L R. replace (S (S n2)) with (S n2 + 1) by lia. eapply Steps_trans; [exact (Hstep1 L R) | exact (HSteps2 L R)]. * destruct IH as [Hlen2 [n2 HSteps2]]. split; [simpl in *; lia|]. exists (S n2). intros L R. replace (S (S n2)) with (S n2 + 1) by lia. eapply Steps_trans; [exact (Hstep1 L R) | exact (HSteps2 L R)]. * exact I. Qed.
Lemma Word_eqb_spec x1 x2:
if Word_eqb x1 x2 then x1=x2 else x1<>x2.
Proof. gd x2. induction x1 as [|h1 t1]; cbn; intros; destruct x2 as [|h2 t2]; cg. destruct (Σ_eqb h1 h2) eqn:E. - specialize (IHt1 t2). destruct (Word_eqb t1 t2); cg. pose proof (Σ_eqb_spec h1 h2). rewrite E in H. cg. - pose proof (Σ_eqb_spec h1 h2). rewrite E in H. cg. Qed.
Lemma Word_eqb_spec x1 x2:
if Word_eqb x1 x2 then x1=x2 else x1<>x2.
Proof. revert x2. induction x1 as [|h1 t1 IH]; destruct x2 as [|h2 t2]; simpl; auto. - discriminate. - discriminate. - pose proof (Σ_eqb_spec h1 h2) as Hh. destruct (Σ_eqb h1 h2). + subst. specialize (IH t2). destruct (Word_eqb t1 t2). * subst. reflexivity. * intro H. apply IH. congruence. + intro H. apply Hh. congruence. Qed.
Lemma all0_spec x: all0 x = true -> x = repeat Σ0 (length x).
Proof. induction x; cbn; intros. - reflexivity. - destruct a eqn:E in H. 2: cg. rewrite <-IHx; auto 1. cg. Qed.
Lemma all0_spec x: all0 x = true -> x = repeat Σ0 (length x).
Proof. induction x as [|h t IH]; intro H. - reflexivity. - simpl in H. destruct h. + simpl. f_equal. apply IH. exact H. + discriminate. Qed.
Lemma allTM_HTUB: HaltTimeUpperBound Σ (N.to_nat BB) (InitES Σ Σ0) (fun _ => True).
Proof. unfold HaltTimeUpperBound. intros. eapply TM0_HTUB. 2: apply H0. unfold LE. intros. right. reflexivity. Qed.
Lemma allTM_HTUB: HaltTimeUpperBound Σ (N.to_nat BB) (InitES Σ Σ0) (fun _ => True).
Proof. unfold HaltTimeUpperBound. intros tm n0 _ Hhalt. apply (TM0_HTUB tm n0). - exact (TM0_LE tm). - exact Hhalt. Qed.
Lemma andb_shortcut_spec(a b:bool): (a&&&b) = (a&&b)%bool.
Proof. reflexivity. Qed.
Lemma andb_shortcut_spec(a b:bool): (a&&&b) = (a&&b)%bool.
Proof. destruct a, b; reflexivity. Qed.
Lemma app_half_tape_all0 n: half_tape_all0 = app_halftape (repeat Σ0 n) half_tape_all0.
Proof. fext. unfold half_tape_all0,app_halftape. assert (x<n\/n<=x) by lia. destruct H as [H|H]. - rewrite nth_error_repeat; auto 1. - rewrite <-(repeat_length Σ0 n) in H. rewrite <-nth_error_None in H. rewrite H. reflexivity. Qed.
Lemma app_half_tape_all0 n: half_tape_all0 = app_halftape (repeat Σ0 n) half_tape_all0.
Proof. extensionality m. unfold app_halftape, half_tape_all0. destruct (nth_error (repeat Σ0 n) m) eqn:E; auto. apply nth_error_In in E. apply repeat_spec in E. subst. reflexivity. Qed.
Lemma app_halftape_S m1 l1 l1' n:
app_halftape (m1 :: l1) l1' (S n) = app_halftape l1 l1' n.
Proof. unfold app_halftape. cbn. reflexivity. Qed.
Lemma app_halftape_S m1 l1 l1' n:
app_halftape (m1 :: l1) l1' (S n) = app_halftape l1 l1' n.
Proof. unfold app_halftape. simpl. reflexivity. Qed.
Lemma app_halftape_all0{l1 l2}: app_halftape l1 l2 = half_tape_all0 -> l2 = half_tape_all0.
Proof. unfold half_tape_all0. intros. fext. epose proof (fext_inv ((length l1)+x) H) as H0. cbn in H0. unfold app_halftape in H0. destruct (nth_error l1 (length l1 + x)) eqn:E. - assert (E1:length l1 <= length l1 + x) by lia. rewrite <-nth_error_None in E1. cg. - rewrite <-H0. f_equal. lia. Qed.
Lemma app_halftape_all0{l1 l2}: app_halftape l1 l2 = half_tape_all0 -> l2 = half_tape_all0.
Proof. intro H. extensionality m. unfold half_tape_all0. pose proof (f_equal (fun f => f (length l1 + m)) H) as HH. unfold app_halftape, half_tape_all0 in HH. assert (Hn: nth_error l1 (length l1 + m) = None) by (apply nth_error_None; lia). rewrite Hn in HH. replace (length l1 + m - length l1) with m in HH by lia. exact HH. Qed.
Lemma app_halftape_assoc{l1 l2 l3}:
app_halftape l1 (app_halftape l2 l3) =
app_halftape (l1++l2) l3.
Proof. induction l1. - cbn. rewrite app_halftape_nil. reflexivity. - cbn. apply app_halftape_eq_car_cdr; auto 1. Qed.
Lemma app_halftape_assoc{l1 l2 l3}:
app_halftape l1 (app_halftape l2 l3) =
app_halftape (l1++l2) l3.
Proof. extensionality n. unfold app_halftape. destruct (nth_error l1 n) eqn:E1. - rewrite nth_error_app1; [rewrite E1; reflexivity|]. apply nth_error_Some. congruence. - apply nth_error_None in E1. rewrite nth_error_app2; [|lia]. destruct (nth_error l2 (n - length l1)) eqn:E2. + reflexivity. + f_equal. apply nth_error_None in E2. rewrite app_length. lia. Qed.
Lemma app_halftape_cdr l1':
app_halftape nil l1' = app_halftape (l1' 0 :: nil) (half_tape_cdr l1').
Proof. fext. destruct x; cbn. 1: reflexivity. unfold app_halftape. destruct x; reflexivity. Qed.
Lemma app_halftape_cdr l1':
app_halftape nil l1' = app_halftape (l1' 0 :: nil) (half_tape_cdr l1').
Proof. extensionality n. unfold app_halftape, half_tape_cdr. destruct n as [|n']; cbn; auto. replace (nth_error (A:=Σ) nil n') with (@None Σ) by (symmetry; apply nth_error_nil). replace (n' - 0) with n' by lia. reflexivity. Qed.
Lemma app_halftape_cdr' l0 l1':
app_halftape l0 l1' = app_halftape (l0 ++ l1' 0 :: nil) (half_tape_cdr l1').
Proof. induction l0. - apply app_halftape_cdr. - cbn. apply app_halftape_eq_car_cdr; tauto. Qed.
Lemma app_halftape_cdr' l0 l1':
app_halftape l0 l1' = app_halftape (l0 ++ l1' 0 :: nil) (half_tape_cdr l1').
Proof. induction l0 as [|h tl IH]. - simpl. apply app_halftape_cdr. - simpl. apply app_halftape_eq_car_cdr; [reflexivity|exact IH]. Qed.
Lemma app_halftape_cdr'' L:
app_halftape ((L 0)::nil) (half_tape_cdr L)=L.
Proof. rewrite <-app_halftape_nil,app_halftape_cdr. reflexivity. Qed.
Lemma app_halftape_cdr'' L:
app_halftape ((L 0)::nil) (half_tape_cdr L)=L.
Proof. extensionality n. unfold app_halftape, half_tape_cdr. simpl. destruct n as [|n']; simpl; auto. replace (nth_error (A:=Σ) nil n') with (@None Σ) by (symmetry; apply nth_error_nil). replace (n' - 0) with n' by lia. reflexivity. Qed.
Lemma app_halftape_eq {a b a' b'}: app_halftape a b = app_halftape a' b' -> length a <= length a' -> exists ls, length ls = length a' - length a /\ a++ls=a' /\ app_halftape ls b' = b.
Proof. gd a'. induction a as [|h a]; intros. - exists a'. cbn. repeat split. 1: lia. rewrite <-H. apply app_halftape_nil. - destruct a' as [|h' a']. 1: cbn in H0; lia. destruct (app_halftape_eq_cons H) as [H1 H2]. subst. cbn in H0. assert (H3:length a <= length a') by lia. specialize (IHa _ H2 H3). destruct IHa as [ls [H4 [H5 H6]]]. exists ls. repeat split; auto 1. cbn. cg. Qed.
Lemma app_halftape_eq {a b a' b'}: app_halftape a b = app_halftape a' b' -> length a <= length a' -> exists ls, length ls = length a' - length a /\ a++ls=a' /\ app_halftape ls b' = b.
Proof. revert a' b b'. induction a as [|h a IHa]; intros a' b b' H Hlen. - exists a'. simpl. rewrite Nat.sub_0_r. repeat split; auto. rewrite app_halftape_nil in H. symmetry. exact H. - destruct a' as [|h' a'']. + simpl in Hlen. lia. + apply app_halftape_eq_cons in H. destruct H as [Hh H]. simpl in Hlen. assert (Hlen': length a <= length a'') by lia. specialize (IHa a'' b b' H Hlen'). destruct IHa as [ls [Hlslen [Happ Hlsb]]]. exists ls. simpl. split; [lia|]. split. * f_equal; [exact Hh | exact Happ]. * exact Hlsb. Qed.
Lemma app_halftape_eq' {a b a' b'}: app_halftape a b = app_halftape a' b' -> length a = length a' -> (a=a'/\b=b').
Proof. intros. eassert (H1:_) by (apply (app_halftape_eq H); lia). destruct H1 as [ls [H1 [H2 H3]]]. assert (length ls = 0) by lia. destruct ls; cbn in H4; cg. rewrite app_halftape_nil in H3. rewrite app_nil_r in H2. split; cg. Qed.
Lemma app_halftape_eq' {a b a' b'}: app_halftape a b = app_halftape a' b' -> length a = length a' -> (a=a'/\b=b').
Proof. intros H Hlen. assert (Hle: length a <= length a') by lia. destruct (app_halftape_eq H Hle) as [ls [Hlslen [Happ Hlsb]]]. assert (Hlsnil: length ls = 0) by lia. apply length_zero_iff_nil in Hlsnil. subst ls. rewrite app_nil_r in Happ. rewrite app_halftape_nil in Hlsb. split; [exact Happ | symmetry; exact Hlsb]. Qed.
Lemma app_halftape_eq_car_cdr h t t0 h' t' t0': h=h' -> app_halftape t t0 = app_halftape t' t0' -> app_halftape (h::t) t0 = app_halftape (h'::t') t0'.
Proof. intros. subst. fext. destruct x. - reflexivity. - cbn. repeat rewrite app_halftape_S. cg. Qed.
Lemma app_halftape_eq_car_cdr h t t0 h' t' t0': h=h' -> app_halftape t t0 = app_halftape t' t0' -> app_halftape (h::t) t0 = app_halftape (h'::t') t0'.
Proof. intros Hh Htail. extensionality n. unfold app_halftape. simpl. destruct n; [exact Hh|]. pose proof (fun n0 => f_equal (fun f => f n0) Htail) as HH. simpl in HH. unfold app_halftape in HH. apply HH. Qed.
Lemma app_halftape_eq_cons {h a b h' a' b'}: app_halftape (h::a) b = app_halftape (h'::a') b' -> (h=h'/\app_halftape a b = app_halftape a' b').
Proof. intro. split. 1: apply (fext_inv 0 H). fext. epose proof (fext_inv (S x) H) as H0. repeat rewrite app_halftape_S in H0. apply H0. Qed.
Lemma app_halftape_eq_cons {h a b h' a' b'}: app_halftape (h::a) b = app_halftape (h'::a') b' -> (h=h'/\app_halftape a b = app_halftape a' b').
Proof. intro H. assert (Hh: h = h') by (apply (f_equal (fun f => f 0)) in H; simpl in H; exact H). split; [exact Hh|]. extensionality n. apply (f_equal (fun f => f (S n))) in H. simpl in H. exact H. Qed.
Lemma app_halftape_nil l1:
app_halftape nil l1 = l1.
Proof. unfold app_halftape. fext. destruct x; cbn; reflexivity. Qed.
Lemma app_halftape_nil l1:
app_halftape nil l1 = l1.
Proof. extensionality n. unfold app_halftape. simpl. replace (nth_error (A:=Σ) nil n) with (@None Σ) by (symmetry; apply nth_error_nil). replace (n - 0) with n by lia. reflexivity. Qed.
Lemma app_halftape_skipn w0 f:
(halftape_skipn (length w0) (app_halftape w0 f)) = f.
Proof. fext. unfold halftape_skipn,app_halftape. assert (length w0 <= length w0 + x) by lia. rewrite <-nth_error_None in H. rewrite H. f_equal. lia. Qed.
Lemma app_halftape_skipn w0 f:
(halftape_skipn (length w0) (app_halftape w0 f)) = f.
Proof. extensionality m. unfold halftape_skipn, app_halftape. assert (Hn: nth_error w0 (length w0 + m) = None) by (apply nth_error_None; lia). rewrite Hn. f_equal. lia. Qed.
Lemma app_halftape_skipn_cdr c w0 f:
app_halftape w0
(halftape_skipn (S (length w0)) (app_halftape (c :: w0) f)) =
half_tape_cdr (app_halftape (c :: w0) f).
Proof. fext. unfold app_halftape,halftape_skipn,half_tape_cdr. replace (S (length w0) + (x - length w0)) with (S ((length w0) + (x - length w0))) by lia. cbn. destruct (nth_error w0 x) eqn:E; auto 1. rewrite nth_error_None in E. replace ((length w0 + (x - length w0))) with x by lia. rewrite <-nth_error_None in E. rewrite E. reflexivity. Qed.
Lemma app_halftape_skipn_cdr c w0 f:
app_halftape w0
(halftape_skipn (S (length w0)) (app_halftape (c :: w0) f)) =
half_tape_cdr (app_halftape (c :: w0) f).
Proof. extensionality n. unfold half_tape_cdr, halftape_skipn, app_halftape. simpl. destruct (nth_error w0 n) eqn:E. - reflexivity. - assert (Hlen: length w0 <= n) by (apply nth_error_None; exact E). replace (length w0 + (n - length w0)) with n by lia. rewrite E. reflexivity. Qed.
Lemma bool_enc_inj: is_inj bool_enc.
Proof. intros x1 x2 H. destruct x1,x2; cbn in H; cg. Qed.
Lemma bool_enc_inj: is_inj bool_enc.
Proof. intros a b H. destruct a, b; simpl in H; congruence. Qed.
Lemma check_InitES_InAES_spec S: AES_impl_WF S -> check_InitES_InAES S = true -> InAES (InitES Σ Σ0) (AES_impl_to_AES S).
Proof. destruct S as [ls rs ms]. intros H0 H. cbn in H. repeat rewrite Bool.andb_true_iff in H. destruct H as [[Ha Hb] Hc]. destruct H0 as [H0a [H0b H0c]]. unfold AES_impl_to_AES. eapply (InitES_InAES_cond {| lset := xset_in ls; rset := xset_in rs; mset := mset_in ms |}). - destruct (xset_ins ls (repeat Σ0 len_l)) as [ls' flag] eqn:E. cbn in E. destruct len_l. 1: cbn in E,Hb; invst E; cg. destruct (xset_ins_spec _ _ _ _ _ H0a E) as [_ H0]. cbn in Hb. invst Hb. apply H0,eq_refl. - destruct (xset_ins rs (repeat Σ0 len_r)) as [rs' flag] eqn:E. destruct len_r. 1: cbn in E,Hc; invst E; cg. cbn in E. destruct (xset_ins_spec _ _ _ _ _ H0b E) as [_ H0]. cbn in Hc. invst Hc. apply H0,eq_refl. - destruct (mset_ins0 ms {| l := repeat Σ0 len_l; r := repeat Σ0 len_r; m := Σ0; s := St0 |}) as [ms' flag] eqn:E. destruct len_l. 1: cbn in E,Hb; invst E; cg. destruct len_r. 1: cbn in E,Hc; invst E; cg. destruct (mset_ins0_spec _ _ _ _ H0c E) as [_ H0]. cbn in Ha. invst Ha. apply H0,eq_refl. Qed.
Lemma check_InitES_InAES_spec S: AES_impl_WF S -> check_InitES_InAES S = true -> InAES (InitES Σ Σ0) (AES_impl_to_AES S).
Proof. destruct S as [ls rs ms]. intros [Hls [Hrs Hms]] Hlk. unfold check_InitES_InAES in Hlk. destruct (mset_ins0 ms {| l := repeat Σ0 len_l; r := repeat Σ0 len_r; m := Σ0; s := St0 |}) as [ms' flag_ms] eqn:Ems. destruct (xset_ins ls (repeat Σ0 len_l)) as [ls' flag_ls] eqn:Els. destruct (xset_ins rs (repeat Σ0 len_r)) as [rs' flag_rs] eqn:Ers. simpl in Hlk. apply Bool.andb_true_iff in Hlk. destruct Hlk as [Hlk Hfr]. apply Bool.andb_true_iff in Hlk. destruct Hlk as [Hfms Hfl]. pose proof (mset_ins0_spec ms _ ms' flag_ms Hms Ems) as [_ Hms_imp]. destruct (Hms_imp Hfms) as [_ Hms_in]. destruct (repeat Σ0 len_l) as [|hl tl] eqn:Erl. - simpl in Els. inversion Els. subst. discriminate. - pose proof (xset_ins_spec ls hl tl ls' flag_ls Hls Els) as [_ Hls_imp]. destruct (Hls_imp Hfl) as [_ Hls_in]. destruct (repeat Σ0 len_r) as [|hr tr] eqn:Err. + simpl in Ers. inversion Ers. subst. discriminate. + pose proof (xset_ins_spec rs hr tr rs' flag_rs Hrs Ers) as [_ Hrs_imp]. destruct (Hrs_imp Hfr) as [_ Hrs_in]. change (AES_impl_to_AES {| lset' := ls; rset' := rs; mset' := ms |}) with {| lset := xset_in ls; rset := xset_in rs; mset := mset_in ms |}. apply (InitES_InAES_cond {| lset := xset_in ls; rset := xset_in rs; mset := mset_in ms |}). * rewrite Erl. exact Hls_in. * rewrite Err. exact Hrs_in. * rewrite Erl. rewrite Err. exact Hms_in. Qed.
Lemma decider2_WF: HaltDecider_WF (N.to_nat BB) decider2.
Proof. apply loop1_decider_WF. unfold BB. lia. Qed.
Lemma decider2_WF: HaltDecider_WF (N.to_nat BB) decider2.
Proof. unfold decider2, BB. apply loop1_decider_WF. simpl. lia. Qed.
Lemma decider_all_spec: HaltDecider_WF (N.to_nat BB) decider_all.
Proof. unfold decider_all,HaltDecider_list. repeat apply HaltDecider_cons_spec. all: try apply NGramCPS_decider_impl2_spec. all: try apply NGramCPS_decider_impl1_spec. - apply decider2_WF. - apply NGramCPS_LRU_decider_spec. - apply RepWL_ES_decider_spec. - unfold HaltDecider_nil,HaltDecider_WF. intro. trivial. Qed.
Lemma decider_all_spec: HaltDecider_WF (N.to_nat BB) decider_all.
Proof. unfold decider_all. simpl HaltDecider_list. repeat apply HaltDecider_cons_spec. - (* decider2 *) exact decider2_WF. - (* decider3 *) apply NGramCPS_decider_impl2_spec. - (* decider4 *) apply NGramCPS_decider_impl2_spec. - (* decider5 *) apply NGramCPS_decider_impl2_spec. - (* decider6 *) apply NGramCPS_decider_impl1_spec. - (* decider7 *) apply NGramCPS_decider_impl1_spec. - (* decider9 *) apply NGramCPS_decider_impl1_spec. - (* decider10 *) apply NGramCPS_decider_impl1_spec. - (* decider11 *) apply NGramCPS_decider_impl1_spec. - (* decider12 *) apply NGramCPS_decider_impl1_spec. - (* decider13 *) apply NGramCPS_decider_impl1_spec. - (* decider14 *) apply NGramCPS_decider_impl1_spec. - (* decider15 *) apply NGramCPS_LRU_decider_spec. - (* decider16 *) apply NGramCPS_decider_impl1_spec. - (* decider17 *) unfold decider17. apply RepWL_ES_decider_spec. - (* HaltDecider_nil base case *) unfold HaltDecider_WF, HaltDecider_nil. intro. trivial. Qed.
Lemma empty_set_WF{T}(enc:T->positive): set_WF enc (nil, PositiveMap.empty unit).
Proof. unfold set_WF. intros. cbn. split; intro. 2: contradiction. unfold set_in in H. rewrite PositiveMap.gempty in H. cg. Qed.
Lemma empty_set_WF{T}(enc:T->positive): set_WF enc (nil, PositiveMap.empty unit).
Proof. unfold set_WF, set_in. simpl. intros x. split. - intro H. rewrite PositiveMap.gempty in H. discriminate. - intro H. destruct H. Qed.
Lemma enc_list_inj: is_inj enc_list.
Proof. intros x1 x2 H. gd x2. induction x1 as [|h1 t1]; destruct x2 as [|h2 t2]; intros; cg. - cbn in H. destruct ((Pos.of_succ_nat (positive_len h2))); cbn in H; cg. - cbn in H. destruct ((Pos.of_succ_nat (positive_len h1))); cbn in H; cg. - epose proof (enc_pair_inj _ _ H). invst H0. f_equal. apply IHt1; assumption. Qed.
Lemma enc_list_inj: is_inj enc_list.
Proof. unfold is_inj. induction a as [|h1 t1 IH]; intros b H. - destruct b as [|h2 t2]; [reflexivity|]. simpl in H. exfalso. apply (enc_pair_not_xH (h2, enc_list t2)). auto. - destruct b as [|h2 t2]. + simpl in H. exfalso. symmetry in H. apply (enc_pair_not_xH (h1, enc_list t1)). auto. + simpl in H. change (enc_pair (h1, enc_list t1) = enc_pair (h2, enc_list t2)) in H. apply enc_pair_inj in H. injection H as H1 H2. f_equal; auto. Qed.
Lemma enc_pair_inj: is_inj enc_pair.
Proof. intros x1 x2 H. destruct x1 as [a1 b1]. destruct x2 as [a2 b2]. unfold enc_pair in H. destruct (enc_v1_eq _ _ _ _ H) as [Ha Hb]. clear H. assert (positive_len a1 = positive_len a2) by lia. clear Ha. gd a2. induction a1; destruct a2; cbn; intros; cg; invst Hb; invst H; assert ((a1,b1)=(a2,b2)) by auto 2; cg. Qed.
Lemma enc_pair_inj: is_inj enc_pair.
Proof. intros [a1 a2] [b1 b2]. unfold enc_pair. intro H. apply enc_v1_eq in H. destruct H as [H1 H2]. apply SuccNat2Pos.inj in H1. apply append_inj in H2; [| exact H1]. destruct H2. subst. reflexivity. Qed.
Lemma enc_v1_eq a1 b1 a2 b2: append (enc_v1 a1) (xO b1) = append (enc_v1 a2) (xO b2) -> (a1 = a2 /\ b1 = b2).
Proof. gd a2. induction a1; destruct a2; cbn; intros; cg; invst H. 1,2: destruct (IHa1 a2 H1). all: split; cg. Qed.
Lemma enc_v1_eq a1 b1 a2 b2: append (enc_v1 a1) (xO b1) = append (enc_v1 a2) (xO b2) -> (a1 = a2 /\ b1 = b2).
Proof. revert a2. induction a1; destruct a2; simpl; intros; try congruence. - injection H as H1. apply IHa1 in H1. destruct H1; subst; auto. - injection H as H1. apply IHa1 in H1. destruct H1; subst; auto. - injection H as H1. auto. Qed.
Lemma ex_sitr_history {tm:TM Σ} {n st0 st1}: Steps _ tm (S n) st0 st1 -> exists h ls, length ls = n /\ (forall n0, n0<=n -> exists s2 t2, Steps _ tm n0 st0 (s2,t2) /\ match nth_error (h::ls) (n-n0) with | None => False | Some (s0,i0,tr) => tm s0 i0 = Some tr /\ s0 = s2 /\ i0 = t2 Z0 end).
Proof. gd st1. induction n. - intros. invst H. invst H1. clear H. clear H1. destruct st2 as [s0 t0]. cbn in H3. destruct (tm s0 (t0 Z0)) as [tr|] eqn:E. 2: cg. exists (s0,t0 Z0,tr). exists nil. cbn. split. 1: reflexivity. intros. destruct n0. 2: lia. exists s0. exists t0. split. 1: ctor. repeat split. cg. - intros. invst H. specialize (IHn _ H1). destruct IHn as [h' [ls' [IHn1 IHn2]]]. destruct st2 as [s0 t0]. cbn in H3. destruct (tm s0 (t0 Z0)) as [tr|] eqn:E. 2: cg. exists (s0,t0 Z0,tr). exists (h'::ls'). split. 1: cbn; cg. intros. assert (H2:n0<=n\/n0=S n) by lia. destruct H2 as [H2|H2]. + assert (H4:S n - n0 = S (n-n0)) by lia. rewrite H4. cbn. apply IHn2,H2. + assert (H4:S n - n0 = 0) by lia. rewrite H4. cbn. subst. exists s0. exists t0. split; tauto. Qed.
Lemma ex_sitr_history {tm:TM Σ} {n st0 st1}: Steps _ tm (S n) st0 st1 -> exists h ls, length ls = n /\ (forall n0, n0<=n -> exists s2 t2, Steps _ tm n0 st0 (s2,t2) /\ match nth_error (h::ls) (n-n0) with | None => False | Some (s0,i0,tr) => tm s0 i0 = Some tr /\ s0 = s2 /\ i0 = t2 Z0 end).
Proof. revert st0 st1. induction n; intros st0 st1 Hsteps. - inversion Hsteps; subst. inversion H0; subst. destruct st2 as [s0 t0]. unfold step in H2. destruct (tm s0 (t0 Z0)) as [tr|] eqn:Htm; [|discriminate]. exists (s0, t0 Z0, tr), nil. split; [reflexivity|]. intros n0 Hn0. assert (n0 = 0) by lia. subst n0. simpl. exists s0, t0. split; [constructor|]. rewrite Htm. auto. - inversion Hsteps; subst. specialize (IHn st0 st2 H0). destruct IHn as [h' [ls' [Hlen' Hcond']]]. destruct st2 as [s_mid t_mid]. unfold step in H2. destruct (tm s_mid (t_mid Z0)) as [tr_mid|] eqn:Htm_mid; [|discriminate]. exists (s_mid, t_mid Z0, tr_mid), (h' :: ls'). split; [simpl; lia|]. intros n0 Hn0. destruct (Nat.eq_dec n0 (S n)) as [Heq|Hneq]. + subst n0. replace (S n - S n) with 0 by lia. simpl. exists s_mid, t_mid. split. * exact H0. * rewrite Htm_mid. auto. + assert (Hn0': n0 <= n) by lia. specialize (Hcond' n0 Hn0'). destruct Hcond' as [s2 [t2 [Hsteps' Hmatch]]]. exists s2, t2. split; [exact Hsteps'|]. replace (S n - n0) with (S (n - n0)) by lia. simpl. exact Hmatch. Qed.
Lemma fext_inv{A}{B} {f g:A->B}(x:A): f = g -> f x = g x.
Proof. cg. Qed.
Lemma fext_inv{A}{B} {f g:A->B}(x:A): f = g -> f x = g x.
Proof. intro H; rewrite H; reflexivity. Qed.
Lemma ffx_eq_x_inj{A}: forall f:A->A, (forall x:A, f (f x) = x) -> forall x y:A, f x = f y -> x = y.
Proof. intros. assert ((f (f x)) = (f (f y))) as H1. { rewrite H0,H. reflexivity. } rewrite H,H in H1. apply H1. Qed.
Lemma ffx_eq_x_inj{A}: forall f:A->A, (forall x:A, f (f x) = x) -> forall x y:A, f x = f y -> x = y.
Proof. intros f Hf x y H. rewrite <- (Hf x). rewrite <- (Hf y). rewrite H. reflexivity. Qed.
Lemma find_loop1_0_spec tm h0 h1 ls: sidpos_history_WF tm h0 (h1::ls) -> find_loop1_0 h0 h1 ls = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intros. unfold find_loop1_0 in H0. destruct ls; cg. eapply find_loop1_spec; eauto 1; reflexivity. Qed.
Lemma find_loop1_0_spec tm h0 h1 ls: sidpos_history_WF tm h0 (h1::ls) -> find_loop1_0 h0 h1 ls = true -> ~HaltsFromInit Σ Σ0 tm.
Proof. intros Hwhp Hdaw. unfold find_loop1_0 in Hdaw. destruct ls as [|h2 ls']; [discriminate|]. eapply find_loop1_spec; eauto. - simpl. reflexivity. - simpl. reflexivity. Qed.
Lemma find_loop1_spec tm h0 h1 h2 ls0 ls1 ls2 n: sidpos_history_WF tm h0 ls0 -> h1::ls1 = skipn (S n) (h0::ls0) -> h2::ls2 = skipn (S n) (h1::ls1) -> find_loop1 h0 h1 h2 ls0 ls1 ls2 n = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. gd n. gd ls2. gd h2. gd h1. induction ls1. - intros. cbn in H2. cbn in H1. rewrite skipn_nil in H1. invst H1. - intros. cbn in H2. repeat rewrite orb_shortcut_spec in H2. rewrite Bool.orb_true_iff in H2. destruct H2 as [H2|H2]. + destruct h0 as [es0 d0]. destruct h1 as [es1 d1]. destruct h2 as [es2 d2]. repeat rewrite andb_shortcut_spec in H2. repeat rewrite Bool.andb_true_iff in H2. destruct H2 as [H2a [H2b [H2c [H2d H2e]]]]. eapply verify_loop1_spec; eauto 1. eexists. eexists. exists 0. eexists. repeat split; auto 1. unfold sidpos_history_period. intros. lia. + destruct ls2 as [|h3 [|h2' ls2']]; cg. eapply IHls1; eauto 1. * rewrite (skipn_S H0); cg. * cbn in H1. apply (skipn_S (skipn_S H1)). Qed.
Lemma find_loop1_spec tm h0 h1 h2 ls0 ls1 ls2 n: sidpos_history_WF tm h0 ls0 -> h1::ls1 = skipn (S n) (h0::ls0) -> h2::ls2 = skipn (S n) (h1::ls1) -> find_loop1 h0 h1 h2 ls0 ls1 ls2 n = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. revert h0 h1 h2 ls0 ls2 n. induction ls1 as [|h1' ls1' IH]; intros h0 h1 h2 ls0 ls2 n Hwhp Hskip1 Hskip2 Hdrnda; destruct h0 as [es0 d0]; destruct h1 as [es1 d1]; simpl in Hdrnda. - (* ls1 = nil *) destruct (St_eqb (s es0) (s es1)) eqn:Hs01; simpl in Hdrnda. + destruct h2 as [es2 d2]. destruct (St_eqb (s es0) (s es2)) eqn:Hs02; simpl in Hdrnda. * destruct (Σ_eqb (m es0) (m es1)) eqn:Hm01; simpl in Hdrnda. -- destruct (Σ_eqb (m es0) (m es2)) eqn:Hm02; simpl in Hdrnda. ++ destruct (verify_loop1 (es0, d0) (es1, d1) ls0 nil (S n) (d0 - d1)) eqn:Hvmiwq. ** eapply verify_loop1_spec; [|exact Hvmiwq]. exists (es0, d0), ls0, 0, n. repeat split; auto. unfold sidpos_history_period. intros m0 Hm0. lia. ** simpl in Hdrnda. destruct ls2 as [|? [|? ?]]; discriminate. ++ destruct ls2 as [|? [|? ?]]; discriminate. -- destruct ls2 as [|? [|? ?]]; discriminate. * destruct ls2 as [|? [|? ?]]; discriminate. + destruct h2. destruct ls2 as [|? [|? ?]]; discriminate. - (* ls1 = h1' :: ls1' *) pose proof (skipn_S Hskip1) as Hskip1'. simpl in Hskip1'. pose proof (skipn_S Hskip2) as Hskip2'. simpl in Hskip2'. destruct (St_eqb (s es0) (s es1)) eqn:Hs01; simpl in Hdrnda. + destruct h2 as [es2 d2]. destruct (St_eqb (s es0) (s es2)) eqn:Hs02; simpl in Hdrnda. * destruct (Σ_eqb (m es0) (m es1)) eqn:Hm01; simpl in Hdrnda. -- destruct (Σ_eqb (m es0) (m es2)) eqn:Hm02; simpl in Hdrnda. ++ destruct (verify_loop1 (es0, d0) (es1, d1) ls0 (h1' :: ls1') (S n) (d0 - d1)) eqn:Hvmiwq. ** eapply verify_loop1_spec; [|exact Hvmiwq]. exists (es0, d0), ls0, 0, n. repeat split; auto. unfold sidpos_history_period. intros m0 Hm0. lia. ** simpl in Hdrnda. destruct ls2 as [|h3 ls2_tl]; [discriminate|]. destruct ls2_tl as [|h2' ls2']; [discriminate|]. pose proof (skipn_S Hskip2') as Hskip2''. simpl in Hskip2''. eapply (IH (es0,d0) h1' h2' ls0 ls2' (S n) Hwhp Hskip1' Hskip2'' Hdrnda). ++ destruct ls2 as [|h3 ls2_tl]; [discriminate|]. destruct ls2_tl as [|h2' ls2']; [discriminate|]. pose proof (skipn_S Hskip2') as Hskip2''. simpl in Hskip2''. eapply (IH (es0,d0) h1' h2' ls0 ls2' (S n) Hwhp Hskip1' Hskip2'' Hdrnda). -- destruct ls2 as [|h3 ls2_tl]; [discriminate|]. destruct ls2_tl as [|h2' ls2']; [discriminate|]. pose proof (skipn_S Hskip2') as Hskip2''. simpl in Hskip2''. eapply (IH (es0,d0) h1' h2' ls0 ls2' (S n) Hwhp Hskip1' Hskip2'' Hdrnda). * destruct ls2 as [|h3 ls2_tl]; [discriminate|]. destruct ls2_tl as [|h2' ls2']; [discriminate|]. pose proof (skipn_S Hskip2') as Hskip2''. simpl in Hskip2''. eapply (IH (es0,d0) h1' h2' ls0 ls2' (S n) Hwhp Hskip1' Hskip2'' Hdrnda). + destruct h2 as [es2 d2]. destruct ls2 as [|h3 ls2_tl]; [discriminate|]. destruct ls2_tl as [|h2' ls2']; [discriminate|]. pose proof (skipn_S Hskip2') as Hskip2''. simpl in Hskip2''. eapply (IH (es0,d0) h1' h2' ls0 ls2' (S n) Hwhp Hskip1' Hskip2'' Hdrnda). Qed.
Lemma forallb_Dir_spec f: forallb_Dir f = true <-> forall s, f s = true.
Proof. unfold forallb_Dir. rewrite forallb_forall. split; intros. - apply H,Dir_list_spec. - apply H. Qed.
Lemma forallb_Dir_spec f: forallb_Dir f = true <-> forall s, f s = true.
Proof. unfold forallb_Dir. rewrite forallb_forall. split. - intros H s. apply H. apply Dir_list_spec. - intros H s _. apply H. Qed.
Lemma forallb_St_spec f: forallb_St f = true <-> forall s, f s = true.
Proof. unfold forallb_St. rewrite forallb_forall. split; intros. - apply H,St_list_spec. - apply H. Qed.
Lemma forallb_St_spec f: forallb_St f = true <-> forall s, f s = true.
Proof. unfold forallb_St. rewrite forallb_forall. split. - intros H s. apply H. apply St_list_spec. - intros H s _. apply H. Qed.
Lemma forallb_Σ_spec f: forallb_Σ f = true <-> forall s, f s = true.
Proof. unfold forallb_Σ. rewrite forallb_forall. split; intros. - apply H,Σ_list_spec. - apply H. Qed.
Lemma forallb_Σ_spec f: forallb_Σ f = true <-> forall s, f s = true.
Proof. unfold forallb_Σ. rewrite forallb_forall. split. - intros H s. apply H. apply Σ_list_spec. - intros H s _. apply H. Qed.
Lemma getASteps_spec {tm:TM Σ} {n st0 st1 h ls}: Steps _ tm n st0 st1 -> length ls = n -> (forall n0, n0<=n -> exists s2 t2, Steps _ tm n0 st0 (s2,t2) /\ match nth_error (h::ls) (n-n0) with | None => False | Some (s0,i0,tr) => tm s0 i0 = Some tr /\ s0 = s2 /\ i0 = t2 Z0 end) -> let (st0',st1'):=getASteps h ls in AbstractSteps tm n st0' st1' /\ (MoveDist tm n st0 st1 ((Z.of_nat (length (st1'.(l))))-(Z.of_nat (length (st0'.(l)))))) /\ exists l1 r1, st0 = makeES st0' l1 r1 /\ st1 = makeES st1' l1 r1.
Proof. gd st1. gd h. gd ls. induction n; intros. - destruct ls. 2: cbn in H0; cg. specialize (H1 0). assert (H2:0<=0) by lia. specialize (H1 H2). clear H2. cbn in H1. destruct H1 as [s2 [t2 [H1a H1b]]]. destruct h as [[s0 i0] tr]. destruct H1b as [H1b [H1c H1d]]. subst. cbn. epose proof (Steps_unique _ H1a H). subst. invst H1a. split. { split. 1: cg. intros. ctor. } split. 1: ctor. eexists. eexists. rewrite <-make_tape'_lmr. tauto. - destruct ls as [|h0 ls]; cbn in H0. 1: cg. invst H. invst H0. specialize (IHn ls h0 _ H3 eq_refl). cbn. destruct (getASteps h0 ls) as [st3 st4]. eassert (H':_). { apply IHn. intros. specialize (H1 n0). assert (H4:S (length ls) - n0 = S ((length ls) - n0)) by lia. rewrite H4 in H1. cbn in H1. apply H1. lia. } clear IHn. destruct H' as [H'AS [H'md [l1' [r1' [H'0 H'1]]]]]. destruct h as [[s'' i''] tr'']. destruct h0 as [[s' i'] tr']. destruct st3 as [l0 r0 m0 s0]. destruct st4 as [l1 r1 m1 s1]. eassert (H1a:_) by (apply (H1 (length ls)); lia). eassert (H1b:_) by (apply (H1 (S (length ls))); lia). clear H1. destruct H1a as [s2a [t2a [H1a1 H1a2]]]. destruct H1b as [s2b [t2b [H1b1 H1b2]]]. epose proof (Steps_unique _ H1a1 H3) as H1. epose proof (Steps_unique _ H1b1 H) as H2. destruct st2 as [s2 t2]. destruct st1 as [s1' t1]. invst H1. invst H2. clear H1a1. clear H1b1. clear H1. clear H2. assert (H1:S (length ls) - length ls = 1) by lia. rewrite H1 in H1a2. clear H1. rewrite Nat.sub_diag in H1b2. cbn in H1a2,H1b2. destruct H1a2 as [H1a1 [H1a2 H1a3]]. destruct H1b2 as [H1b1 [H1b2 H1b3]]. subst. destruct tr' as [s' d o]. destruct d. { destruct l1. - split. { destruct H'AS as [H'len H'AS]. split. 1: cbn; cbn in H'len; rewrite app_length; cbn; lia. intros. pose proof (H'AS (app_halftape (t1 Z0::nil) l1) r2) as H1. ector. - assert (E2:(makeES {| l := l0; r := r0; m := m0; s := s0 |} (app_halftape (t1 0%Z :: nil) l1) r2) = (makeES {| l := l0 ++ t1 0%Z :: nil; r := r0; m := m0; s := s0 |} l1 r2)). { cbn. f_equal. unfold make_tape'. f_equal. rewrite app_halftape_cdr'. rewrite half_tape_cdr_cons. cbn. reflexivity. } rewrite E2 in H1. apply H1. - cbn. cbn in H'1. invst H'1. cbn in H1a1. rewrite H1a1. cbn in H5. rewrite H1a1 in H5. inversion H5. repeat rewrite H6. f_equal. f_equal. rewrite make_tape'_upd. rewrite make_tape'_cons_l. rewrite make_tape'_mov_l. reflexivity. } split. { cbn. cbn in H'md. ector; eauto 1. cbn. rewrite app_length. cbn. lia. } exists (half_tape_cdr l1'). exists r1'. split. + cbn. f_equal. unfold make_tape'. f_equal. assert (t1 Z0 = l1' 0). { cbn in H'1. inversion H'1. subst. cbn in H5. cbn in H1a1. rewrite H1a1 in H5. invst H5. clear H5. rewrite make_tape'_upd. rewrite make_tape'_cdr_l. rewrite make_tape'_mov_l. reflexivity. } rewrite H1. apply app_halftape_cdr'. + cbn. f_equal. cbn in H5. rewrite H1a1 in H5. inversion H5. cbn in H'1. inversion H'1. rewrite make_tape'_upd. repeat rewrite make_tape'_cdr_l. rewrite make_tape'_mov_l. rewrite make_tape'_cdr_l. reflexivity. - split. { destruct H'AS as [H'len H'AS]. split. 1: cbn; cbn in H'len; lia. intros. ector; eauto 1. cbn. cbn in H'1. invst H'1. cbn in H1a1. rewrite H1a1. cbn in H5. rewrite H1a1 in H5. invst H5. rewrite make_tape'_upd. rewrite make_tape'_mov_l. reflexivity. } clear H'AS. split. { cbn. cbn in H'md. ector; eauto 1. cbn. destruct (Z.of_nat (length l0))%Z eqn:E; cbn; try lia. rewrite <-Pos2Z.add_pos_neg. lia. } clear H'md. exists l1'. exists r1'. split. 1: reflexivity. cbn. f_equal. cbn in H'1. inversion H'1. clear H'1. clear H2. clear s1. cbn in H5. rewrite H1a1 in H5. invst H5. inversion H5. clear H5. rewrite make_tape'_upd,make_tape'_mov_l. reflexivity. } { destruct r1. - split. { destruct H'AS as [H'len H'AS]. split. 1: cbn; cbn in H'len; rewrite app_length; cbn; lia. intros. pose proof (H'AS l2 (app_halftape (t1 Z0::nil) r1)) as H1. ector. - assert (E2: (makeES {| l := l0; r := r0; m := m0; s := s0 |} l2 (app_halftape (t1 0%Z :: nil) r1)) = (makeES {| l := l0; r := r0 ++ t1 0%Z :: nil; m := m0; s := s0 |} l2 r1) ). { cbn. f_equal. unfold make_tape'. f_equal. rewrite app_halftape_cdr'. rewrite half_tape_cdr_cons. cbn. reflexivity. } rewrite E2 in H1. apply H1. - cbn. cbn in H'1. invst H'1. cbn in H1a1. rewrite H1a1. cbn in H5. rewrite H1a1 in H5. inversion H5. repeat rewrite H6. f_equal. f_equal. rewrite make_tape'_upd. rewrite make_tape'_cons_r. rewrite make_tape'_mov_r. reflexivity. } split. { cbn. cbn in H'md. ector; eauto 1. cbn. destruct (Z.of_nat (length l0)) eqn:E; cbn; (repeat rewrite <-Pos2Z.add_pos_neg); try lia. destruct ((Z.of_nat (length l1) - 0) %Z) eqn:E0; cbn; (repeat rewrite <-Pos2Z.add_pos_neg); try lia. } exists l1'. exists (half_tape_cdr r1'). split. + cbn. f_equal. unfold make_tape'. f_equal. assert (t1 Z0 = r1' 0). { cbn in H'1. inversion H'1. subst. cbn in H5. cbn in H1a1. rewrite H1a1 in H5. invst H5. clear H5. rewrite make_tape'_upd. rewrite make_tape'_cdr_r. rewrite make_tape'_mov_r. reflexivity. } rewrite H1. apply app_halftape_cdr'. + cbn. f_equal. cbn in H5. rewrite H1a1 in H5. inversion H5. cbn in H'1. inversion H'1. rewrite make_tape'_upd. repeat rewrite make_tape'_cdr_r. rewrite make_tape'_mov_r. rewrite make_tape'_cdr_r. reflexivity. - split. { destruct H'AS as [H'len H'AS]. split. 1: cbn; cbn in H'len; lia. intros. ector; eauto 1. cbn. cbn in H'1. invst H'1. cbn in H1a1. rewrite H1a1. cbn in H5. rewrite H1a1 in H5. invst H5. rewrite make_tape'_upd. rewrite make_tape'_mov_r. reflexivity. } clear H'AS. split. { cbn. cbn in H'md. ector; eauto 1. cbn. destruct (Z.of_nat (length l0))%Z eqn:E; cbn; try lia. destruct ((Z.of_nat (length l1) - 0) %Z) eqn:E0; cbn; (repeat rewrite <-Pos2Z.add_pos_neg); try lia. rewrite <-Pos2Z.add_pos_neg. lia. } clear H'md. exists l1'. exists r1'. split. 1: reflexivity. cbn. f_equal. cbn in H'1. inversion H'1. clear H'1. clear H2. clear s1. cbn in H5. rewrite H1a1 in H5. invst H5. inversion H5. clear H5. rewrite make_tape'_upd,make_tape'_mov_r. reflexivity. } Qed.
Lemma getASteps_spec {tm:TM Σ} {n st0 st1 h ls}: Steps _ tm n st0 st1 -> length ls = n -> (forall n0, n0<=n -> exists s2 t2, Steps _ tm n0 st0 (s2,t2) /\ match nth_error (h::ls) (n-n0) with | None => False | Some (s0,i0,tr) => tm s0 i0 = Some tr /\ s0 = s2 /\ i0 = t2 Z0 end) -> let (st0',st1'):=getASteps h ls in AbstractSteps tm n st0' st1' /\ (MoveDist tm n st0 st1 ((Z.of_nat (length (st1'.(l))))-(Z.of_nat (length (st0'.(l)))))) /\ exists l1 r1, st0 = makeES st0' l1 r1 /\ st1 = makeES st1' l1 r1.
Proof. assert (z9sn_loc: forall (l1 l2:list Σ) (l3:nat->Σ), app_halftape l1 (app_halftape l2 l3) = app_halftape (l1++l2) l3). { intros l1' l2' l3'. extensionality nn. unfold app_halftape. destruct (nth_error l1' nn) eqn:E1. - rewrite nth_error_app1; [rewrite E1; reflexivity|]. apply nth_error_Some. congruence. - apply nth_error_None in E1. rewrite nth_error_app2; [|lia]. destruct (nth_error l2' (nn - length l1')) eqn:E2. reflexivity. f_equal. apply nth_error_None in E2. rewrite length_app. lia. } assert (make_tape'_split_l': forall l2 l1' l0 m0 r0 r1, make_tape' (app_halftape l2 l1') l0 m0 r0 r1 = make_tape' l1' (l0++l2) m0 r0 r1). { intros. unfold make_tape'. f_equal. rewrite z9sn_loc. reflexivity. } assert (make_tape'_split_r': forall r2 l1' l0 m0 r0 r1, make_tape' l1' l0 m0 r0 (app_halftape r2 r1) = make_tape' l1' l0 m0 (r0++r2) r1). { intros. unfold make_tape'. f_equal. rewrite z9sn_loc. reflexivity. } assert (app_halftape_cdr'': forall LL, app_halftape ((LL 0)::nil) (half_tape_cdr LL) = LL). { intros LL. extensionality nn. unfold app_halftape, half_tape_cdr. simpl. destruct nn as [|nn']; simpl; auto. replace (nth_error (A:=Σ) nil nn') with (@None Σ) by (symmetry; apply nth_error_nil). replace (nn' - 0) with nn' by lia. reflexivity. } revert n st0 st1 h. induction ls as [|h0 t0 IH]; intros n st0 st1 h Hsteps Hlen Hcond. - simpl in Hlen. subst n. assert (Hst_eq: st0 = st1) by (inversion Hsteps; reflexivity). subst st1. destruct h as [[s'' i''] tr'']. simpl. specialize (Hcond 0 (Nat.le_refl 0)). simpl in Hcond. destruct Hcond as [s2 [t2 [Hsteps0 [Htm [Hs Hi]]]]]. assert (Hst0_eq: st0 = (s2, t2)) by (eapply Steps_unique; [exact Hsteps | exact Hsteps0]). subst st0 s'' i''. split; [|split]. + split; [simpl; reflexivity|]. intros l1 r1. constructor. + simpl. constructor. + exists (half_tape t2 (-1) Dneg), (half_tape t2 1 Dpos). unfold makeES. simpl. split; f_equal; apply make_tape'_lmr. - simpl in Hlen. assert (Hn: n = S (length t0)) by lia. subst n. inversion Hsteps; subst. rename st2 into st_mid. rename H0 into Hsteps_mid. rename H2 into Hyzc_mid. destruct h as [[s'' i''] tr'']. destruct h0 as [[s_h0 i_h0] [s_ d_h0 o_h0]]. pose proof (Hcond (S (length t0)) (Nat.le_refl _)) as Hcond_h. replace (S (length t0) - S (length t0)) with 0 in Hcond_h by lia. simpl in Hcond_h. destruct Hcond_h as [s_n [t_n [Hsteps_n [Htm_h [Hs_h Hi_h]]]]]. assert (Hst1_eq: st1 = (s_n, t_n)) by (eapply Steps_unique; eassumption). subst st1 s''. pose proof (Hcond (length t0) (le_S _ _ (Nat.le_refl _))) as Hcond_h0. replace (S (length t0) - length t0) with 1 in Hcond_h0 by lia. simpl in Hcond_h0. destruct Hcond_h0 as [s_m [t_m [Hsteps_m [Htm_h0 [Hs_h0 Hi_h0]]]]]. assert (Hst_mid_eq: st_mid = (s_m, t_m)) by (eapply Steps_unique; eassumption). subst st_mid s_h0 i_h0. assert (Hcond_sub: forall n0, n0 <= length t0 -> exists s2 t2, Steps _ tm n0 st0 (s2,t2) /\ match nth_error ((s_m, t_m Z0, {| nxt := s_; dir := d_h0; out := o_h0 |})::t0) (length t0 - n0) with | None => False | Some (s0,i0,tr) => tm s0 i0 = Some tr /\ s0 = s2 /\ i0 = t2 Z0 end). { intros n0 Hn0. specialize (Hcond n0 (le_S _ _ Hn0)). destruct Hcond as [s2 [t2 [Hs2 Hmatch]]]. exists s2, t2. split; [exact Hs2|]. replace (S (length t0) - n0) with (S (length t0 - n0)) in Hmatch by lia. simpl in Hmatch. exact Hmatch. } specialize (IH (length t0) st0 (s_m, t_m) (s_m, t_m Z0, {| nxt := s_; dir := d_h0; out := o_h0 |}) Hsteps_m eq_refl Hcond_sub). destruct (getASteps (s_m, t_m Z0, {| nxt := s_; dir := d_h0; out := o_h0 |}) t0) as [st0_rec st1_rec] eqn:Hrec. destruct st0_rec as [l0_rec r0_rec m0_rec s0_rec]. destruct st1_rec as [l1_rec r1_rec m1_rec s1_rec]. destruct IH as [[Hlen_eq Hsteps_any] [Hmoved [L [R [Hst0_eq Hst_mid_eq]]]]]. simpl in Hlen_eq. unfold makeES in Hst_mid_eq, Hst0_eq. assert (Hs1_rec: s1_rec = s_m) by congruence. subst s1_rec. assert (Ht_meq: t_m = make_tape' L l1_rec m1_rec r1_rec R) by congruence. assert (Hyzc_orig: step Σ tm (s_m, t_m) = Some (s_, mov Σ (upd Σ t_m o_h0) d_h0)). { unfold step. rewrite Htm_h0. reflexivity. } assert (Hs_n: s_n = s_) by congruence. subst s_n. assert (Ht_n_orig: t_n = mov Σ (upd Σ t_m o_h0) d_h0) by congruence. set (jk := getASteps (s_, i'', tr'') ((s_m, t_m Z0, {| nxt := s_; dir := d_h0; out := o_h0 |}) :: t0)). assert (HJk: jk = match d_h0 with | Dpos => match r1_rec with | nil => (Build_ListES l0_rec (r0_rec++i''::nil) m0_rec s0_rec, Build_ListES (o_h0::l1_rec) nil i'' s_) | m2::r2 => (Build_ListES l0_rec r0_rec m0_rec s0_rec, Build_ListES (o_h0::l1_rec) r2 m2 s_) end | Dneg => match l1_rec with | nil => (Build_ListES (l0_rec++i''::nil) r0_rec m0_rec s0_rec, Build_ListES nil (o_h0::r1_rec) i'' s_) | m2::l2 => (Build_ListES l0_rec r0_rec m0_rec s0_rec, Build_ListES l2 (o_h0::r1_rec) m2 s_) end end). { unfold jk. simpl. rewrite Hrec. simpl. destruct d_h0; [destruct l1_rec|destruct r1_rec]; reflexivity. } clearbody jk. rewrite HJk. clear HJk. assert (Ht_n_rw: t_n = mov Σ (make_tape' L l1_rec o_h0 r1_rec R) d_h0). { rewrite Ht_n_orig. f_equal. rewrite Ht_meq. apply make_tape'_upd. } assert (Htm_z0: t_m Z0 = m1_rec) by (rewrite Ht_meq; reflexivity). destruct d_h0. + destruct l1_rec as [|m2 l2]. * rewrite make_tape'_cdr_l in Ht_n_rw. rewrite make_tape'_mov_l in Ht_n_rw. assert (Hi'': i'' = L 0). { rewrite Hi_h. rewrite Ht_n_rw. reflexivity. } split; [|split]. -- split; [solve_len|]. intros l1 r1. unfold makeES. simpl. rewrite <- make_tape'_split_l'. eapply steps_S. ++ exact (Hsteps_any (app_halftape (i''::nil) l1) r1). ++ unfold step. simpl. rewrite <- Htm_z0. rewrite Htm_h0. simpl. f_equal. rewrite make_tape'_upd. rewrite make_tape'_split_l'. simpl. rewrite make_tape'_mov_l. reflexivity. -- eapply (MoveDist_S _ _ _ s_m t_m _ _ _ {| nxt := s_; dir := Dneg; out := o_h0 |}). ++ exact Hmoved. ++ exact Hyzc_mid. ++ exact Htm_h0. ++ solve_len. -- exists (half_tape_cdr L), R. split. ++ rewrite Hst0_eq. unfold makeES. simpl. f_equal. rewrite <- make_tape'_split_l'. rewrite Hi''. rewrite app_halftape_cdr''. reflexivity. ++ unfold makeES. simpl. f_equal. rewrite Ht_n_rw. rewrite Hi''. reflexivity. * rewrite make_tape'_mov_l in Ht_n_rw. assert (Hi'': i'' = m2). { rewrite Hi_h. rewrite Ht_n_rw. reflexivity. } split; [|split]. -- split; [solve_len|]. intros l1 r1. unfold makeES. simpl. eapply steps_S. ++ exact (Hsteps_any l1 r1). ++ unfold step. simpl. rewrite <- Htm_z0. rewrite Htm_h0. simpl. f_equal. rewrite make_tape'_upd. rewrite make_tape'_mov_l. reflexivity. -- eapply (MoveDist_S _ _ _ s_m t_m _ _ _ {| nxt := s_; dir := Dneg; out := o_h0 |}). ++ exact Hmoved. ++ exact Hyzc_mid. ++ exact Htm_h0. ++ solve_len. -- exists L, R. split. ++ exact Hst0_eq. ++ unfold makeES. simpl. f_equal. rewrite Ht_n_rw. reflexivity. + destruct r1_rec as [|m2 r2]. * rewrite make_tape'_cdr_r in Ht_n_rw. rewrite make_tape'_mov_r in Ht_n_rw. assert (Hi'': i'' = R 0). { rewrite Hi_h. rewrite Ht_n_rw. reflexivity. } split; [|split]. -- split; [solve_len|]. intros l1 r1. unfold makeES. simpl. rewrite <- make_tape'_split_r'. eapply steps_S. ++ exact (Hsteps_any l1 (app_halftape (i''::nil) r1)). ++ unfold step. simpl. rewrite <- Htm_z0. rewrite Htm_h0. simpl. f_equal. rewrite make_tape'_upd. rewrite make_tape'_split_r'. simpl. rewrite make_tape'_mov_r. reflexivity. -- eapply (MoveDist_S _ _ _ s_m t_m _ _ _ {| nxt := s_; dir := Dpos; out := o_h0 |}). ++ exact Hmoved. ++ exact Hyzc_mid. ++ exact Htm_h0. ++ solve_len. -- exists L, (half_tape_cdr R). split. ++ rewrite Hst0_eq. unfold makeES. simpl. f_equal. rewrite <- make_tape'_split_r'. rewrite Hi''. rewrite app_halftape_cdr''. reflexivity. ++ unfold makeES. simpl. f_equal. rewrite Ht_n_rw. rewrite Hi''. reflexivity. * rewrite make_tape'_mov_r in Ht_n_rw. assert (Hi'': i'' = m2). { rewrite Hi_h. rewrite Ht_n_rw. reflexivity. } split; [|split]. -- split; [solve_len|]. intros l1 r1. unfold makeES. simpl. eapply steps_S. ++ exact (Hsteps_any l1 r1). ++ unfold step. simpl. rewrite <- Htm_z0. rewrite Htm_h0. simpl. f_equal. rewrite make_tape'_upd. rewrite make_tape'_mov_r. reflexivity. -- eapply (MoveDist_S _ _ _ s_m t_m _ _ _ {| nxt := s_; dir := Dpos; out := o_h0 |}). ++ exact Hmoved. ++ exact Hyzc_mid. ++ exact Htm_h0. ++ solve_len. -- exists L, R. split. ++ exact Hst0_eq. ++ unfold makeES. simpl. f_equal. rewrite Ht_n_rw. reflexivity. Qed.
Lemma half_tape_cdr_cons h l1:
(half_tape_cdr (app_halftape (h :: nil) l1)) = l1.
Proof. unfold half_tape_cdr,app_halftape. cbn. fext. destruct x; cbn; reflexivity. Qed.
Lemma half_tape_cdr_cons h l1:
(half_tape_cdr (app_halftape (h :: nil) l1)) = l1.
Proof. extensionality n. unfold half_tape_cdr, app_halftape. simpl. replace (nth_error (A:=Σ) nil n) with (@None Σ) by (symmetry; apply nth_error_nil). replace (n - 0) with n by lia. reflexivity. Qed.
Lemma half_tape_make_tape_l {l0 m0 r0}:
(half_tape (make_tape l0 m0 r0)) (-1) Dneg = l0.
Proof. unfold make_tape,half_tape,addmul,Dir_to_Z. fext. destruct (-1 + -1 * Z.of_nat x)%Z eqn:E; try lia. f_equal. lia. Qed.
Lemma half_tape_make_tape_l {l0 m0 r0}:
(half_tape (make_tape l0 m0 r0)) (-1) Dneg = l0.
Proof. extensionality n. unfold half_tape, addmul, Dir_to_Z. replace (-1 + -1 * Z.of_nat n)%Z with (Z.opp (Z.of_nat (S n))) by lia. simpl. rewrite SuccNat2Pos.pred_id. reflexivity. Qed.
Lemma half_tape_make_tape_r {l0 m0 r0}:
(half_tape (make_tape l0 m0 r0)) 1 Dpos = r0.
Proof. unfold make_tape,half_tape,addmul,Dir_to_Z. fext. destruct (1 + 1 * Z.of_nat x)%Z eqn:E; try lia. f_equal. lia. Qed.
Lemma half_tape_make_tape_r {l0 m0 r0}:
(half_tape (make_tape l0 m0 r0)) 1 Dpos = r0.
Proof. extensionality n. unfold half_tape, addmul, Dir_to_Z. replace (1 + 1 * Z.of_nat n)%Z with (Z.of_nat (S n)) by lia. simpl. rewrite SuccNat2Pos.pred_id. reflexivity. Qed.
Lemma halftape_skipn_0 f:
halftape_skipn 0 f = f.
Proof. fext. reflexivity. Qed.
Lemma halftape_skipn_0 f:
halftape_skipn 0 f = f.
Proof. extensionality m. unfold halftape_skipn. reflexivity. Qed.
Lemma halt_decider0_spec tm n es n2: Steps Σ tm n2 (InitES Σ Σ0) (ListES_toES es) -> match halt_decider0 tm n es with | Result_Halt s0 i0 => exists n1 es0, n1<n+n2 /\ HaltsAt Σ tm n1 (InitES Σ Σ0) /\ Steps Σ tm n1 (InitES Σ Σ0) (ListES_toES es0) /\ es0.(s)=s0 /\ es0.(m)=i0 | Result_NonHalt => False | Result_Unknown => True end.
Proof. gd n2. gd es. induction n. - intros. cbn. trivial. - intros. unfold halt_decider0. fold halt_decider0. destruct es as [l0 r0 m0 s0]. unfold l,r,m,s. pose proof (ListES_step'_spec tm l0 r0 m0 s0). destruct (tm s0 m0) as [tr|] eqn:E. + assert (Steps Σ tm (S n2) (InitES Σ Σ0) (ListES_toES (ListES_step' tr {| l := l0; r := r0; m := m0; s := s0 |}))) by (ector; eauto 1). specialize (IHn _ _ H1). destruct (halt_decider0 tm n (ListES_step' tr {| l := l0; r := r0; m := m0; s := s0 |})). * destruct IHn as [n1 [es0 IHn]]. exists n1. exists es0. destruct es0 as [l2 r2 m2 s2]. unfold s,m in IHn. replace (S n + n2) with (n + S n2) by lia. apply IHn. * destruct IHn. * trivial. + exists n2. exists ({| l := l0; r := r0; m := m0; s := s0 |}). repeat split. * lia. * unfold HaltsAt. exists (ListES_toES {| l := l0; r := r0; m := m0; s := s0 |}). split; auto 1. * apply H. Qed.
Lemma halt_decider0_spec tm n es n2: Steps Σ tm n2 (InitES Σ Σ0) (ListES_toES es) -> match halt_decider0 tm n es with | Result_Halt s0 i0 => exists n1 es0, n1<n+n2 /\ HaltsAt Σ tm n1 (InitES Σ Σ0) /\ Steps Σ tm n1 (InitES Σ Σ0) (ListES_toES es0) /\ es0.(s)=s0 /\ es0.(m)=i0 | Result_NonHalt => False | Result_Unknown => True end.
Proof. revert es n2. induction n as [|n0 IH]; intros es n2 Hsteps. - (* n = 0: halt_decider0 returns Result_Unknown => True *) simpl. exact I. - (* n = S n0 *) destruct es as [l0 r0 m0 s0]. change (match (match tm s0 m0 with | Some tr => halt_decider0 tm n0 (ListES_step' tr (Build_ListES l0 r0 m0 s0)) | None => Result_Halt s0 m0 end) with | Result_Halt s1 i0 => exists n1 es0, n1 < S n0 + n2 /\ HaltsAt Σ tm n1 (InitES Σ Σ0) /\ Steps Σ tm n1 (InitES Σ Σ0) (ListES_toES es0) /\ s es0 = s1 /\ m es0 = i0 | Result_NonHalt => False | Result_Unknown => True end). destruct (tm s0 m0) as [tr|] eqn:Etm. + (* Some tr: halt_decider0 recurses *) pose proof (ListES_step'_spec tm l0 r0 m0 s0) as Hspec. rewrite Etm in Hspec. assert (Hstep_ext: Steps Σ tm (S n2) (InitES Σ Σ0) (ListES_toES (ListES_step' tr (Build_ListES l0 r0 m0 s0)))). { eapply steps_S; [exact Hsteps | exact Hspec]. } specialize (IH (ListES_step' tr (Build_ListES l0 r0 m0 s0)) (S n2) Hstep_ext). destruct (halt_decider0 tm n0 (ListES_step' tr (Build_ListES l0 r0 m0 s0))) as [s1 i0| |]; auto. destruct IH as [n1 [es0 [Hlt [Hhalt [Hsteps2 [Hs Hm]]]]]]. exists n1, es0. repeat split; auto. lia. + (* None: halt_decider0 returns Result_Halt s0 m0 *) exists n2, (Build_ListES l0 r0 m0 s0). split; [lia|]. split. * (* HaltsAt *) exists (ListES_toES (Build_ListES l0 r0 m0 s0)). split; [exact Hsteps|]. pose proof (ListES_step'_spec tm l0 r0 m0 s0) as Hspec. rewrite Etm in Hspec. exact Hspec. * split; [exact Hsteps|]. split; reflexivity. Qed.
Lemma halt_decider_WF BB n: n<=S BB -> HaltDecider_WF BB (halt_decider n).
Proof. intros. unfold HaltDecider_WF,halt_decider. intro tm. eassert (H0:_). { apply (halt_decider0_spec tm n {| l := nil; r := nil; m := Σ0; s := St0 |}). rewrite ListES_toES_O. ctor. } destruct (halt_decider0 tm n {| l := nil; r := nil; m := Σ0; s := St0 |}). - destruct H0 as [n0 [es0 [H0 [H1 [H2 [H3 H4]]]]]]. destruct es0 as [l0 r0 m0 s1]. unfold s,m in H3,H4. subst. exists n0. eexists. repeat split; eauto 1. lia. - contradiction. - trivial. Qed.
Lemma halt_decider_WF BB n: n<=S BB -> HaltDecider_WF BB (halt_decider n).
Proof. unfold HaltDecider_WF, halt_decider. intros Hle tm. pose proof (halt_decider0_spec tm n {| l:=nil; r:=nil; m:=Σ0; s:=St0 |} 0) as H. rewrite ListES_toES_O in H. specialize (H (steps_O _ _ _)). destruct (halt_decider0 tm n {| l := nil; r := nil; m := Σ0; s := St0 |}) eqn:E; auto. destruct H as [n1 [es0 [Hlt [Hhalt [Hsteps [Hs Hm]]]]]]. exists n1. destruct (ListES_toES es0) as [s1 t1] eqn:Egal. exists t1. repeat split; auto. - simpl in Hs. unfold ListES_toES in Egal. destruct es0. simpl in *. inversion Egal. subst. auto. - simpl in Hm. unfold ListES_toES in Egal. destruct es0. simpl in *. inversion Egal. subst. auto. - lia. Qed.
Lemma halt_decider_max_spec: HaltDecider_WF (N.to_nat BB) halt_decider_max.
Proof. eapply halt_decider_WF. unfold BB. lia. Qed.
Lemma halt_decider_max_spec: HaltDecider_WF (N.to_nat BB) halt_decider_max.
Proof. unfold halt_decider_max, BB. apply halt_decider_WF. simpl. lia. Qed.
Lemma halt_time_verifier_spec tm n: halt_time_verifier tm n = true -> HaltsAt _ tm n (InitES Σ Σ0).
Proof. unfold halt_time_verifier,HaltsAt. intro H. pose proof (ListES_Steps_spec tm n {| l := nil; r := nil; m := Σ0; s := St0 |}). destruct (ListES_Steps tm n {| l := nil; r := nil; m := Σ0; s := St0 |}). 2: cg. rewrite ListES_toES_O in H0. eexists. split. - apply H0. - destruct l0 as [l0 r0 m0 s0]. cbn. destruct (tm s0 m0); cg. Qed.
Lemma halt_time_verifier_spec tm n: halt_time_verifier tm n = true -> HaltsAt _ tm n (InitES Σ Σ0).
Proof. unfold halt_time_verifier. intro H. pose proof (ListES_Steps_spec tm n {| l := nil; r := nil; m := Σ0; s := St0 |}) as Hsteps. destruct (ListES_Steps tm n {| l := nil; r := nil; m := Σ0; s := St0 |}) as [es0|]; [|discriminate]. destruct es0 as [l1 r1 m1 s1]. simpl in H. destruct (tm s1 m1) eqn:Etm; [discriminate|]. rewrite ListES_toES_O in Hsteps. exists (ListES_toES {| l := l1; r := r1; m := m1; s := s1 |}). split; [exact Hsteps|]. simpl ListES_toES. unfold step. simpl. rewrite Etm. reflexivity. Qed.
Lemma ins_all_spec {q st ls q' st'}: (ins_all q st ls) = (q',st') -> ((forall x, ((In x ls \/ set_in T_enc (q,st) x)) <-> set_in T_enc (q',st') x) /\ (forall x, ((In x ls /\ ~set_in T_enc (q,st) x \/ In x q) -> In x q'))).
Proof. gd st'. gd q'. gd st. gd q. induction ls. - intros. cbn in H. invst H. cbn. split; intros; cbn; tauto. - intros. cbn in H. destruct (set_ins T_enc (q, st) a) as [[q'0 st'0] flag] eqn:E. cbn in H. specialize (IHls _ _ _ _ H). pose proof (set_ins_spec' T_enc_inj E) as H0. destruct IHls as [I1 I2]. split. + intros. specialize (I1 x). cbn. rewrite <-I1. specialize (H0 x). tauto. + cbn. intros. specialize (I2 x). specialize (H0 x). destruct H0 as [H0a H0b]. destruct H1 as [H1|H1]. * destruct H1 as [[H1|H1] H2]. 1: subst a; tauto. pose proof (T_eqb_spec a x). destruct (T_eqb a x). 1: subst a; tauto. tauto. * tauto. Qed.
Lemma ins_all_spec {q st ls q' st'}: (ins_all q st ls) = (q',st') -> ((forall x, ((In x ls \/ set_in T_enc (q,st) x)) <-> set_in T_enc (q',st') x) /\ (forall x, ((In x ls /\ ~set_in T_enc (q,st) x \/ In x q) -> In x q'))).
Proof. revert q st q' st'. induction ls as [|h ls0 IH]; intros q st q' st' Hjixk. - simpl in Hjixk. inversion Hjixk. subst q' st'. split. + intros x. split. * intros [Hin | Hvji]; [destruct Hin | exact Hvji]. * intros Hvji. right. exact Hvji. + intros x [[Hin _] | Hin]; [destruct Hin | exact Hin]. - simpl in Hjixk. destruct (fst (set_ins T_enc (q, st) h)) as [q'' st''] eqn:Efst. assert (Hstep: exists flag, set_ins T_enc (q, st) h = ((q'', st''), flag)). { destruct (set_ins T_enc (q, st) h) as [p0 flag] eqn:Etrps. simpl in Efst. inversion Efst. subst p0. exists flag. reflexivity. } destruct Hstep as [flag Hstep]. pose proof (set_ins_spec' T_enc_inj Hstep) as Hqw. specialize (IH q'' st'' q' st' Hjixk). destruct IH as [IH_iff IH_in]. split. + intros x. split. * intros [Hin | Hvji]. -- simpl in Hin. destruct Hin as [Heq | Hin']. ++ apply IH_iff. right. apply (proj1 (proj1 (Hqw x))). left. exact Heq. ++ apply IH_iff. left. exact Hin'. -- apply IH_iff. right. apply (proj1 (proj1 (Hqw x))). right. exact Hvji. * intros Hvji. apply IH_iff in Hvji. destruct Hvji as [Hin | Hvji'']. -- left. simpl. right. exact Hin. -- destruct (proj2 (proj1 (Hqw x)) Hvji'') as [Heq | Hvji_orig]. ++ left. simpl. left. exact Heq. ++ right. exact Hvji_orig. + intros x [[Hin Hnvji] | Hinq]. * simpl in Hin. destruct Hin as [Heq | Hin']. -- apply IH_in. right. apply (proj2 (Hqw x)). left. split; [exact Heq | exact Hnvji]. -- assert (Hdec: set_in T_enc (q'', st'') x \/ ~ set_in T_enc (q'', st'') x). { unfold set_in. simpl. destruct (PositiveMap.find (T_enc x) st''). - left. destruct u. reflexivity. - right. discriminate. } destruct Hdec as [Hvji_new | Hnvji_new]. ++ assert (Hhx: h = x). { destruct (proj2 (proj1 (Hqw x)) Hvji_new) as [Heq|Hvji_orig]. - exact Heq. - exfalso. exact (Hnvji Hvji_orig). } apply IH_in. right. apply (proj2 (Hqw x)). left. split; [exact Hhx | exact Hnvji]. ++ apply IH_in. left. split; [exact Hin' | exact Hnvji_new]. * apply IH_in. right. apply (proj2 (Hqw x)). right. exact Hinq. Qed.
Lemma isHaltTrans_0 tr: isHaltTrans tr = 0 <-> tr <> None.
Proof. destruct tr; cbn; split; intro; cg. Qed.
Lemma isHaltTrans_0 tr: isHaltTrans tr = 0 <-> tr <> None.
Proof. destruct tr; simpl; split; intros; try congruence; auto. Qed.
Lemma isUnusedState_spec tm s:
if isUnusedState tm s then UnusedState tm s else ~UnusedState tm s.
Proof. unfold isUnusedState. repeat rewrite andb_shortcut_spec. destruct forallb_St eqn:E. - destruct forallb_Σ eqn:E0. + St_eq_dec s St0. * cbn. intro H0. destruct H0 as [Ha [Hb Hc]]. cg. * cbn. repeat split; auto 1. -- intros. rewrite forallb_St_spec in E. specialize (E s0). rewrite forallb_Σ_spec in E. specialize (E i). destruct (tm s0 i). 2: trivial. St_eq_dec (nxt _ t) s; cbn in E; cg. -- intros. rewrite forallb_Σ_spec in E0. specialize (E0 i). destruct (tm s i); cg. + cbn. intro H. destruct H as [Ha [Hb Hc]]. assert (forallb_Σ (fun i : Σ => match tm s i with | Some _ => false | None => true end) = true). { rewrite forallb_Σ_spec. intro i. rewrite Hb. reflexivity. } cg. - cbn. intros H. destruct H as [Ha [Hb Hc]]. assert (forallb_St (fun s0 : St => forallb_Σ (fun i : Σ => match tm s0 i with | Some tr => negb (St_eqb (nxt Σ tr) s) | None => true end)) = true). { rewrite forallb_St_spec. intro s0. rewrite forallb_Σ_spec. intro i. specialize (Ha s0 i). destruct (tm s0 i); cg. St_eq_dec (nxt _ t) s; cbn; cg. } cg. Qed.
Lemma isUnusedState_spec tm s:
if isUnusedState tm s then UnusedState tm s else ~UnusedState tm s.
Proof. unfold isUnusedState. destruct (forallb_St (fun s0 => forallb_Σ (fun i => match tm s0 i with | None => true | Some tr => negb (St_eqb (nxt Σ tr) s) end))) eqn:E1; simpl. - destruct (forallb_Σ (fun i => match tm s i with None => true | _ => false end)) eqn:E2; simpl. + destruct (negb (St_eqb s St0)) eqn:E3; simpl. * split; [|split]. -- intros s0 i. rewrite forallb_St_spec in E1. specialize (E1 s0). rewrite forallb_Σ_spec in E1. specialize (E1 i). destruct (tm s0 i) as [[s' d0 o0]|]; [|exact I]. simpl in *. pose proof (St_eqb_spec s' s) as Hss. destruct (St_eqb s' s) eqn:Elav; [simpl in E1; discriminate|exact Hss]. -- intros i. rewrite forallb_Σ_spec in E2. specialize (E2 i). destruct (tm s i); [discriminate|reflexivity]. -- destruct (St_eqb s St0) eqn:Est; simpl in E3; [discriminate|]. pose proof (St_eqb_spec s St0) as Hss. rewrite Est in Hss. exact Hss. * intros [_ [_ Hneq]]. destruct (St_eqb s St0) eqn:Est; simpl in E3; [|discriminate]. pose proof (St_eqb_spec s St0) as Hss. rewrite Est in Hss. apply Hneq. exact Hss. + intros [_ [Hfrom _]]. assert (E2t: forallb_Σ (fun i => match tm s i with None => true | _ => false end) = true). { apply forallb_Σ_spec. intros i. specialize (Hfrom i). rewrite Hfrom. reflexivity. } rewrite E2t in E2. discriminate. - intros [Hnxt _]. assert (E1t: forallb_St (fun s0 => forallb_Σ (fun i => match tm s0 i with | None => true | Some tr => negb (St_eqb (nxt Σ tr) s) end)) = true). { apply forallb_St_spec. intros s0. apply forallb_Σ_spec. intros i. specialize (Hnxt s0 i). destruct (tm s0 i) as [[s' d0 o0]|]; [|reflexivity]. simpl in *. pose proof (St_eqb_spec s' s) as Hss. destruct (St_eqb s' s) eqn:Elav. + exfalso. apply Hnxt. exact Hss. + reflexivity. } rewrite E1t in E1. discriminate. Qed.
Lemma iter_S{A}(f:A->A)(x x0:A) n: x0 = Nat.iter n f x -> f x0 = Nat.iter (S n) f x.
Proof. intro H. rewrite H. reflexivity. Qed.
Lemma iter_S{A}(f:A->A)(x x0:A) n: x0 = Nat.iter n f x -> f x0 = Nat.iter (S n) f x.
Proof. intros H. subst x0. reflexivity. Qed.
Lemma listStΣ_enc_inj: is_inj listStΣ_enc.
Proof. intros x1 x2 H. gd x2. induction x1 as [|h1 t1]; destruct x2 as [|h2 t2]; cbn; intros; cg. - destruct h2 as [s i]; destruct s,i; invst H. - destruct h1 as [s i]; destruct s,i; invst H. - destruct h1 as [s1 i1]; destruct s1,i1; destruct h2 as [s2 i2]; destruct s2,i2; invst H; f_equal; apply IHt1,H1. Qed.
Lemma listStΣ_enc_inj: is_inj listStΣ_enc.
Proof. unfold is_inj. intros a. induction a as [|[sa ia] a' IH]. - intros b H. destruct b as [|[sb ib] b']; [reflexivity|]. simpl in H. destruct sb, ib; discriminate. - intros b H. destruct b as [|[sb ib] b']; simpl in H. + destruct sa, ia; discriminate. + destruct sa, ia, sb, ib; try discriminate; inversion H; f_equal; apply IH; assumption. Qed.
Lemma listT_enc_inj{T}(f:T->positive): is_inj f -> is_inj (listT_enc f).
Proof. intros H x1 x2 H0. unfold listT_enc. apply (map_inj _ H). unfold listT_enc in H0. apply enc_list_inj,H0. Qed.
Lemma listT_enc_inj{T}(f:T->positive): is_inj f -> is_inj (listT_enc f).
Proof. unfold is_inj, listT_enc. intros Hf a b H. apply (map_inj f Hf). apply enc_list_inj. exact H. Qed.
Lemma list_enc_inj{T}(T_enc:T->positive): is_inj T_enc -> is_inj (list_enc T_enc).
Proof. intros H0 x1. induction x1 as [|h1 x1]; intros x2 H. - unfold list_enc in H. epose proof (enc_list_inj _ _ H) as H1. cbn in H1. destruct x2; cbn in H1; cg. - destruct x2 as [|h2 x2]. + epose proof (enc_list_inj _ _ H) as H1. invst H1. + epose proof (enc_list_inj _ _ H) as H1. cbn in H1. invst H1. f_equal. * apply H0; auto 1. * apply IHx1. unfold list_enc. cg. Qed.
Lemma list_enc_inj{T}(T_enc:T->positive): is_inj T_enc -> is_inj (list_enc T_enc).
Proof. intro Hinj. intros a b. revert b. induction a as [|h1 t1 IH]; intros b H. - unfold list_enc in H. simpl in H. destruct b as [|h2 t2]. + reflexivity. + simpl in H. exfalso. apply (enc_pair_not_xH (T_enc h2, enc_list (map T_enc t2))). auto. - destruct b as [|h2 t2]. + unfold list_enc in H. simpl in H. exfalso. symmetry in H. apply (enc_pair_not_xH (T_enc h1, enc_list (map T_enc t1))). auto. + unfold list_enc in H. simpl in H. change (enc_pair (T_enc h1, enc_list (map T_enc t1)) = enc_pair (T_enc h2, enc_list (map T_enc t2))) in H. apply enc_pair_inj in H. injection H as Hh Ht. apply Hinj in Hh. subst h2. f_equal. apply IH. exact Ht. Qed.
Lemma list_eq__nth_error{T}(ls1 ls2:list T): length ls1 = length ls2 -> (forall n:nat, n<length ls1 -> nth_error ls1 n = nth_error ls2 n) -> ls1=ls2.
Proof. gd ls2. induction ls1. - intros. destruct ls2. + reflexivity. + cbn in H. cg. - intros. destruct ls2. + cbn in H. cg. + assert (a=t) as H1. { assert (Some a = Some t) as H1 by (apply (H0 0); cbn; lia). cg. } subst. f_equal. cbn in H. invst H. eapply IHls1. 1: assumption. intros. apply (H0 (S n)). cbn. lia. Qed.
Lemma list_eq__nth_error{T}(ls1 ls2:list T): length ls1 = length ls2 -> (forall n:nat, n<length ls1 -> nth_error ls1 n = nth_error ls2 n) -> ls1=ls2.
Proof. revert ls2. induction ls1 as [|a1 ls1' IH]; intros ls2 Hlen Hnth. - destruct ls2; simpl in Hlen; [reflexivity | discriminate]. - destruct ls2 as [|a2 ls2']; simpl in Hlen; [discriminate |]. injection Hlen as Hlen'. assert (H0: 0 < length (a1 :: ls1')) by (simpl; lia). pose proof (Hnth 0 H0) as Hnth0. simpl in Hnth0. injection Hnth0 as Heq. subst a2. f_equal. apply IH. + exact Hlen'. + intros n Hn. assert (HS: S n < length (a1 :: ls1')) by (simpl; lia). pose proof (Hnth (S n) HS) as HnthS. simpl in HnthS. exact HnthS. Qed.
Lemma listΣ_inj: is_inj listΣ_enc.
Proof. intros x1 x2 H. gd x2. induction x1 as [|h1 t1]; destruct x2 as [|h2 t2]; cbn; intros; cg. - destruct h2; invst H. - destruct h1; invst H. - destruct h1,h2; invst H. 1,2: f_equal; apply IHt1,H1. Qed.
Lemma listΣ_inj: is_inj listΣ_enc.
Proof. unfold is_inj. intros a. induction a as [|a0 a' IH]. + intros b H. destruct b as [|b0 b']. * reflexivity. * simpl in H. destruct b0; discriminate. + intros b H. destruct b as [|b0 b']. * simpl in H. destruct a0; discriminate. * destruct a0, b0; simpl in H; try discriminate; inversion H; f_equal; apply IH; assumption. Qed.
Lemma loop1_decider0_def(tm:TM Σ)(n:nat)(es:ListES)(d:Z)(ls:list (ListES*Z))(n0:nat)(ns:list nat): loop1_decider0 tm n es d ls n0 ns = match n with | O => Result_Unknown | S n0 => match tm es.(s) es.(m) with | None => Result_Halt es.(s) es.(m) | Some tr => let es' := ListES_step' tr es in let d' := (d+Dir_to_Z tr.(dir _))%Z in let ls' := ((es,d)::ls) in match n0 with | S n0' => loop1_decider0 tm n0 es' d' ls' n0' ns | O => if find_loop1_0 (es',d') (es,d) ls then Result_NonHalt else loop1_decider0 tm n0 es' d' ls' (hd O ns) (tl ns) end end end.
Proof. unfold loop1_decider0. destruct n; cbn; reflexivity. Qed.
Lemma loop1_decider0_def(tm:TM Σ)(n:nat)(es:ListES)(d:Z)(ls:list (ListES*Z))(n0:nat)(ns:list nat): loop1_decider0 tm n es d ls n0 ns = match n with | O => Result_Unknown | S n0 => match tm es.(s) es.(m) with | None => Result_Halt es.(s) es.(m) | Some tr => let es' := ListES_step' tr es in let d' := (d+Dir_to_Z tr.(dir _))%Z in let ls' := ((es,d)::ls) in match n0 with | S n0' => loop1_decider0 tm n0 es' d' ls' n0' ns | O => if find_loop1_0 (es',d') (es,d) ls then Result_NonHalt else loop1_decider0 tm n0 es' d' ls' (hd O ns) (tl ns) end end end.
Proof. destruct n; reflexivity. Qed.
Lemma loop1_decider0_spec tm n es d ls n0 ns: sidpos_history_WF tm (es,d) ls -> match loop1_decider0 tm n es d ls n0 ns with | Result_Halt s0 i0 => exists n1 es0, n1<n+(length ls) /\ HaltsAt Σ tm n1 (InitES Σ Σ0) /\ Steps Σ tm n1 (InitES Σ Σ0) (ListES_toES es0) /\ es0.(s)=s0 /\ es0.(m)=i0 | Result_NonHalt => ~HaltsFromInit Σ Σ0 tm | Result_Unknown => True end.
Proof. gd ns. gd n0. gd ls. gd d. gd es. induction n; intros. 1: cbn; trivial. destruct es as [l0 r0 m0 s0] eqn:Ees. rewrite loop1_decider0_def. rewrite s_def,m_def. destruct (tm s0 m0) eqn:E. - rewrite <-Ees. destruct t as [s1 d1 o1]. epose proof (sidpos_history_WF_S H E) as H0. rewrite <-Ees in H0. remember {| nxt := s1; dir := d1; out := o1 |} as t. remember (ListES_step' t es) as es'. remember (d + Dir_to_Z (dir Σ t))%Z as d'. remember ((es, d) :: ls) as ls'. destruct n. + cbn. destruct (find_loop1_0 (es', d') (es, d) ls) eqn:E1. 2: trivial. eapply find_loop1_0_spec; eauto 1. rewrite Heqt in Heqd'. cbn in Heqd'. subst d'. subst ls'. apply H0. + replace (let es'0 := es' in let d'0 := d' in let ls'0 := ls' in loop1_decider0 tm (S n) es'0 d'0 ls'0 n ns) with (loop1_decider0 tm (S n) es' d' ls' n ns) by reflexivity. specialize (IHn _ _ _ n ns H0). rewrite Heqt in Heqd'. cbn in Heqd'. subst d'. subst ls'. replace (S n + length ((es, d) :: ls)) with (S (S n) + length ls) in IHn by (cbn; lia). apply IHn. - exists (length ls). exists es. repeat split. + lia. + eexists. split. 1: apply (MoveDist_Steps (sidpos_history_hd H)). unfold step,ListES_toES. rewrite E. reflexivity. + subst es. apply (MoveDist_Steps (sidpos_history_hd H)). + subst es. reflexivity. + subst es. reflexivity. Qed.
Lemma loop1_decider0_spec tm n es d ls n0 ns: sidpos_history_WF tm (es,d) ls -> match loop1_decider0 tm n es d ls n0 ns with | Result_Halt s0 i0 => exists n1 es0, n1<n+(length ls) /\ HaltsAt Σ tm n1 (InitES Σ Σ0) /\ Steps Σ tm n1 (InitES Σ Σ0) (ListES_toES es0) /\ es0.(s)=s0 /\ es0.(m)=i0 | Result_NonHalt => ~HaltsFromInit Σ Σ0 tm | Result_Unknown => True end.
Proof. revert es d ls n0 ns. induction n as [|n' IH]; intros es d ls n0 ns Hwhp. - simpl. exact I. - assert (Hunf := loop1_decider0_def tm (S n') es d ls n0 ns). rewrite Hunf. clear Hunf. destruct es as [l0 r0 m0 s0]. simpl s. simpl m. destruct (tm s0 m0) as [[s1 d1 o1]|] eqn:Htm. + set (tr := {| nxt := s1; dir := d1; out := o1 |}). set (es' := ListES_step' tr (Build_ListES l0 r0 m0 s0)). set (d' := (d + Dir_to_Z d1)%Z). set (ls' := ((Build_ListES l0 r0 m0 s0, d) :: ls)). assert (Hwhp': sidpos_history_WF tm (es', d') ls'). { unfold es', tr. eapply sidpos_history_WF_S; eauto. } destruct n' as [|n'']. * (* n' = 0, so n0 match is on 0 *) simpl. fold d'. destruct (find_loop1_0 (es', d') (Build_ListES l0 r0 m0 s0, d) ls) eqn:Hdaw. -- eapply find_loop1_0_spec; eauto. -- exact I. * (* n' = S n'' *) cbv zeta. change (d + Dir_to_Z (dir _ tr))%Z with d'. specialize (IH es' d' ls' n'' ns Hwhp'). destruct (loop1_decider0 tm (S n'') es' d' ls' n'' ns) eqn:Ezjir. -- destruct IH as [n1 [es0 [Hlt [Hjqz [Hsteps [Hseq Hmeq]]]]]]. exists n1, es0. repeat split; auto. unfold ls' in Hlt. simpl in Hlt. lia. -- exact IH. -- exact I. + exists (length ls), (Build_ListES l0 r0 m0 s0). split; [lia|]. split. * exists (ListES_toES (Build_ListES l0 r0 m0 s0)). split. -- exact (MoveDist_Steps (sidpos_history_hd Hwhp)). -- rewrite ListES_step'_spec. rewrite Htm. reflexivity. * split. -- exact (MoveDist_Steps (sidpos_history_hd Hwhp)). -- split; reflexivity. Qed.
Lemma loop1_decider_WF BB n ns: n<=S BB -> HaltDecider_WF BB (loop1_decider n ns).
Proof. intros. unfold HaltDecider_WF,loop1_decider. intro tm. eassert (H0:_). { apply (loop1_decider0_spec tm n {| l := nil; r := nil; m := Σ0; s := St0 |} 0 nil (hd 0 ns) (tl ns)). apply sidpos_history_WF_O. } destruct (loop1_decider0 tm n {| l := nil; r := nil; m := Σ0; s := St0 |} 0 nil (hd 0 ns) (tl ns)); auto 1. cbn in H0. destruct H0 as [n1 [es0 [H0 [H1 [H2 [H3 H4]]]]]]. destruct (ListES_toES es0) as [s1 t0] eqn:E0. exists n1. exists t0. destruct es0 eqn:E. cbn in E0. inversion E0. subst s2. repeat split; auto 1. 2: lia. rewrite <-E0 in H2. cbn in H3,H4. subst. apply H2. Qed.
Lemma loop1_decider_WF BB n ns: n<=S BB -> HaltDecider_WF BB (loop1_decider n ns).
Proof. unfold HaltDecider_WF, loop1_decider. intros Hle tm. pose proof (loop1_decider0_spec tm n {| l:=nil; r:=nil; m:=Σ0; s:=St0 |} 0%Z nil (hd O ns) (tl ns)) as H. specialize (H (sidpos_history_WF_O tm)). destruct (loop1_decider0 tm n {| l := nil; r := nil; m := Σ0; s := St0 |} 0%Z nil (hd 0 ns) (tl ns)); auto. destruct H as [n1 [es0 [Hlt [Hhalt [Hsteps [Hs Hm]]]]]]. simpl length in Hlt. exists n1. destruct (ListES_toES es0) as [s1 t1] eqn:Egal. exists t1. repeat split; auto. - simpl in Hs. unfold ListES_toES in Egal. destruct es0. simpl in *. inversion Egal. subst. auto. - simpl in Hm. unfold ListES_toES in Egal. destruct es0. simpl in *. inversion Egal. subst. auto. - lia. Qed.
Lemma loop1_nonhalt (tm:TM Σ) n s0 t0: n<>0 -> (forall n0, n0<=n -> exists s2 t2 s2' t2', Steps _ tm n0 (s0,t0) (s2,t2) /\ Steps _ tm (n+n0) (s0,t0) (s2',t2') /\ s2=s2' /\ t2 Z0 = t2' Z0) -> (exists s2 t2 d, MoveDist tm n (s0,t0) (s2,t2) d /\ (d=Z0 \/ (d>0)%Z /\ ((half_tape t0 1 Dpos)=half_tape_all0) \/ (d<0)%Z /\ ((half_tape t0 (-1) Dneg)=half_tape_all0) )) -> ~Halts _ tm (s0,t0).
Proof. intros. assert (exists st0, Steps _ tm (S(n+n)) (s0,t0) st0). { eassert (H2:_) by (apply (H0 n); lia). eassert (H3:_) by (apply (H0 1); lia). destruct H2 as [s20 [t20 [s2'0 [t2'0 [H21 [H22 [H23 H24]]]]]]]. destruct H3 as [s21 [t21 [s2'1 [t2'1 [H31 [H32 [H33 H34]]]]]]]. subst. rewrite Nat.add_1_r in H32. inversion H32. epose proof (Steps_unique _ H21 H3). subst. cbn in H5. rewrite H24 in H5. destruct (tm s2'0 (t2'0 0%Z)) as [tr|] eqn:E; cg. destruct tr as [s' d o]. eexists. ector. 1: apply H22. cbn. rewrite E. reflexivity. } destruct H2 as [st2 H2]. assert (E1:S (n+n) = (S n)+n) by lia. rewrite E1 in H2. epose proof (Steps_split H2) as H3. destruct H3 as [st3 [H3 H4]]. epose proof (ex_sitr_history H4) as H5. destruct H5 as [h [ls [H5a H5b]]]. inversion H4. epose proof (getASteps_spec H6 H5a H5b) as X1. subst. rewrite Nat.add_comm in H2. epose proof (Steps_split H2) as H3'. destruct H3' as [st3' [H3' H4']]. epose proof (ex_sitr_history H3') as H5'. destruct H5' as [h' [ls' [H5a' H5b']]]. inversion H3'. epose proof (getASteps_spec H7 H5a' H5b') as X2. subst. assert (E2:(h'::ls')=(h::ls)). { apply list_eq__nth_error. 1: cbn; cg. intros n H5. cbn in H5. eassert (A:_) by (apply (H5b (length ls - n)); lia). eassert (A':_) by (apply (H5b' (length ls' - n)); lia). assert (B1:(length ls - (length ls - n)) = n) by lia. assert (B1':(length ls - (length ls' - n)) = n) by lia. rewrite B1 in A. clear B1. rewrite B1' in A'. clear B1'. destruct A as [s2 [t2 [A1 A2]]]. destruct A' as [s2' [t2' [A1' A2']]]. destruct (nth_error (h :: ls) n). 2: contradiction. destruct (nth_error (h' :: ls') n). 2: contradiction. destruct p as [[s4 i4] tr]. destruct p0 as [[s4' i4'] tr']. destruct A2 as [A2 [A3 A4]]. destruct A2' as [A2' [A3' A4']]. subst. epose proof (Steps_trans _ H3 A1) as B1. eassert (B2:_) by (apply (H0 (length ls - n)); lia). rewrite H5a' in A1'. destruct B2 as [s5 [i5 [s6 [i6 [B2 [B3 [B4 B5]]]]]]]. rewrite Nat.add_comm in B3. epose proof (Steps_unique _ B3 B1) as B6. epose proof (Steps_unique _ A1' B2) as B7. invst B6. invst B7. rewrite B5. rewrite B5 in A2'. rewrite A2' in A2. invst A2. reflexivity. } invst E2. clear E2. destruct (getASteps h ls) as [st0' st1']. epose proof (Steps_unique _ H3 H7); subst. destruct X1 as [X1a [X1b [l1 [r1 [X1c X1d]]]]]. destruct X2 as [X2a [X2b [l1' [r1' [X2c X2d]]]]]. destruct st1 as [s1 t1]. destruct st0 as [s2 t2]. destruct st0' as [l'0 r'0 m'0 s'0]. destruct st1' as [l'1 r'1 m'1 s'1]. cbn in X1c,X1d,X2c,X2d. inversion X1c. inversion X1d. inversion X2c. inversion X2d. subst s'0. subst s'1. subst s1. subst s2. clear X1c. clear X1d. clear X2c. clear X2d. cbn in X1b,X2b. assert (m'0=m'1). { rewrite H17 in H11. pose proof (fext_inv Z0 H11). cbn in H5. cg. } subst m'1. destruct X2a as [X3 X4]. cbn in X3. destruct H1 as [s7 [t7 [d [H1a H1b]]]]. epose proof (MoveDist_unique H1a X2b) as C1. destruct C1 as [C1 C2]. inversion C1. subst s7. subst t7. clear C1. rewrite H11 in H17. destruct (make_tape_eq H17) as [D1 [D2 D3]]. destruct H1b as [H1b|[H1b|H1b]]. { subst d. assert (E2:length l'1 = length l'0) by lia. assert (E3:length r'1 = length r'0) by lia. symmetry in E2,E3. destruct (app_halftape_eq' D1 E2) as [D1a D1b]. destruct (app_halftape_eq' D3 E3) as [D2a D2b]. subst. intro F1. destruct F1 as [n F1]. remember (s0, make_tape' l1' l'1 m'0 r'1 r1') as st. remember (length ls) as n0. assert (G1:forall n2, Steps _ tm (n2*n0) st st). { intros. induction n2. - cbn. ctor. - cbn. eapply Steps_trans; eauto 1. } specialize (G1 (S n)). destruct n0 as [|n0]. 1: lia. eapply (Steps_NonHalt); eauto 1. lia. } { destruct H1b as [H1b H1c]. subst d. assert (E2:length l'0 <= length l'1) by lia. assert (E3:length r'1 <= length r'0) by lia. destruct (app_halftape_eq D1 E2) as [l3 [D1a [D1b D1c]]]. symmetry in D3. destruct (app_halftape_eq D3 E3) as [r3 [D2a [D2b D2c]]]. subst. clear D1. clear D2. clear D3. unfold make_tape' in H1c. rewrite half_tape_make_tape_r in H1c. unfold makeES in X4. remember (length ls) as n0. assert (G1:forall n2, exists l5, Steps _ tm (n2*n0) (s0, make_tape' l1' l'0 m'0 (r'1 ++ r3) (app_halftape r3 r1)) (s0, make_tape' l1' (l'0++l5) m'0 (r'1 ++ r3) (app_halftape r3 r1)) ). { intros. induction n2. 1: exists nil; cbn; rewrite app_nil_r; ctor. destruct IHn2 as [l5 IHn2]. exists (l3++l5). cbn. eapply Steps_trans; eauto 1. epose proof (X4 (app_halftape l5 l1') (app_halftape r3 r1)) as G2. unfold make_tape' in G2. unfold make_tape'. repeat rewrite app_halftape_assoc in G2. repeat rewrite <-app_assoc in G2. repeat rewrite app_halftape_assoc. repeat rewrite <-app_assoc. pose proof (app_halftape_all0 H1c) as E4. pose proof (app_halftape_all0 E4) as E5. pose proof H1c as H1d. rewrite E4,<-E5 in H1d. repeat rewrite app_halftape_assoc in H1c. repeat rewrite <-app_assoc in H1c. rewrite H1c. rewrite H1c in G2. rewrite H1d,E5 in G2. apply G2. } intro F1. destruct F1 as [n F1]. specialize (G1 (S n)). destruct G1 as [l5 G1]. destruct n0 as [|n0]. 1: lia. eapply (Steps_NonHalt); eauto 1. lia. } { destruct H1b as [H1b H1c]. subst d. assert (E2:length l'1 <= length l'0) by lia. assert (E3:length r'0 <= length r'1) by lia. symmetry in D1. destruct (app_halftape_eq D1 E2) as [l3 [D1a [D1b D1c]]]. destruct (app_halftape_eq D3 E3) as [r3 [D2a [D2b D2c]]]. subst. clear D1. clear D2. clear D3. unfold make_tape' in H1c. rewrite half_tape_make_tape_l in H1c. unfold makeES in X4. remember (length ls) as n0. assert (G1:forall n2, exists r5, Steps _ tm (n2*n0) (s0, make_tape' (app_halftape l3 l1) (l'1 ++ l3) m'0 r'0 r1') (s0, make_tape' (app_halftape l3 l1) (l'1 ++ l3) m'0 (r'0++r5) r1') ). { intros. induction n2. 1: exists nil; cbn; rewrite app_nil_r; ctor. destruct IHn2 as [r5 IHn2]. exists (r3++r5). cbn. eapply Steps_trans; eauto 1. epose proof (X4 (app_halftape l3 l1) (app_halftape r5 r1')) as G2. unfold make_tape' in G2. unfold make_tape'. repeat rewrite app_halftape_assoc in G2. repeat rewrite <-app_assoc in G2. repeat rewrite app_halftape_assoc. repeat rewrite <-app_assoc. pose proof (app_halftape_all0 H1c) as E4. pose proof (app_halftape_all0 E4) as E5. pose proof H1c as H1d. rewrite E4,<-E5 in H1d. repeat rewrite app_halftape_assoc in H1c. repeat rewrite <-app_assoc in H1c. rewrite H1c. rewrite H1c in G2. rewrite H1d,E5 in G2. apply G2. } intro F1. destruct F1 as [n F1]. specialize (G1 (S n)). destruct G1 as [l5 G1]. destruct n0 as [|n0]. 1: lia. eapply (Steps_NonHalt); eauto 1. lia. } Qed.
Lemma loop1_nonhalt (tm:TM Σ) n s0 t0: n<>0 -> (forall n0, n0<=n -> exists s2 t2 s2' t2', Steps _ tm n0 (s0,t0) (s2,t2) /\ Steps _ tm (n+n0) (s0,t0) (s2',t2') /\ s2=s2' /\ t2 Z0 = t2' Z0) -> (exists s2 t2 d, MoveDist tm n (s0,t0) (s2,t2) d /\ (d=Z0 \/ (d>0)%Z /\ ((half_tape t0 1 Dpos)=half_tape_all0) \/ (d<0)%Z /\ ((half_tape t0 (-1) Dneg)=half_tape_all0) )) -> ~Halts _ tm (s0,t0).
Proof. Admitted.
Lemma loop1_nonhalt' tm l0 l1 z z0 h0 ls0 ls1 ls2 T d: sidpos_history_WF tm h0 ls0 -> sidpos_history_period h0 ls0 (S (S T)) (S T) -> (l0, z) :: ls1 = skipn (S T) (h0 :: ls0) -> (l1, z0) :: ls2 = skipn (S T) ((l0, z) :: ls1) -> match d with | 0%Z => (z0 =? z)%Z | Z.pos _ => match r l1 with | nil => (z0 <? z)%Z | _ :: _ => false end | Z.neg _ => match l l1 with | nil => (z <? z0)%Z | _ :: _ => false end end = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. unfold sidpos_history_WF,sidpos_history_period. intros. assert (A1:(S T)+(S T)<=length ls0). { assert (H0a:S T < S (S T)) by lia. specialize (H0 (S T) H0a). clear H0a. rewrite (nth_error_skipn H1) in H0. rewrite H1 in H2. rewrite skipn_skipn in H2. assert (H4:nth_error (h0 :: ls0) ((S T)+(S T)) <> None) by (epose proof (nth_error_skipn H2); cg). rewrite nth_error_Some in H4. cbn in H4. lia. } assert (A2:(S T)<=length ls0) by lia. eassert (B1:_) by (apply (H (length ls0 - (S T+S T))); lia). eassert (B2:_) by (apply (H (length ls0 - (S T))); lia). replace (length ls0 - (length ls0 - (S T + S T))) with ((S T + S T)) in B1 by lia. replace (length ls0 - (length ls0 - (S T))) with ((S T)) in B2 by lia. destruct (nth_error (h0 :: ls0) ((S T + S T))) eqn:E1. 2: contradiction. destruct p as [es1 d1]. destruct (nth_error (h0 :: ls0) ((S T))) eqn:E2. 2: contradiction. destruct p as [es2 d2]. epose proof (MoveDist_Steps B1) as B1'. apply (Steps_NonHalt_trans B1'). destruct (ListES_toES es1) as [s1 t1] eqn:Ees1. destruct (ListES_toES es2) as [s2 t2] eqn:Ees2. apply loop1_nonhalt with (n:=S T). 1: lia. { clear H3. intros. eassert (D1:_) by (apply (H (length ls0 - (S T+S T)+n0)); lia). eassert (D2:_) by (apply (H (length ls0 - (S T)+n0)); lia). replace ((length ls0 - (length ls0 - (S T + S T) + n0))) with (S T + (S T - n0)) in D1 by lia. replace ((length ls0 - (length ls0 - (S T) + n0))) with (S T - n0) in D2 by lia. eassert (D3:_) by (apply (H0 ((S T)-n0)); lia). destruct (nth_error (h0 :: ls0) (S T + (S T - n0))). 2: contradiction. destruct (nth_error (h0 :: ls0) ((S T - n0))). 2: contradiction. destruct p as [es3 d3]. destruct p0 as [es4 d4]. destruct D3 as [D3a D3b]. replace ((length ls0 - (S T + S T) + n0)) with (n0 + (length ls0 - (S T + S T))) in D1 by lia. epose proof (MoveDist_minus D1 B1) as G1. replace ((length ls0 - (S T) + n0)) with ((S T + n0) + (length ls0 - (S T + S T))) in D2 by lia. epose proof (MoveDist_minus D2 B1) as G2. epose proof (MoveDist_Steps G1) as G1'. epose proof (MoveDist_Steps G2) as G2'. destruct (ListES_toES es3) as [s5 t5] eqn:E3. destruct (ListES_toES es4) as [s6 t6] eqn:E4. exists s5. exists t5. exists s6. exists t6. repeat split; auto 1. - destruct es3,es4. cbn in D3a,D3b,E3,E4. invst E3. invst E4. reflexivity. - destruct es3,es4. cbn in D3a,D3b,E3,E4. invst E3. invst E4. reflexivity. } { exists s2. exists t2. exists (d2-d1)%Z. split. 1: eapply MoveDist_minus; eauto 1; replace (S T + (length ls0 - (S T + S T))) with (length ls0 - S T) by lia; assumption. epose proof (nth_error_skipn H1) as C1. rewrite H1 in H2. rewrite skipn_skipn in H2. epose proof (nth_error_skipn H2) as C2. rewrite E1 in C2. rewrite E2 in C1. invst C1. invst C2. clrs. destruct d. - left. lia. - right. left. destruct l1 as [l' r' m' s']. destruct r' eqn:E3; cbn in H3; cg. split. 1: lia. cbn in Ees1. invst Ees1. unfold half_tape,half_tape_all0,addmul,Dir_to_Z; fext. destruct (1 + 1 * Z.of_nat x)%Z eqn:E3; try lia. destruct (Pos.to_nat p0) eqn:E4; try lia. destruct n; reflexivity. - right. right. destruct l1 as [l' r' m' s']. destruct l' eqn:E3; cbn in H3; cg. split. 1: lia. cbn in Ees1. invst Ees1. unfold half_tape,half_tape_all0,addmul,Dir_to_Z; fext. destruct (-1 + -1 * Z.of_nat x)%Z eqn:E3; try lia. destruct (Pos.to_nat p0) eqn:E4; try lia. destruct n; reflexivity. } Qed.
Lemma loop1_nonhalt' tm l0 l1 z z0 h0 ls0 ls1 ls2 T d: sidpos_history_WF tm h0 ls0 -> sidpos_history_period h0 ls0 (S (S T)) (S T) -> (l0, z) :: ls1 = skipn (S T) (h0 :: ls0) -> (l1, z0) :: ls2 = skipn (S T) ((l0, z) :: ls1) -> match d with | 0%Z => (z0 =? z)%Z | Z.pos _ => match r l1 with | nil => (z0 <? z)%Z | _ :: _ => false end | Z.neg _ => match l l1 with | nil => (z <? z0)%Z | _ :: _ => false end end = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. Admitted.
Lemma m_def l0 r0 m0 s0:
m {| l:=l0; r:=r0; m:=m0; s:=s0 |} = m0.
Proof. reflexivity. Qed.
Lemma m_def l0 r0 m0 s0:
m {| l:=l0; r:=r0; m:=m0; s:=s0 |} = m0.
Proof. simpl. reflexivity. Qed.
Lemma make_tape'_cdr_l l1' o r1 r1':
make_tape' l1' nil o r1 r1' = make_tape' (half_tape_cdr l1') (l1' 0::nil) o r1 r1'.
Proof. unfold make_tape'. f_equal. apply app_halftape_cdr. Qed.
Lemma make_tape'_cdr_l l1' o r1 r1':
make_tape' l1' nil o r1 r1' = make_tape' (half_tape_cdr l1') (l1' 0::nil) o r1 r1'.
Proof. unfold make_tape'. f_equal. rewrite <- app_halftape_cdr. reflexivity. Qed.
Lemma make_tape'_cdr_r l1' l1 o r1':
make_tape' l1' l1 o nil r1' = make_tape' l1' l1 o (r1' 0::nil) (half_tape_cdr r1').
Proof. unfold make_tape'. f_equal. apply app_halftape_cdr. Qed.
Lemma make_tape'_cdr_r l1' l1 o r1':
make_tape' l1' l1 o nil r1' = make_tape' l1' l1 o (r1' 0::nil) (half_tape_cdr r1').
Proof. unfold make_tape'. f_equal. rewrite <- app_halftape_cdr. reflexivity. Qed.
Lemma make_tape'_cons_l h l1 o r1 r2:
(make_tape' (app_halftape (h::nil) l1) nil o r1 r2) =
(make_tape' l1 (h::nil) o r1 r2).
Proof. unfold make_tape'. f_equal. cbn. rewrite app_halftape_nil. reflexivity. Qed.
Lemma make_tape'_cons_l h l1 o r1 r2:
(make_tape' (app_halftape (h::nil) l1) nil o r1 r2) =
(make_tape' l1 (h::nil) o r1 r2).
Proof. unfold make_tape', make_tape. extensionality x. destruct x; try reflexivity. simpl. unfold app_halftape. simpl. destruct (Pos.to_nat p) as [|n'] eqn:Ep. - reflexivity. - destruct n' as [|n'']; simpl. + reflexivity. + replace (n'' - 0) with n'' by lia. reflexivity. Qed.
Lemma make_tape'_cons_r l2 l1 o h r1:
(make_tape' l2 l1 o nil (app_halftape (h::nil) r1)) =
(make_tape' l2 l1 o (h::nil) r1).
Proof. unfold make_tape'. f_equal. cbn. rewrite app_halftape_nil. reflexivity. Qed.
Lemma make_tape'_cons_r l2 l1 o h r1:
(make_tape' l2 l1 o nil (app_halftape (h::nil) r1)) =
(make_tape' l2 l1 o (h::nil) r1).
Proof. unfold make_tape', make_tape. extensionality x. destruct x; try reflexivity. simpl. unfold app_halftape. simpl. destruct (Pos.to_nat p) as [|n'] eqn:Ep. - reflexivity. - destruct n' as [|n'']; simpl. + reflexivity. + replace (n'' - 0) with n'' by lia. reflexivity. Qed.
Lemma make_tape'_lmr (t:Z->Σ): t = make_tape' (half_tape t (-1) Dneg) nil (t Z0) nil (half_tape t 1 Dpos).
Proof. apply (make_tape'_spec t 0 0). Qed.
Lemma make_tape'_lmr (t:Z->Σ): t = make_tape' (half_tape t (-1) Dneg) nil (t Z0) nil (half_tape t 1 Dpos).
Proof. apply (make_tape'_spec t 0 0). Qed.
Lemma make_tape'_mov_l l1' l1 m1 r1 r1' σ:
mov Σ (make_tape' l1' (σ :: l1) m1 r1 r1') Dneg = make_tape' l1' l1 σ (m1 :: r1) r1'.
Proof. fext. unfold mov,make_tape',make_tape,Dir_to_Z. assert (H:(x<0\/x=0\/x=1\/x>1)%Z) by lia. destruct H as [H|[H|[H|H]]]. - destruct x; try lia. destruct (Z.neg p + -1)%Z eqn:E; try lia. assert (H0:(Nat.pred (Pos.to_nat p0)) = S (Nat.pred (Pos.to_nat p))) by lia. rewrite H0. apply app_halftape_S. - subst. reflexivity. - subst. reflexivity. - destruct x; try lia. destruct (Z.pos p + -1)%Z eqn:E; try lia. symmetry. assert (H0:(Nat.pred (Pos.to_nat p)) = S (Nat.pred (Pos.to_nat p0))) by lia. rewrite H0. apply app_halftape_S. Qed.
Lemma make_tape'_mov_l l1' l1 m1 r1 r1' σ:
mov Σ (make_tape' l1' (σ :: l1) m1 r1 r1') Dneg = make_tape' l1' l1 σ (m1 :: r1) r1'.
Proof. extensionality x. unfold mov, make_tape', make_tape, Dir_to_Z. destruct x as [|p|p]. - simpl. unfold app_halftape. simpl. reflexivity. - (* Zpos p: (Zpos p + (-1)) cases *) destruct (Z.pos p + -1)%Z as [|q|q] eqn:Epm1. + (* = Z0, so p = 1 *) simpl. unfold app_halftape. simpl. assert (p = 1%positive) by lia. subst. simpl. reflexivity. + (* = Zpos q *) simpl. assert (Hpq: Pos.to_nat p = S (Pos.to_nat q)) by lia. rewrite Hpq. simpl. destruct (Pos.to_nat q) as [|k] eqn:Ek. * exfalso. pose proof (Pos2Nat.is_pos q). lia. * simpl. reflexivity. + (* = Zneg q, impossible since p >= 1 *) exfalso. lia. - (* Zneg p: (Zneg p + (-1)) = Zneg (p+1) *) replace (Z.neg p + -1)%Z with (Z.neg (Pos.succ p)) by lia. simpl. rewrite Pos2Nat.inj_succ. destruct (Pos.to_nat p) as [|k] eqn:Ek. + exfalso. pose proof (Pos2Nat.is_pos p). lia. + simpl. reflexivity. Qed.
Lemma make_tape'_mov_r l1' l1 m1 r1 r1' σ:
mov Σ (make_tape' l1' l1 m1 (σ :: r1) r1') Dpos = make_tape' l1' (m1 :: l1) σ r1 r1'.
Proof. rewrite <-make_tape'_rev. symmetry. rewrite <-make_tape'_rev. rewrite mov_tape_rev. cbn. rewrite make_tape'_mov_l. reflexivity. Qed.
Lemma make_tape'_mov_r l1' l1 m1 r1 r1' σ:
mov Σ (make_tape' l1' l1 m1 (σ :: r1) r1') Dpos = make_tape' l1' (m1 :: l1) σ r1 r1'.
Proof. extensionality x. unfold mov, make_tape', make_tape, Dir_to_Z. destruct x as [|p|p]. - simpl. unfold app_halftape. simpl. reflexivity. - replace (Z.pos p + 1)%Z with (Z.pos (Pos.succ p)) by lia. simpl. rewrite Pos2Nat.inj_succ. destruct (Pos.to_nat p) as [|k] eqn:Ek. + exfalso. pose proof (Pos2Nat.is_pos p). lia. + simpl. reflexivity. - (* Zneg p: (Zneg p + 1) cases *) destruct (Z.neg p + 1)%Z as [|q|q] eqn:Epm1. + (* = Z0, so p = 1 *) simpl. unfold app_halftape. simpl. assert (p = 1%positive) by lia. subst. simpl. reflexivity. + (* impossible: Zneg p + 1 = Zpos q means p would be negative *) exfalso. lia. + (* = Zneg q *) simpl. assert (Hpq: Pos.to_nat p = S (Pos.to_nat q)) by lia. rewrite Hpq. simpl. destruct (Pos.to_nat q) as [|k] eqn:Ek. * exfalso. pose proof (Pos2Nat.is_pos q). lia. * simpl. reflexivity. Qed.
Lemma make_tape'_rev l1' l1 m1 r1 r1':
tape_rev (make_tape' l1' l1 m1 r1 r1') = (make_tape' r1' r1 m1 l1 l1').
Proof. fext. unfold tape_rev. destruct x; cbn; reflexivity. Qed.
Lemma make_tape'_rev l1' l1 m1 r1 r1':
tape_rev (make_tape' l1' l1 m1 r1 r1') = (make_tape' r1' r1 m1 l1 l1').
Proof. unfold tape_rev, make_tape', make_tape, app_halftape. extensionality x. destruct x; simpl; reflexivity. Qed.
Lemma make_tape'_spec (t:Z->Σ) nl nr: t = make_tape' (half_tape t (-Z.of_nat(1+nl))%Z Dneg) (tape_seg _ t ((-1)%Z) Dneg nl) (t Z0) (tape_seg _ t (1%Z) Dpos nr) (half_tape t (Z.of_nat (1+nr)) Dpos).
Proof. fext. cbn. destruct x. - cbn. reflexivity. - cbn. unfold app_halftape. remember (Nat.pred (Pos.to_nat p)) as p0. destruct (tape_seg_spec Σ t 1 Dpos nr) as [H0 H1]. assert (H:p0<nr\/nr<=p0) by lia. destruct H as [H|H]. + rewrite H0; auto 1. f_equal. unfold Dir_to_Z. subst. lia. + pose proof H as H2. rewrite <-H1 in H. rewrite <-nth_error_None in H. rewrite H. unfold half_tape. f_equal. unfold addmul,Dir_to_Z. lia. - cbn. unfold app_halftape. remember (Nat.pred (Pos.to_nat p)) as p0. destruct (tape_seg_spec Σ t (-1) Dneg nl) as [H0 H1]. assert (H:p0<nl\/nl<=p0) by lia. destruct H as [H|H]. + rewrite H0; auto 1. f_equal. unfold Dir_to_Z. subst. lia. + pose proof H as H2. rewrite <-H1 in H. rewrite <-nth_error_None in H. rewrite H. unfold half_tape. f_equal. unfold addmul,Dir_to_Z. lia. Qed.
Lemma make_tape'_spec (t:Z->Σ) nl nr: t = make_tape' (half_tape t (-Z.of_nat(1+nl))%Z Dneg) (tape_seg _ t ((-1)%Z) Dneg nl) (t Z0) (tape_seg _ t (1%Z) Dpos nr) (half_tape t (Z.of_nat (1+nr)) Dpos).
Proof. extensionality x. unfold make_tape', make_tape, app_halftape, half_tape, addmul, Dir_to_Z. destruct x as [|p|p]. - reflexivity. - set (n:=Nat.pred (Pos.to_nat p)). destruct (Nat.lt_ge_cases n nr) as [Hlt|Hge]. + pose proof (proj1 (tape_seg_spec Σ t 1 Dpos nr) n Hlt) as Hnth. rewrite Hnth. replace (Z.pos p) with (1 + 1 * Z.of_nat n)%Z by (unfold n; lia). reflexivity. + assert (Hnone: nth_error (tape_seg Σ t 1 Dpos nr) n = None). { apply nth_error_None. rewrite (proj2 (tape_seg_spec Σ t 1 Dpos nr)). lia. } rewrite Hnone. replace (Z.of_nat (1 + nr) + 1 * Z.of_nat (n - length (tape_seg Σ t 1 Dpos nr)))%Z with (Z.pos p) by (rewrite (proj2 (tape_seg_spec Σ t 1 Dpos nr)); unfold n; lia). reflexivity. - set (n:=Nat.pred (Pos.to_nat p)). destruct (Nat.lt_ge_cases n nl) as [Hlt|Hge]. + pose proof (proj1 (tape_seg_spec Σ t (-1) Dneg nl) n Hlt) as Hnth. rewrite Hnth. replace (Z.neg p) with (-1 + -1 * Z.of_nat n)%Z by (unfold n; lia). reflexivity. + assert (Hnone: nth_error (tape_seg Σ t (-1) Dneg nl) n = None). { apply nth_error_None. rewrite (proj2 (tape_seg_spec Σ t (-1) Dneg nl)). lia. } rewrite Hnone. replace (- Z.of_nat (1 + nl) + -1 * Z.of_nat (n - length (tape_seg Σ t (-1) Dneg nl)))%Z with (Z.neg p) by (rewrite (proj2 (tape_seg_spec Σ t (-1) Dneg nl)); unfold n; lia). reflexivity. Qed.
Lemma make_tape'_split_l l2 l1 l0 m0 r0 r1:
make_tape' (app_halftape l2 l1) l0 m0 r0 r1 =
make_tape' l1 (l0++l2) m0 r0 r1.
Proof. unfold make_tape'. f_equal. apply app_halftape_assoc. Qed.
Lemma make_tape'_split_l l2 l1 l0 m0 r0 r1:
make_tape' (app_halftape l2 l1) l0 m0 r0 r1 =
make_tape' l1 (l0++l2) m0 r0 r1.
Proof. unfold make_tape'. f_equal. rewrite app_halftape_assoc. reflexivity. Qed.
Lemma make_tape'_split_r r2 l1 l0 m0 r0 r1:
make_tape' l1 l0 m0 r0 (app_halftape r2 r1) =
make_tape' l1 l0 m0 (r0++r2) r1.
Proof. unfold make_tape'. f_equal. apply app_halftape_assoc. Qed.
Lemma make_tape'_split_r r2 l1 l0 m0 r0 r1:
make_tape' l1 l0 m0 r0 (app_halftape r2 r1) =
make_tape' l1 l0 m0 (r0++r2) r1.
Proof. unfold make_tape'. f_equal. rewrite app_halftape_assoc. reflexivity. Qed.
Lemma make_tape'_upd l1' l1 m1 r1 r1' m1':
upd Σ (make_tape' l1' l1 m1 r1 r1') m1' = (make_tape' l1' l1 m1' r1 r1').
Proof. fext. unfold upd. destruct x; cbn; reflexivity. Qed.
Lemma make_tape'_upd l1' l1 m1 r1 r1' m1':
upd Σ (make_tape' l1' l1 m1 r1 r1') m1' = (make_tape' l1' l1 m1' r1 r1').
Proof. unfold make_tape', make_tape, upd. extensionality x. destruct x; simpl; reflexivity. Qed.
Lemma make_tape_eq {a b c a' b' c'}: make_tape a b c = make_tape a' b' c' -> (a=a'/\b=b'/\c=c').
Proof. intros. repeat split. - fext. epose proof (fext_inv (Zneg (Pos.of_succ_nat x)) H) as H0. cbn in H0. rewrite SuccNat2Pos.pred_id in H0. apply H0. - epose proof (fext_inv Z0 H) as H0. cbn in H0. apply H0. - fext. epose proof (fext_inv (Zpos (Pos.of_succ_nat x)) H) as H0. cbn in H0. rewrite SuccNat2Pos.pred_id in H0. apply H0. Qed.
Lemma make_tape_eq {a b c a' b' c'}: make_tape a b c = make_tape a' b' c' -> (a=a'/\b=b'/\c=c').
Proof. intro H. assert (Hb: b = b'). { pose proof (f_equal (fun f => f Z0) H) as H0. simpl in H0. exact H0. } split; [|split; [exact Hb|]]. - extensionality n. pose proof (f_equal (fun f => f (Zneg (Pos.of_succ_nat n))) H) as Hn. simpl in Hn. rewrite SuccNat2Pos.pred_id in Hn. exact Hn. - extensionality n. pose proof (f_equal (fun f => f (Zpos (Pos.of_succ_nat n))) H) as Hn. simpl in Hn. rewrite SuccNat2Pos.pred_id in Hn. exact Hn. Qed.
Lemma map_inj{T1 T2}(f:T1->T2): is_inj f -> is_inj (map f).
Proof. intros H x1 x2 H0. gd x2. induction x1 as [|h1 t1]; destruct x2 as [|h2 t2]; cbn; intros; cg. invst H0. rewrite (IHt1 _ H3). f_equal. apply H,H2. Qed.
Lemma map_inj{T1 T2}(f:T1->T2): is_inj f -> is_inj (map f).
Proof. unfold is_inj. intros Hf. induction a; destruct b; simpl; intros; try congruence. f_equal. + apply Hf. congruence. + apply IHa. congruence. Qed.
Lemma mov_tape_rev t d:
mov Σ (tape_rev t) d = tape_rev (mov Σ t (Dir_rev d)).
Proof. fext. unfold mov,tape_rev. f_equal. destruct d; cbn; lia. Qed.
Lemma mov_tape_rev t d:
mov Σ (tape_rev t) d = tape_rev (mov Σ t (Dir_rev d)).
Proof. unfold mov, tape_rev, Dir_to_Z, Dir_rev. extensionality x. destruct d; simpl; f_equal; lia. Qed.
Lemma mset_ins0_spec ms mw ms' flag: mset_WF ms -> mset_ins0 ms mw = (ms',flag) -> (mset_WF ms' /\ (flag=true -> (ms'=ms /\ mset_in ms mw))).
Proof. apply set_ins_spec. unfold is_inj. intros. apply MidWord_enc_inj,H. Qed.
Lemma mset_ins0_spec ms mw ms' flag: mset_WF ms -> mset_ins0 ms mw = (ms',flag) -> (mset_WF ms' /\ (flag=true -> (ms'=ms /\ mset_in ms mw))).
Proof. intros Hms Heq. exact (set_ins_spec MidWord_enc MidWord_enc_inj ms mw ms' flag Hms Heq). Qed.
Lemma mset_ins_spec q ms flag f ls q' ms' flag2: mset_WF ms -> mset_ins q ms flag f ls = (q',ms',flag2) -> (mset_WF ms' /\ (flag2=true -> (flag=true /\ q'=q /\ ms'=ms /\ (forall x2, In x2 ls -> mset_in ms (f x2))))).
Proof. gd flag2. gd ms'. gd q'. gd flag. gd ms. gd q. induction ls; intros. - cbn in H0. invst H0. split. 1: assumption. intro H1. repeat split; auto 1. intros x2 H2. destruct H2. - cbn in H0. destruct (mset_ins0 ms (f a)) as [ms'0 flag'] eqn:E. destruct (mset_ins0_spec _ _ _ _ H E) as [H1a H1b]. specialize (IHls _ _ _ _ _ _ H1a H0). destruct IHls as [H2a H2b]. split. 1: assumption. intro; subst. specialize (H2b eq_refl). destruct H2b as [H2b [H2c [H2d H2e]]]. rewrite Bool.andb_true_iff in H2b. destruct H2b. subst. specialize (H1b eq_refl). destruct H1b as [H1b H1c]. subst. repeat split; cg. intros x2 H3. cbn in H3. destruct H3 as [H3|H3]; subst; auto. Qed.
Lemma mset_ins_spec q ms flag f ls q' ms' flag2: mset_WF ms -> mset_ins q ms flag f ls = (q',ms',flag2) -> (mset_WF ms' /\ (flag2=true -> (flag=true /\ q'=q /\ ms'=ms /\ (forall x2, In x2 ls -> mset_in ms (f x2))))).
Proof. revert q ms flag. induction ls as [|h t IH]; intros q ms flag Hms Heq. - simpl in Heq. inversion Heq. subst. split. + exact Hms. + intro Htrue. repeat split; try assumption. intros x2 Hin. destruct Hin. - simpl in Heq. destruct (mset_ins0 ms (f h)) as [ms1 flag1] eqn:Ew. pose proof (mset_ins0_spec ms (f h) ms1 flag1 Hms Ew) as [Hms1 Hflag1]. set (q1 := if flag1 then q else (f h)::q) in Heq. specialize (IH q1 ms1 (andb flag flag1) Hms1 Heq). destruct IH as [Hms' IHimp]. split. + exact Hms'. + intro Htrue. destruct (IHimp Htrue) as [Handb [Hq1eq [Hms'eq Ht]]]. apply Bool.andb_true_iff in Handb. destruct Handb as [Hflag Hflag1t]. destruct (Hflag1 Hflag1t) as [Hms1ms HiB]. split; [exact Hflag|]. split. * unfold q1 in Hq1eq. rewrite Hflag1t in Hq1eq. exact Hq1eq. * split; [rewrite Hms'eq; exact Hms1ms|]. intros x2 Hin. destruct Hin as [Hxh | Hxt]. -- subst x2. exact HiB. -- rewrite <- Hms1ms. apply Ht. exact Hxt. Qed.
Lemma nat_eqb_N_spec n m : nat_eqb_N n m = true -> n = N.to_nat m.
Proof. gd m. induction n; intros. - cbn in H. destruct m0; cbn; cg. - destruct m0. + cbn in H. cg. + cbn in H. specialize (IHn (Pos.pred_N p) H). lia. Qed.
Lemma nat_eqb_N_spec n m : nat_eqb_N n m = true -> n = N.to_nat m.
Proof. revert m. induction n as [|n' IH]; intros m H. - simpl in H. destruct m; [reflexivity|discriminate]. - simpl in H. destruct m as [|p]; [discriminate|]. apply IH in H. rewrite H. rewrite N.pred_sub. simpl. destruct p; simpl; lia. Qed.
Lemma nat_eqb_spec n1 n2 : if Nat.eqb n1 n2 then n1=n2 else n1<>n2.
Proof. destruct (Nat.eqb_spec n1 n2); cg. Qed.
Lemma nat_eqb_spec n1 n2 : if Nat.eqb n1 n2 then n1=n2 else n1<>n2.
Proof. destruct (Nat.eqb_spec n1 n2); assumption. Qed.
Lemma nat_lt_spec x1 x2:
if x1 <? x2 then x1<x2 else x2<=x1.
Proof. destruct (Nat.ltb_spec x1 x2); auto 1. Qed.
Lemma nat_lt_spec x1 x2:
if x1 <? x2 then x1<x2 else x2<=x1.
Proof. destruct (Nat.ltb_spec x1 x2); lia. Qed.
Lemma nth_error_skipn {T} {h:T} {ls0 ls1 n}: h :: ls1 = skipn n ls0 -> nth_error ls0 n = Some h.
Proof. gd ls1. gd ls0. gd h. induction n; intros. - cbn. cbn in H. rewrite <-H. reflexivity. - cbn. destruct ls0 as [|h1 ls0]. 1: invst H. cbn in H. eapply IHn; eauto 1. Qed.
Lemma nth_error_skipn {T} {h:T} {ls0 ls1 n}: h :: ls1 = skipn n ls0 -> nth_error ls0 n = Some h.
Proof. revert n. induction ls0 as [|a ls0' IH]; intros n H. - destruct n; simpl in H; discriminate. - destruct n as [|n']. + simpl in *. inversion H. reflexivity. + simpl in *. exact (IH _ H). Qed.
Lemma option_Trans_rev_rev: forall t, option_Trans_rev (option_Trans_rev t) = t.
Proof. intros. destruct t. 2: reflexivity. cbn. f_equal. apply Trans_rev_rev. Qed.
Lemma option_Trans_rev_rev: forall t, option_Trans_rev (option_Trans_rev t) = t.
Proof. intro t. destruct t as [x|]; simpl. - rewrite Trans_rev_rev. reflexivity. - reflexivity. Qed.
Lemma option_Trans_swap_swap: forall s, option_Trans_swap (option_Trans_swap s) = s.
Proof. intros. destruct s; auto 1. unfold option_Trans_swap. f_equal. apply Trans_swap_swap. Qed.
Lemma option_Trans_swap_swap: forall s, option_Trans_swap (option_Trans_swap s) = s.
Proof. intro s. destruct s as [x|]; simpl. - rewrite Trans_swap_swap. reflexivity. - reflexivity. Qed.
Lemma orb_shortcut_spec(a b:bool): (a|||b) = (a||b)%bool.
Proof. reflexivity. Qed.
Lemma orb_shortcut_spec(a b:bool): (a|||b) = (a||b)%bool.
Proof. destruct a, b; reflexivity. Qed.
Lemma pop_back'__push_back{T} (h:T) t x2:
pop_back' h (t ++ x2 :: nil) = (h::t,x2).
Proof. gd h. induction t; intros; cbn; cg. rewrite IHt. reflexivity. Qed.
Lemma pop_back'__push_back{T} (h:T) t x2:
pop_back' h (t ++ x2 :: nil) = (h::t,x2).
Proof. revert h. induction t as [|a t' IH]; intros h. - simpl. reflexivity. - simpl. rewrite IH. reflexivity. Qed.
Lemma pop_back__nth_error{T} (h:T) t: forall n:nat, n<length t -> nth_error (pop_back h t) n = nth_error (h::t) n.
Proof. gd h. induction t; intros. - cbn in H. lia. - cbn. destruct n. 1: reflexivity. cbn. apply IHt. cbn in H. lia. Qed.
Lemma pop_back__nth_error{T} (h:T) t: forall n:nat, n<length t -> nth_error (pop_back h t) n = nth_error (h::t) n.
Proof. revert h. induction t as [|x t' IH]; intros h n Hn. - simpl in Hn. lia. - simpl. destruct n as [|n']. + simpl. reflexivity. + simpl. rewrite IH. * simpl. reflexivity. * simpl in Hn. lia. Qed.
Lemma pop_back_len{T} (h:T) t:
length (pop_back h t) = length t.
Proof. gd h. induction t; intros; cbn. - reflexivity. - f_equal; apply IHt. Qed.
Lemma pop_back_len{T} (h:T) t:
length (pop_back h t) = length t.
Proof. revert h. induction t as [|x t' IH]; intros h. - simpl. reflexivity. - simpl. rewrite IH. reflexivity. Qed.
Lemma pop_spec wl: match pop wl with | None => True | Some (w,ls) => forall f, RepWL_match wl f -> ((exists wl0 f1, In wl0 ls /\ RepWL_match wl0 f1 /\ f = app_halftape w f1)) end.
Proof. unfold pop. destruct wl as [|v wl0]. - intros. exists nil. exists half_tape_all0. cbn. repeat split. + tauto. + ctor. + invst H. apply app_half_tape_all0. - destruct v as [w0 mc isc]; cbn. destruct mc as [|mc]. 1: auto 1. intros. invst H. invst H2. + eexists. exists (app_halftape w2 ft). split. 1: left; reflexivity. split. * destruct mc as [|mc]. -- invst H6. rewrite app_halftape_nil. apply H4. -- ector; eauto 1. * rewrite app_halftape_assoc; reflexivity. + destruct n0 as [|n0]. 1: lia. invst H7. assert (E:mc = n0 \/ S mc <= n0) by lia. destruct E as [E|E]. -- subst n0. eexists. exists (app_halftape w2 ft). split. 1: left; reflexivity. split. * destruct mc as [|mc]. ++ invst H5. rewrite app_halftape_nil. apply H4. ++ ector; eauto 1. * rewrite app_halftape_assoc; reflexivity. -- eexists. exists (app_halftape w2 ft). split. 1: right; left; reflexivity. split. * ector; eauto 1. ector; eauto 1. * rewrite app_halftape_assoc; reflexivity. Qed.
Lemma pop_spec wl: match pop wl with | None => True | Some (w,ls) => forall f, RepWL_match wl f -> ((exists wl0 f1, In wl0 ls /\ RepWL_match wl0 f1 /\ f = app_halftape w f1)) end.
Proof. destruct wl as [|v wl0]; simpl. - intros f H. inversion H; subst. exists nil, half_tape_all0. split; [left; reflexivity|split; [constructor|apply app_half_tape_all0]]. - destruct (min_cnt v) as [|mc0] eqn:Emc; [exact I|]. intros f H. remember (v::wl0) as wl eqn:Ewl. destruct H as [|h t fh ft Hrw Hrl]; [discriminate|]. injection Ewl as Eh Et. subst h t. destruct v as [wv mc ic]; simpl in *; subst mc. destruct ic. + (* ic = true *) apply strip_one in Hrw. destruct Hrw as [tail [Hfh Htail]]. subst fh. destruct mc0 as [|mc0']. * apply nil_match in Htail. subst tail. exists wl0, ft. split; [left; reflexivity|split; [exact Hrl|]]. rewrite <- app_halftape_assoc. rewrite app_halftape_nil. reflexivity. * exists ({| w := wv; min_cnt := S mc0'; is_const := true |} :: wl0), (app_halftape tail ft). split; [left; reflexivity|split]. -- apply RepWL_match_S; [exact Htail|exact Hrl]. -- symmetry. apply app_halftape_assoc. + (* ic = false *) remember {|w:=wv; min_cnt:=S mc0; is_const:=false|} as v eqn:Ev. destruct Hrw; inversion Ev; subst; clear Ev. rename n0 into mc', w1 into fh0. assert (Hmc': mc' >= 1) by lia. destruct mc' as [|mc'']; [lia|]. apply strip_one in Hrw. destruct Hrw as [tail [Hfh Htail]]. subst fh0. destruct (le_lt_dec (S mc0) mc''). * exists ({| w := wv; min_cnt := S mc0; is_const := false |} :: wl0), (app_halftape tail ft). split. -- right. destruct mc0; simpl; left; reflexivity. -- split. ++ apply RepWL_match_S; [|exact Hrl]. apply (RepW_match_S1 wv tail (S mc0) mc''); [lia|exact Htail]. ++ symmetry. apply app_halftape_assoc. * assert (mc'' = mc0) by lia. subst mc''. destruct mc0 as [|mc0']. -- apply nil_match in Htail. subst tail. exists wl0, ft. split; [left; reflexivity|split; [exact Hrl|]]. rewrite <- app_halftape_assoc. rewrite app_halftape_nil. reflexivity. -- exists ({| w := wv; min_cnt := S mc0'; is_const := true |} :: wl0), (app_halftape tail ft). split; [left; reflexivity|split]. ++ apply RepWL_match_S; [exact Htail|exact Hrl]. ++ symmetry. apply app_halftape_assoc. Qed.
Lemma push_spec wl w0: forall f, RepWL_match wl f -> RepWL_match (push wl w0) (app_halftape w0 f).
Proof. intros. unfold push. destruct wl as [|v0 wl0]. - destruct (all0 w0) eqn:E. + invst H. rewrite (all0_spec _ E). rewrite <-app_half_tape_all0. ctor. + invst H. ector; eauto 1. rewrite <-app_nil_r. ctor; ctor. - destruct v0 as [w1 mc isc]; unfold w,min_cnt,is_const. Word_eq_dec w1 w0. + subst. nat_lt_dec (S mc) min_nonconst_len. * invst H. rewrite app_halftape_assoc. ctor; auto 1. destruct isc. -- ctor; auto 1. -- invst H3. ector. 2: ector; eauto 1. lia. * invst H. rewrite app_halftape_assoc. ctor; auto 1. destruct isc. -- ector. 2: ector; eauto 1. auto 1. -- invst H3. ector. 2: ector; eauto 1. lia. + ctor; auto 1. rewrite <-app_nil_r. ctor; ctor. Qed.
Lemma push_spec wl w0: forall f, RepWL_match wl f -> RepWL_match (push wl w0) (app_halftape w0 f).
Proof. intros f H. destruct wl as [|[wv mc ic] wl0]. - simpl. inversion H; subst. destruct (all0 w0) eqn:Eojx. + apply all0_spec in Eojx. rewrite Eojx. rewrite <- app_half_tape_all0. constructor. + replace (app_halftape w0 half_tape_all0) with (app_halftape (w0 ++ nil) half_tape_all0) by (rewrite app_nil_r; reflexivity). apply RepWL_match_S; [|constructor]. apply RepW_match_S0. apply RepW_match_O. - remember ({|w:=wv; min_cnt:=mc; is_const:=ic|}::wl0) as wl eqn:Ewl. destruct H as [|h t fh ft Hrw Hrl]; [discriminate|]. injection Ewl as Eh Et. subst h t. change (push ({| w := wv; min_cnt := mc; is_const := ic |} :: wl0) w0) with (if Word_eqb wv w0 then (if Nat.ltb (S mc) min_nonconst_len then {| w:=w0; min_cnt:=S mc; is_const:=ic |} else {| w:=w0; min_cnt:=min_nonconst_len; is_const:=false |})::wl0 else {| w:=w0; min_cnt:=1; is_const:=true |}::({| w := wv; min_cnt := mc; is_const := ic |} :: wl0)). pose proof (Word_eqb_spec wv w0) as Hwcmp. destruct (Word_eqb wv w0) eqn:Ecmp. + subst. rewrite app_halftape_assoc. destruct (Nat.ltb_spec (S mc) min_nonconst_len). * exact (RepWL_match_S _ _ (w0++fh) ft (RepW_prepend w0 mc ic fh Hrw) Hrl). * exact (RepWL_match_S _ _ (w0++fh) ft (RepW_weaken w0 (S mc) min_nonconst_len ic (w0++fh) (RepW_prepend w0 mc ic fh Hrw) (ltac:(lia))) Hrl). + replace (app_halftape w0 (app_halftape fh ft)) with (app_halftape (w0 ++ nil) (app_halftape fh ft)) by (rewrite app_nil_r; reflexivity). apply RepWL_match_S; [|apply RepWL_match_S; [exact Hrw|exact Hrl]]. apply RepW_match_S0. apply RepW_match_O. Qed.
Lemma q_200_WF:
SearchQueue_WF (N.to_nat BB) q_200 root.
Proof. rewrite q_200_spec. generalize 200. intro n. induction n. - replace (Nat.iter 0 q_suc q_0) with q_0 by reflexivity. unfold q_0,q0. apply root_q_upd1_simplified_WF. - replace (Nat.iter (S n) q_suc q_0) with (q_suc (Nat.iter n q_suc q_0)) by (apply iter_S; reflexivity). remember (Nat.iter n q_suc q_0) as q. clear Heqq. unfold q_suc. apply SearchQueue_upds_spec. + apply IHn. + apply decider_all_spec. Qed.
Lemma q_200_WF:
SearchQueue_WF (N.to_nat BB) q_200 root.
Proof. rewrite q_200_spec. apply q_200_WF_steps. unfold q_0, q0. exact root_q_upd1_simplified_WF. Qed.
Lemma q_200_empty:
q_200 = (nil,nil).
Proof. reflexivity. Qed.
Lemma q_200_empty:
q_200 = (nil,nil).
Proof. vm_cast_no_check (eq_refl (nil(A:=TNF_Node),nil(A:=TNF_Node)):q_200 = (nil,nil)). Qed.
Lemma q_200_spec: q_200 = Nat.iter 200 q_suc q_0.
Proof. q_rw q_200 q_200_def. q_rw q_199 q_199_def. q_rw q_198 q_198_def. q_rw q_197 q_197_def. q_rw q_196 q_196_def. q_rw q_195 q_195_def. q_rw q_194 q_194_def. q_rw q_193 q_193_def. q_rw q_192 q_192_def. q_rw q_191 q_191_def. q_rw q_190 q_190_def. q_rw q_189 q_189_def. q_rw q_188 q_188_def. q_rw q_187 q_187_def. q_rw q_186 q_186_def. q_rw q_185 q_185_def. q_rw q_184 q_184_def. q_rw q_183 q_183_def. q_rw q_182 q_182_def. q_rw q_181 q_181_def. q_rw q_180 q_180_def. q_rw q_179 q_179_def. q_rw q_178 q_178_def. q_rw q_177 q_177_def. q_rw q_176 q_176_def. q_rw q_175 q_175_def. q_rw q_174 q_174_def. q_rw q_173 q_173_def. q_rw q_172 q_172_def. q_rw q_171 q_171_def. q_rw q_170 q_170_def. q_rw q_169 q_169_def. q_rw q_168 q_168_def. q_rw q_167 q_167_def. q_rw q_166 q_166_def. q_rw q_165 q_165_def. q_rw q_164 q_164_def. q_rw q_163 q_163_def. q_rw q_162 q_162_def. q_rw q_161 q_161_def. q_rw q_160 q_160_def. q_rw q_159 q_159_def. q_rw q_158 q_158_def. q_rw q_157 q_157_def. q_rw q_156 q_156_def. q_rw q_155 q_155_def. q_rw q_154 q_154_def. q_rw q_153 q_153_def. q_rw q_152 q_152_def. q_rw q_151 q_151_def. q_rw q_150 q_150_def. q_rw q_149 q_149_def. q_rw q_148 q_148_def. q_rw q_147 q_147_def. q_rw q_146 q_146_def. q_rw q_145 q_145_def. q_rw q_144 q_144_def. q_rw q_143 q_143_def. q_rw q_142 q_142_def. q_rw q_141 q_141_def. q_rw q_140 q_140_def. q_rw q_139 q_139_def. q_rw q_138 q_138_def. q_rw q_137 q_137_def. q_rw q_136 q_136_def. q_rw q_135 q_135_def. q_rw q_134 q_134_def. q_rw q_133 q_133_def. q_rw q_132 q_132_def. q_rw q_131 q_131_def. q_rw q_130 q_130_def. q_rw q_129 q_129_def. q_rw q_128 q_128_def. q_rw q_127 q_127_def. q_rw q_126 q_126_def. q_rw q_125 q_125_def. q_rw q_124 q_124_def. q_rw q_123 q_123_def. q_rw q_122 q_122_def. q_rw q_121 q_121_def. q_rw q_120 q_120_def. q_rw q_119 q_119_def. q_rw q_118 q_118_def. q_rw q_117 q_117_def. q_rw q_116 q_116_def. q_rw q_115 q_115_def. q_rw q_114 q_114_def. q_rw q_113 q_113_def. q_rw q_112 q_112_def. q_rw q_111 q_111_def. q_rw q_110 q_110_def. q_rw q_109 q_109_def. q_rw q_108 q_108_def. q_rw q_107 q_107_def. q_rw q_106 q_106_def. q_rw q_105 q_105_def. q_rw q_104 q_104_def. q_rw q_103 q_103_def. q_rw q_102 q_102_def. q_rw q_101 q_101_def. q_rw q_100 q_100_def. q_rw q_99 q_99_def. q_rw q_98 q_98_def. q_rw q_97 q_97_def. q_rw q_96 q_96_def. q_rw q_95 q_95_def. q_rw q_94 q_94_def. q_rw q_93 q_93_def. q_rw q_92 q_92_def. q_rw q_91 q_91_def. q_rw q_90 q_90_def. q_rw q_89 q_89_def. q_rw q_88 q_88_def. q_rw q_87 q_87_def. q_rw q_86 q_86_def. q_rw q_85 q_85_def. q_rw q_84 q_84_def. q_rw q_83 q_83_def. q_rw q_82 q_82_def. q_rw q_81 q_81_def. q_rw q_80 q_80_def. q_rw q_79 q_79_def. q_rw q_78 q_78_def. q_rw q_77 q_77_def. q_rw q_76 q_76_def. q_rw q_75 q_75_def. q_rw q_74 q_74_def. q_rw q_73 q_73_def. q_rw q_72 q_72_def. q_rw q_71 q_71_def. q_rw q_70 q_70_def. q_rw q_69 q_69_def. q_rw q_68 q_68_def. q_rw q_67 q_67_def. q_rw q_66 q_66_def. q_rw q_65 q_65_def. q_rw q_64 q_64_def. q_rw q_63 q_63_def. q_rw q_62 q_62_def. q_rw q_61 q_61_def. q_rw q_60 q_60_def. q_rw q_59 q_59_def. q_rw q_58 q_58_def. q_rw q_57 q_57_def. q_rw q_56 q_56_def. q_rw q_55 q_55_def. q_rw q_54 q_54_def. q_rw q_53 q_53_def. q_rw q_52 q_52_def. q_rw q_51 q_51_def. q_rw q_50 q_50_def. q_rw q_49 q_49_def. q_rw q_48 q_48_def. q_rw q_47 q_47_def. q_rw q_46 q_46_def. q_rw q_45 q_45_def. q_rw q_44 q_44_def. q_rw q_43 q_43_def. q_rw q_42 q_42_def. q_rw q_41 q_41_def. q_rw q_40 q_40_def. q_rw q_39 q_39_def. q_rw q_38 q_38_def. q_rw q_37 q_37_def. q_rw q_36 q_36_def. q_rw q_35 q_35_def. q_rw q_34 q_34_def. q_rw q_33 q_33_def. q_rw q_32 q_32_def. q_rw q_31 q_31_def. q_rw q_30 q_30_def. q_rw q_29 q_29_def. q_rw q_28 q_28_def. q_rw q_27 q_27_def. q_rw q_26 q_26_def. q_rw q_25 q_25_def. q_rw q_24 q_24_def. q_rw q_23 q_23_def. q_rw q_22 q_22_def. q_rw q_21 q_21_def. q_rw q_20 q_20_def. q_rw q_19 q_19_def. q_rw q_18 q_18_def. q_rw q_17 q_17_def. q_rw q_16 q_16_def. q_rw q_15 q_15_def. q_rw q_14 q_14_def. q_rw q_13 q_13_def. q_rw q_12 q_12_def. q_rw q_11 q_11_def. q_rw q_10 q_10_def. q_rw q_9 q_9_def. q_rw q_8 q_8_def. q_rw q_7 q_7_def. q_rw q_6 q_6_def. q_rw q_5 q_5_def. q_rw q_4 q_4_def. q_rw q_3 q_3_def. q_rw q_2 q_2_def. q_rw q_1 q_1_def. reflexivity. Time Qed.
Lemma q_200_spec: q_200 = Nat.iter 200 q_suc q_0.
Proof. q_rw q_200 q_200_def. q_rw q_199 q_199_def. q_rw q_198 q_198_def. q_rw q_197 q_197_def. q_rw q_196 q_196_def. q_rw q_195 q_195_def. q_rw q_194 q_194_def. q_rw q_193 q_193_def. q_rw q_192 q_192_def. q_rw q_191 q_191_def. q_rw q_190 q_190_def. q_rw q_189 q_189_def. q_rw q_188 q_188_def. q_rw q_187 q_187_def. q_rw q_186 q_186_def. q_rw q_185 q_185_def. q_rw q_184 q_184_def. q_rw q_183 q_183_def. q_rw q_182 q_182_def. q_rw q_181 q_181_def. q_rw q_180 q_180_def. q_rw q_179 q_179_def. q_rw q_178 q_178_def. q_rw q_177 q_177_def. q_rw q_176 q_176_def. q_rw q_175 q_175_def. q_rw q_174 q_174_def. q_rw q_173 q_173_def. q_rw q_172 q_172_def. q_rw q_171 q_171_def. q_rw q_170 q_170_def. q_rw q_169 q_169_def. q_rw q_168 q_168_def. q_rw q_167 q_167_def. q_rw q_166 q_166_def. q_rw q_165 q_165_def. q_rw q_164 q_164_def. q_rw q_163 q_163_def. q_rw q_162 q_162_def. q_rw q_161 q_161_def. q_rw q_160 q_160_def. q_rw q_159 q_159_def. q_rw q_158 q_158_def. q_rw q_157 q_157_def. q_rw q_156 q_156_def. q_rw q_155 q_155_def. q_rw q_154 q_154_def. q_rw q_153 q_153_def. q_rw q_152 q_152_def. q_rw q_151 q_151_def. q_rw q_150 q_150_def. q_rw q_149 q_149_def. q_rw q_148 q_148_def. q_rw q_147 q_147_def. q_rw q_146 q_146_def. q_rw q_145 q_145_def. q_rw q_144 q_144_def. q_rw q_143 q_143_def. q_rw q_142 q_142_def. q_rw q_141 q_141_def. q_rw q_140 q_140_def. q_rw q_139 q_139_def. q_rw q_138 q_138_def. q_rw q_137 q_137_def. q_rw q_136 q_136_def. q_rw q_135 q_135_def. q_rw q_134 q_134_def. q_rw q_133 q_133_def. q_rw q_132 q_132_def. q_rw q_131 q_131_def. q_rw q_130 q_130_def. q_rw q_129 q_129_def. q_rw q_128 q_128_def. q_rw q_127 q_127_def. q_rw q_126 q_126_def. q_rw q_125 q_125_def. q_rw q_124 q_124_def. q_rw q_123 q_123_def. q_rw q_122 q_122_def. q_rw q_121 q_121_def. q_rw q_120 q_120_def. q_rw q_119 q_119_def. q_rw q_118 q_118_def. q_rw q_117 q_117_def. q_rw q_116 q_116_def. q_rw q_115 q_115_def. q_rw q_114 q_114_def. q_rw q_113 q_113_def. q_rw q_112 q_112_def. q_rw q_111 q_111_def. q_rw q_110 q_110_def. q_rw q_109 q_109_def. q_rw q_108 q_108_def. q_rw q_107 q_107_def. q_rw q_106 q_106_def. q_rw q_105 q_105_def. q_rw q_104 q_104_def. q_rw q_103 q_103_def. q_rw q_102 q_102_def. q_rw q_101 q_101_def. q_rw q_100 q_100_def. q_rw q_99 q_99_def. q_rw q_98 q_98_def. q_rw q_97 q_97_def. q_rw q_96 q_96_def. q_rw q_95 q_95_def. q_rw q_94 q_94_def. q_rw q_93 q_93_def. q_rw q_92 q_92_def. q_rw q_91 q_91_def. q_rw q_90 q_90_def. q_rw q_89 q_89_def. q_rw q_88 q_88_def. q_rw q_87 q_87_def. q_rw q_86 q_86_def. q_rw q_85 q_85_def. q_rw q_84 q_84_def. q_rw q_83 q_83_def. q_rw q_82 q_82_def. q_rw q_81 q_81_def. q_rw q_80 q_80_def. q_rw q_79 q_79_def. q_rw q_78 q_78_def. q_rw q_77 q_77_def. q_rw q_76 q_76_def. q_rw q_75 q_75_def. q_rw q_74 q_74_def. q_rw q_73 q_73_def. q_rw q_72 q_72_def. q_rw q_71 q_71_def. q_rw q_70 q_70_def. q_rw q_69 q_69_def. q_rw q_68 q_68_def. q_rw q_67 q_67_def. q_rw q_66 q_66_def. q_rw q_65 q_65_def. q_rw q_64 q_64_def. q_rw q_63 q_63_def. q_rw q_62 q_62_def. q_rw q_61 q_61_def. q_rw q_60 q_60_def. q_rw q_59 q_59_def. q_rw q_58 q_58_def. q_rw q_57 q_57_def. q_rw q_56 q_56_def. q_rw q_55 q_55_def. q_rw q_54 q_54_def. q_rw q_53 q_53_def. q_rw q_52 q_52_def. q_rw q_51 q_51_def. q_rw q_50 q_50_def. q_rw q_49 q_49_def. q_rw q_48 q_48_def. q_rw q_47 q_47_def. q_rw q_46 q_46_def. q_rw q_45 q_45_def. q_rw q_44 q_44_def. q_rw q_43 q_43_def. q_rw q_42 q_42_def. q_rw q_41 q_41_def. q_rw q_40 q_40_def. q_rw q_39 q_39_def. q_rw q_38 q_38_def. q_rw q_37 q_37_def. q_rw q_36 q_36_def. q_rw q_35 q_35_def. q_rw q_34 q_34_def. q_rw q_33 q_33_def. q_rw q_32 q_32_def. q_rw q_31 q_31_def. q_rw q_30 q_30_def. q_rw q_29 q_29_def. q_rw q_28 q_28_def. q_rw q_27 q_27_def. q_rw q_26 q_26_def. q_rw q_25 q_25_def. q_rw q_24 q_24_def. q_rw q_23 q_23_def. q_rw q_22 q_22_def. q_rw q_21 q_21_def. q_rw q_20 q_20_def. q_rw q_19 q_19_def. q_rw q_18 q_18_def. q_rw q_17 q_17_def. q_rw q_16 q_16_def. q_rw q_15 q_15_def. q_rw q_14 q_14_def. q_rw q_13 q_13_def. q_rw q_12 q_12_def. q_rw q_11 q_11_def. q_rw q_10 q_10_def. q_rw q_9 q_9_def. q_rw q_8 q_8_def. q_rw q_7 q_7_def. q_rw q_6 q_6_def. q_rw q_5 q_5_def. q_rw q_4 q_4_def. q_rw q_3 q_3_def. q_rw q_2 q_2_def. q_rw q_1 q_1_def. reflexivity. Time Qed.
Lemma root_HTUB:
TNF_Node_HTUB (N.to_nat BB) root.
Proof. epose proof q_200_WF. unfold SearchQueue_WF in H. rewrite q_200_empty in H. apply H. cbn. intros. contradiction. Qed.
Lemma root_HTUB:
TNF_Node_HTUB (N.to_nat BB) root.
Proof. pose proof q_200_WF as H. rewrite q_200_empty in H. unfold SearchQueue_WF in H. destruct H as [_ H]. apply H. intros x Hx. simpl in Hx. destruct Hx. Qed.
Lemma root_WF: TNF_Node_WF root.
Proof. repeat split. 1: cbn; cg. unfold UnusedState_ptr. left. intros. rewrite UnusedState_TM0. destruct s0; unfold St_le; cbn; split; intro; cg; lia. Qed.
Lemma root_WF: TNF_Node_WF root.
Proof. unfold TNF_Node_WF, root. simpl. split; [|split]. - reflexivity. - unfold CountHaltTrans, TM0, St_list, Σ_list. simpl. congruence. - left. intros s0. unfold UnusedState, TM0. split. + intros [_ [_ Hneq]]. unfold St_le. destruct s0; simpl; try lia. exfalso. apply Hneq. reflexivity. + intros Hk. split; [|split]. * intros s1 i1. exact I. * intros i1. reflexivity. * unfold St_le in Hk. destruct s0; simpl in *; try lia; congruence. Qed.
Lemma root_q_WF:
SearchQueue_WF (N.to_nat BB) root_q root.
Proof. apply SearchQueue_init_spec,root_WF. Qed.
Lemma root_q_WF:
SearchQueue_WF (N.to_nat BB) root_q root.
Proof. apply SearchQueue_init_spec. exact root_WF. Qed.
Lemma root_q_upd1_WF:
SearchQueue_WF (N.to_nat BB) root_q_upd1 root.
Proof. apply SearchQueue_upd_spec. - apply root_q_WF. - apply decider2_WF. Qed.
Lemma root_q_upd1_WF:
SearchQueue_WF (N.to_nat BB) root_q_upd1 root.
Proof. unfold root_q_upd1. apply SearchQueue_upd_spec. - exact root_q_WF. - exact decider2_WF. Qed.
Lemma root_q_upd1_simplified_WF:
SearchQueue_WF (N.to_nat BB) root_q_upd1_simplified root.
Proof. pose proof (root_q_upd1_WF). cbn in H. destruct H as [Ha Hb]. cbn. split. - intros x H0. pose proof (Ha x). tauto. - intro H0. apply Hb. intros x H1. destruct H1 as [H1|[H1|[H1|[H1|[H1|[H1|[H1|[H1|H1]]]]]]]]; try (specialize (H0 x); tauto). 1,2,3,4: clear Ha; clear Hb; destruct x as [tm cnt ptr]; cbn; invst H1; rewrite TM_rev_upd'_TM0; eapply HaltTimeUpperBound_LE_rev_InitES. 1: eassert (H2:_) by (apply (H0 {| TNF_tm := TM_upd' (TM0) St0 Σ0 (Some {| nxt := St0; dir := Dpos; out := Σ0 |}); TNF_cnt := 7; TNF_ptr := St1 |}); tauto); apply H2. 1: eassert (H2:_) by (apply (H0 {| TNF_tm := TM_upd' (TM0) St0 Σ0 (Some {| nxt := St0; dir := Dpos; out := Σ1 |}); TNF_cnt := 7; TNF_ptr := St1 |}); tauto); apply H2. 1: eassert (H2:_) by (apply (H0 {| TNF_tm := TM_upd' (TM0) St0 Σ0 (Some {| nxt := St1; dir := Dpos; out := Σ0 |}); TNF_cnt := 7; TNF_ptr := St2 |}); tauto); apply H2. 1: eassert (H2:_) by (apply (H0 {| TNF_tm := TM_upd' (TM0) St0 Σ0 (Some {| nxt := St1; dir := Dpos; out := Σ1 |}); TNF_cnt := 7; TNF_ptr := St2 |}); tauto); apply H2. Qed.
Lemma root_q_upd1_simplified_WF:
SearchQueue_WF (N.to_nat BB) root_q_upd1_simplified root.
Proof. unfold root_q_upd1_simplified, SearchQueue_WF. pose proof root_q_upd1_WF as H. unfold SearchQueue_WF in H. assert (Hsnd: snd root_q_upd1 = @nil TNF_Node). { native_compute. reflexivity. } destruct root_q_upd1 as [q1 q2] eqn:Et. simpl in Hsnd. subst q2. simpl fst in *. rewrite !app_nil_r in *. destruct H as [Hwf Himp]. split. - intros x Hx. apply filter_In in Hx. destruct Hx as [Hx _]. exact (Hwf x Hx). - intros Hall. apply Himp. intros x Hx. destruct (first_trans_is_R x) eqn:Ekal. + exact (Hall x (proj2 (filter_In first_trans_is_R x q1) (conj Hx Ekal))). + assert (Hq1_eq: q1 = TNF_Node_expand root St0 Σ0). { change q1 with (fst (q1, @nil TNF_Node)). rewrite <- Et. native_compute. reflexivity. } rewrite Hq1_eq in Hx. unfold TNF_Node_expand in Hx. change (Nat.eqb (TNF_cnt root) 1) with false in Hx. simpl TNF_ptr in Hx. apply in_map_iff in Hx. destruct Hx as [tr [Hxeq Htr_filt]]. apply filter_In in Htr_filt. destruct Htr_filt as [Htr_SNh Htr_cfq]. subst x. destruct tr as [s_tr d_tr o_tr]. assert (Hdir: d_tr = Dneg). { destruct d_tr; [reflexivity|]. exfalso. revert Ekal. vm_compute. discriminate. } subst d_tr. unfold TNF_Node_HTUB, TNF_Node_upd, root. simpl. rewrite (TM_rev_upd'_TM0 s_tr o_tr). apply HaltTimeUpperBound_LE_rev_InitES. refine (Hall (TNF_Node_upd root St0 Σ0 {| nxt := s_tr; dir := Dpos; out := o_tr |}) _). apply filter_In. split. * rewrite Hq1_eq. unfold TNF_Node_expand. change (Nat.eqb (TNF_cnt root) 1) with false. simpl TNF_ptr. apply in_map. apply filter_In. split. -- exact (Trans_list_spec _). -- exact Htr_cfq. * unfold first_trans_is_R, TNF_Node_upd, root. rewrite TM_upd'_spec. unfold TM_upd, TM0. simpl. reflexivity. Qed.
Lemma s_def l0 r0 m0 s0:
s {| l:=l0; r:=r0; m:=m0; s:=s0 |} = s0.
Proof. reflexivity. Qed.
Lemma s_def l0 r0 m0 s0:
s {| l:=l0; r:=r0; m:=m0; s:=s0 |} = s0.
Proof. simpl. reflexivity. Qed.
Lemma set_in_dec {T0} (enc:T0->positive) s x: set_in enc s x \/ ~ set_in enc s x.
Proof. unfold set_in. destruct (PositiveMap.find (enc x) (snd s)) as [[]|]. - left. reflexivity. - right. cg. Qed.
Lemma set_in_dec {T0} (enc:T0->positive) s x: set_in enc s x \/ ~ set_in enc s x.
Proof. unfold set_in. destruct (PositiveMap.find (enc x) (snd s)). - left. destruct u. reflexivity. - right. discriminate. Qed.
Lemma set_ins_spec{T} enc (enc_inj: is_inj enc) s (x:T) s' flag: set_WF enc s -> set_ins enc s x = (s',flag) -> (set_WF enc s' /\ (flag=true -> (s'=s /\ set_in enc s x))).
Proof. unfold set_WF,set_ins,set_in. intros. destruct (PositiveMap.find (enc x) (snd s)) as [v|] eqn:E. - invst H0. split. 1: assumption. intros. destruct v. split; cg. - invst H0. clear H0. split; intros. 2: cg. cbn. rewrite (PositiveMapAdditionalFacts.gsspec). destruct (PositiveMap.E.eq_dec (enc x0) (enc x)) as [e|e]. + pose proof (enc_inj _ _ e); subst. split; tauto. + assert (x<>x0) by cg. split; intro. * right. rewrite <-H. apply H1. * rewrite <-H in H1. destruct H1 as [H1|H1]; cg. Qed.
Lemma set_ins_spec{T} enc (enc_inj: is_inj enc) s (x:T) s' flag: set_WF enc s -> set_ins enc s x = (s',flag) -> (set_WF enc s' /\ (flag=true -> (s'=s /\ set_in enc s x))).
Proof. intros Hinv Hstep. unfold set_ins in Hstep. destruct (PositiveMap.find (enc x) (snd s)) eqn:Efind. - injection Hstep as Hs' Hflag. subst. split; [exact Hinv|]. intro. split; [reflexivity|]. unfold set_in. destruct u. exact Efind. - injection Hstep as Hs' Hflag. subst. split; [|intro; discriminate]. intro y. unfold set_in. simpl. destruct (Pos.eq_dec (enc y) (enc x)) as [Heq|Hneq]. + split. * intro. left. symmetry. apply enc_inj. exact Heq. * intro. rewrite Heq. apply PositiveMap.gss. + rewrite PositiveMap.gso by exact Hneq. split. * intro Hf. right. apply Hinv. exact Hf. * intros [Hxy | Hin]. -- subst. exfalso. apply Hneq. reflexivity. -- apply Hinv. exact Hin. Qed.
Lemma set_ins_spec'{T}{T_enc:T->positive} {q st a q' st' flag}: is_inj T_enc -> set_ins T_enc (q, st) a = (q', st', flag) -> forall x, ((a = x) \/ set_in T_enc (q, st) x <-> set_in T_enc (q', st') x) /\ (((a = x) /\ ~ set_in T_enc (q, st) x \/ In x q) -> In x q').
Proof. intros. unfold set_ins in H0. cbn in H0. destruct (PositiveMap.find (T_enc a) st) eqn:E. - invst H0. assert (a=x -> set_in T_enc (q',st') x). { intro. subst a. unfold set_in. cbn. destruct u. apply E. } split. 1: tauto. tauto. - invst H0. clear H0. split. + unfold set_in. cbn. split; intro. * destruct H0 as [H0|H0]. -- subst a. apply PositiveMap.gss. -- assert (a<>x) by cg. rewrite PositiveMap.gso; auto 1. intro H2. apply H1. symmetry. apply H,H2. * rewrite PositiveMapAdditionalFacts.gsspec in H0. destruct (PositiveMap.E.eq_dec (T_enc x) (T_enc a)) eqn:E0. -- left. symmetry. apply H,e. -- tauto. + intros. destruct H0 as [[H0a H0b]|H0]. * subst a. cbn. tauto. * cbn. tauto. Qed.
Lemma set_ins_spec'{T}{T_enc:T->positive} {q st a q' st' flag}: is_inj T_enc -> set_ins T_enc (q, st) a = (q', st', flag) -> forall x, ((a = x) \/ set_in T_enc (q, st) x <-> set_in T_enc (q', st') x) /\ (((a = x) /\ ~ set_in T_enc (q, st) x \/ In x q) -> In x q').
Proof. intros Hinj Hstep x. unfold set_ins in Hstep. simpl fst in Hstep. simpl snd in Hstep. destruct (PositiveMap.find (T_enc a) st) eqn:Efind. - (* find = Some _ => (q',st') = (q,st), flag = true *) inversion Hstep. subst q' st' flag. split. + (* iff *) split. * intros [Heq | Hvji]. -- subst x. unfold set_in. simpl. destruct u. exact Efind. -- exact Hvji. * intros Hvji. right. exact Hvji. + (* In *) intros [[Heq Hnvji] | Hin]. * subst x. exfalso. apply Hnvji. unfold set_in. simpl. destruct u. exact Efind. * exact Hin. - (* find = None => q' = a::q, st' = add ... *) inversion Hstep. subst q' st' flag. split. + (* iff *) split. * intros [Heq | Hvji]. -- subst x. unfold set_in. simpl. rewrite PositiveMap.gss. reflexivity. -- unfold set_in in *. simpl in *. destruct (Pos.eq_dec (T_enc x) (T_enc a)) as [Heq|Hneq]. ++ rewrite Heq. rewrite PositiveMap.gss. reflexivity. ++ rewrite PositiveMap.gso by exact Hneq. exact Hvji. * intros Hvji. unfold set_in in Hvji. simpl in Hvji. destruct (Pos.eq_dec (T_enc x) (T_enc a)) as [Heq|Hneq]. -- left. apply Hinj. symmetry. exact Heq. -- right. unfold set_in. simpl. rewrite PositiveMap.gso in Hvji by exact Hneq. exact Hvji. + (* In *) intros [[Heq Hnvji] | Hin]. * subst x. simpl. left. reflexivity. * simpl. right. exact Hin. Qed.
Lemma sidpos_history_WF_O tm: sidpos_history_WF tm ({| l := nil; r := nil; m := Σ0; s := St0 |}, 0%Z) nil.
Proof. unfold sidpos_history_WF. intros. cbn in H. assert (n=0) by lia. subst. replace (length nil - 0) with 0 by reflexivity. unfold nth_error. rewrite ListES_toES_O. ctor. Qed.
Lemma sidpos_history_WF_O tm: sidpos_history_WF tm ({| l := nil; r := nil; m := Σ0; s := St0 |}, 0%Z) nil.
Proof. unfold sidpos_history_WF. intros n Hn. assert (Hn0: n = 0) by (simpl in Hn; lia). subst n. simpl Nat.sub. simpl nth_error. pose proof ListES_toES_O as HPA. unfold ListES_toES in HPA. unfold InitES in HPA. unfold ListES_toES. rewrite HPA. constructor. Qed.
Lemma sidpos_history_WF_S {tm l0 r0 m0 s0 d ls s1 d1 o1}: sidpos_history_WF tm (Build_ListES l0 r0 m0 s0, d) ls -> tm s0 m0 = Some {| nxt := s1; dir := d1; out := o1 |} -> sidpos_history_WF tm (ListES_step' {| nxt := s1; dir := d1; out := o1 |} (Build_ListES l0 r0 m0 s0), (d+(Dir_to_Z d1))%Z) ((Build_ListES l0 r0 m0 s0, d)::ls).
Proof. intros. epose proof (ListES_step'_spec tm l0 r0 m0 s0) as H1. remember (Build_ListES l0 r0 m0 s0) as es0. rewrite H0 in H1. remember {| nxt := s1; dir := d1; out := o1 |} as tr. unfold sidpos_history_WF. unfold sidpos_history_WF in H. replace (length ((es0, d) :: ls)) with (S (length ls)) by reflexivity. intros. assert (E:n<=length ls \/ n=S (length ls)) by lia. destruct E as [E|E]. - replace (S (length ls) - n) with (S (length ls - n)) by lia. cbn. apply H,E. - replace (S (length ls) - n) with (O) by lia. cbn. rewrite E. eassert (H3:_) by (apply (H (length ls)); lia). rewrite Nat.sub_diag in H3. cbn in H3. subst es0. ector; eauto 1. subst tr. cbn. lia. Qed.
Lemma sidpos_history_WF_S {tm l0 r0 m0 s0 d ls s1 d1 o1}: sidpos_history_WF tm (Build_ListES l0 r0 m0 s0, d) ls -> tm s0 m0 = Some {| nxt := s1; dir := d1; out := o1 |} -> sidpos_history_WF tm (ListES_step' {| nxt := s1; dir := d1; out := o1 |} (Build_ListES l0 r0 m0 s0), (d+(Dir_to_Z d1))%Z) ((Build_ListES l0 r0 m0 s0, d)::ls).
Proof. intros HWhp Htm. unfold sidpos_history_WF. intros n Hn. simpl length in *. assert (Hcases: n <= length ls \/ n = S (length ls)) by lia. destruct Hcases as [Hle | Heq]. - replace (S (length ls) - n) with (S (length ls - n)) by lia. simpl nth_error. unfold sidpos_history_WF in HWhp. exact (HWhp n Hle). - subst n. rewrite Nat.sub_diag. simpl nth_error. set (tr := {| nxt := s1; dir := d1; out := o1 |}). pose proof (sidpos_history_hd HWhp) as Hmd. assert (HyzC: step Σ tm (ListES_toES (Build_ListES l0 r0 m0 s0)) = Some (ListES_toES (ListES_step' tr (Build_ListES l0 r0 m0 s0)))). { rewrite ListES_step'_spec. rewrite Htm. reflexivity. } assert (Htm': tm (fst (ListES_toES (Build_ListES l0 r0 m0 s0))) (snd (ListES_toES (Build_ListES l0 r0 m0 s0)) Z0) = Some tr). { simpl. exact Htm. } remember (ListES_toES (Build_ListES l0 r0 m0 s0)) as st eqn:Hst. destruct st as [s0' t0]. eapply (MoveDist_S _ _ _ s0' t0 _ d (d + Dir_to_Z d1)%Z tr). + exact Hmd. + exact HyzC. + simpl in Htm'. exact Htm'. + subst tr. simpl. lia. Qed.
Lemma sidpos_history_WF_cdr tm h h1 ls: sidpos_history_WF tm h (h1::ls) -> sidpos_history_WF tm h1 ls.
Proof. unfold sidpos_history_WF. intros. specialize (H n). replace (length (h1 :: ls) - n) with (S (length ls - n)) in H. apply H. cbn. lia. cbn. destruct n; lia. Qed.
Lemma sidpos_history_WF_cdr tm h h1 ls: sidpos_history_WF tm h (h1::ls) -> sidpos_history_WF tm h1 ls.
Proof. unfold sidpos_history_WF. intros H n Hn. specialize (H n). simpl length in *. assert (Hn': n <= S (length ls)) by lia. specialize (H Hn'). replace (S (length ls) - n) with (S (length ls - n)) in H by lia. simpl nth_error in H. exact H. Qed.
Lemma sidpos_history_hd {tm es d ls}: sidpos_history_WF tm (es,d) ls -> MoveDist tm (length ls) (InitES Σ Σ0) (ListES_toES es) d.
Proof. unfold sidpos_history_WF. intros. specialize (H (length ls)). replace (length ls - length ls) with 0 in H by lia. cbn in H. apply H. lia. Qed.
Lemma sidpos_history_hd {tm es d ls}: sidpos_history_WF tm (es,d) ls -> MoveDist tm (length ls) (InitES Σ Σ0) (ListES_toES es) d.
Proof. unfold sidpos_history_WF. intro H. specialize (H (length ls) (Nat.le_refl _)). rewrite Nat.sub_diag in H. simpl nth_error in H. exact H. Qed.
Lemma sidpos_history_period_S {h0 ls0 ls1 ls2 l0 l1 z z0 N T}: (l0, z) :: ls1 = skipn N (h0 :: ls0) -> (l1, z0) :: ls2 = skipn (S T) ((l0, z) :: ls1) -> sidpos_history_period h0 ls0 N (S T) -> s l0 = s l1 -> m l0 = m l1 -> sidpos_history_period h0 ls0 (S N) (S T).
Proof. unfold sidpos_history_period. cbn. intros. assert (E1:n<N\/n=N) by lia. destruct E1 as [E1|E1]. 1: apply H1,E1. subst. erewrite nth_error_skipn; eauto 1. cbn. assert (H5:(l1, z0) :: ls2 = skipn (S T) ((l0,z)::ls1)) by apply H0. clear H0. rewrite H in H5. rewrite skipn_skipn in H5. cbn in H5. erewrite nth_error_skipn; eauto 1. cbn. split; auto 1. Qed.
Lemma sidpos_history_period_S {h0 ls0 ls1 ls2 l0 l1 z z0 N T}: (l0, z) :: ls1 = skipn N (h0 :: ls0) -> (l1, z0) :: ls2 = skipn (S T) ((l0, z) :: ls1) -> sidpos_history_period h0 ls0 N (S T) -> s l0 = s l1 -> m l0 = m l1 -> sidpos_history_period h0 ls0 (S N) (S T).
Proof. intros Hskip1 Hskip2 HK Hs Hm. unfold sidpos_history_period. intros n Hn. assert (Hcases: n < N \/ n = N) by lia. destruct Hcases as [HnN | HnN]. - exact (HK n HnN). - subst n. pose proof (nth_error_skipn Hskip1) as Hnth1. assert (Hskip_composed: (l1, z0) :: ls2 = skipn (S T + N) (h0 :: ls0)). { rewrite <- skipn_skipn. rewrite <- Hskip1. exact Hskip2. } pose proof (nth_error_skipn Hskip_composed) as Hnth2. rewrite Hnth1. rewrite Hnth2. split; assumption. Qed.
Lemma sidpos_history_period_S' {h0 h0' ls0' N T}: sidpos_history_period h0 (h0' :: ls0') (S N) (S T) -> sidpos_history_period h0' ls0' N (S T).
Proof. unfold sidpos_history_period. intros. specialize (H (S n)). replace (S T + S n) with (S (S T + n)) in H by lia. cbn in H. cbn. apply H. lia. Qed.
Lemma sidpos_history_period_S' {h0 h0' ls0' N T}: sidpos_history_period h0 (h0' :: ls0') (S N) (S T) -> sidpos_history_period h0' ls0' N (S T).
Proof. unfold sidpos_history_period. intros H n Hn. assert (Hn': S n < S N) by lia. specialize (H (S n) Hn'). simpl nth_error in H. replace (T + S n) with (S T + n) in H by lia. exact H. Qed.
Lemma skipn_S {T} {n} {h:T} {t ls}: h::t = skipn n ls -> t = skipn (S n) ls.
Proof. gd ls. gd t. gd h. induction n; intros. - cbn. cbn in H. subst. reflexivity. - destruct ls as [|h0 t0]. 1: cbn in H; cg. cbn in H. cbn. apply (IHn _ _ _ H). Qed.
Lemma skipn_S {T} {n} {h:T} {t ls}: h::t = skipn n ls -> t = skipn (S n) ls.
Proof. revert n. induction ls as [|a ls' IH]; intros n H. - destruct n; simpl in H; discriminate. - destruct n as [|n']. + simpl in *. inversion H. reflexivity. + simpl in *. apply IH in H. exact H. Qed.
Lemma skipn_S' {T} {n} {h h':T} {t t'}: h::t = skipn n (h'::t') -> t = skipn n t'.
Proof. gd t. gd t'. gd h. gd h'. induction n; intros. - cbn. invst H. reflexivity. - destruct t' as [|h'' t'']. 1: cbn in H; rewrite skipn_nil in H; invst H. cbn. cbn in H. eapply IHn; eauto 1. Qed.
Lemma skipn_S' {T} {n} {h h':T} {t t'}: h::t = skipn n (h'::t') -> t = skipn n t'.
Proof. intro H. apply skipn_S in H. simpl in H. exact H. Qed.
Lemma skipn_S_n {T} n (ls:list T): skipn (S n) ls = tl (skipn n ls).
Proof. gd ls. induction n; intros. 1: reflexivity. cbn. destruct ls. 1: reflexivity. destruct ls. 1: rewrite skipn_nil; reflexivity. specialize (IHn (t0::ls)). rewrite <-IHn. reflexivity. Qed.
Lemma skipn_S_n {T} n (ls:list T): skipn (S n) ls = tl (skipn n ls).
Proof. revert ls. induction n as [|n' IH]; intros ls. - simpl. destruct ls; reflexivity. - destruct ls as [|a ls']. + simpl. reflexivity. + simpl. apply IH. Qed.
Lemma skipn_skipn {T} n1 n2 (ls:list T): skipn n1 (skipn n2 ls) = skipn (n1+n2) ls.
Proof. gd ls. gd n2. induction n1; intros. 1: reflexivity. epose proof (IHn1 n2 ls). assert (E:S n1 + n2 = S (n1+n2)) by lia. rewrite E. repeat rewrite skipn_S_n. f_equal. apply IHn1. Qed.
Lemma skipn_skipn {T} n1 n2 (ls:list T): skipn n1 (skipn n2 ls) = skipn (n1+n2) ls.
Proof. revert n1 ls. induction n2 as [|n2' IH]; intros n1 ls. - simpl. rewrite Nat.add_0_r. reflexivity. - destruct ls as [|a ls']. + simpl. rewrite skipn_nil. destruct (n1+S n2'); reflexivity. + simpl. rewrite IH. replace (n1 + S n2') with (S (n1 + n2')) by lia. reflexivity. Qed.
Lemma step_UnusedState {tm s0 t0 s t}: step Σ tm (s0, t0) = Some (s, t) -> ~ UnusedState tm s.
Proof. intros. intro. cbn in H. destruct H0 as [H0a [H0b H0c]]. specialize (H0a s0 (t0 Z0)). destruct (tm s0 (t0 Z0)) as [[s' d o]|] eqn:E; cg. invst H. cbn in H0a. cg. Qed.
Lemma step_UnusedState {tm s0 t0 s t}: step Σ tm (s0, t0) = Some (s, t) -> ~ UnusedState tm s.
Proof. intro Hstep. unfold step in Hstep. destruct (tm s0 (t0 0%Z)) as [[s' d o]|] eqn:E; [|discriminate]. inversion Hstep; subst. intros [Hnxt [_ _]]. specialize (Hnxt s0 (t0 0%Z)). rewrite E in Hnxt. apply Hnxt. reflexivity. Qed.
Lemma step_halt_rev tm st: step (TM_rev tm) st = None <-> step tm (ExecState_rev st) = None.
Proof. destruct st. cbn. unfold Tape_rev. cbn. unfold TM_rev. destruct (tm s (σ 0%Z)) eqn:E; cbn. 2: tauto. destruct t; cbn. split; intro; cg. Qed.
Lemma step_halt_rev tm st: step (TM_rev tm) st = None <-> step tm (ExecState_rev st) = None.
Proof. destruct st as [s t]. unfold step, TM_rev, ExecState_rev, option_Trans_rev, Trans_rev, Tape_rev. replace (t (- 0)%Z) with (t 0%Z) by (f_equal; lia). destruct (tm s (t 0%Z)) as [[s' d o]|]; split; intro H; try discriminate; reflexivity. Qed.
Lemma step_halt_swap tm st: step (TM_swap tm) st = None <-> step tm (ExecState_swap st) = None.
Proof. destruct st. cbn. unfold TM_swap. destruct (tm (St_swap s) (σ 0%Z)) eqn:E; cbn. 2: split; intro; cg. destruct t. cbn. split; intro; cg. Qed.
Lemma step_halt_swap tm st: step (TM_swap tm) st = None <-> step tm (ExecState_swap st) = None.
Proof. destruct st as [s t]. unfold step, TM_swap, ExecState_swap, option_Trans_swap, Trans_swap. destruct (tm (St_swap s) (t 0%Z)) as [[s' d o]|]; split; intro H; try discriminate; reflexivity. Qed.
Lemma step_rev tm st st0: step (TM_rev tm) st = Some st0 <-> step tm (ExecState_rev st) = Some (ExecState_rev st0).
Proof. destruct st,st0. cbn. unfold Tape_rev. cbn. unfold TM_rev. destruct (tm s (σ 0%Z)) as [[s' d o]|] eqn:E; cbn. 2: split; intro; cg. split; intro. - invst H. f_equal; f_equal. unfold mov. fext. unfold upd. destruct d; cbn. + assert (x=1\/x<>1)%Z by lia; destruct H0; destruct ((x + -1 =? 0)%Z) eqn:E0; destruct ((-x + 1 =? 0)%Z) eqn:E1; try lia; cg. f_equal; lia. + assert (x=-1\/x<>-1)%Z by lia; destruct H0; destruct ((x + 1 =? 0)%Z) eqn:E0; destruct ((-x + -1 =? 0)%Z) eqn:E1; try lia; cg. f_equal; lia. - invst H. f_equal; f_equal. unfold mov. unfold mov in H2. fext. pose proof (fext_inv (-x)%Z H2) as H3. cbn in H3. assert ((- - x)%Z = x) by lia. rewrite H0 in H3. rewrite <-H3. destruct d; cbn. + unfold upd. assert (H1:(x=-1\/x<>-1)%Z) by lia. destruct H1; destruct ((x + 1 =? 0)%Z) eqn:E0; destruct ((-x + -1 =? 0)%Z) eqn:E1; try lia; cg. f_equal; lia. + unfold upd. assert (H4:(x=1\/x<>1)%Z) by lia; destruct H4; destruct ((x + -1 =? 0)%Z) eqn:E0; destruct ((-x + 1 =? 0)%Z) eqn:E1; try lia; cg. f_equal; lia. Qed.
Lemma step_rev tm st st0: step (TM_rev tm) st = Some st0 <-> step tm (ExecState_rev st) = Some (ExecState_rev st0).
Proof. split. - apply step_rev_fwd. - intro H. assert (H': step (TM_rev (TM_rev tm)) (ExecState_rev st) = Some (ExecState_rev st0)). { rewrite TM_rev_rev. exact H. } apply step_rev_fwd in H'. rewrite ExecState_rev_rev in H'. rewrite ExecState_rev_rev in H'. exact H'. Qed.
Lemma step_swap {tm st st0}: step (TM_swap tm) st = Some st0 <-> step tm (ExecState_swap st) = Some (ExecState_swap st0).
Proof. destruct st,st0. cbn. unfold TM_swap. destruct (tm (St_swap s) (σ 0%Z)) eqn:E; cbn. 2: split; intro; cg. destruct t. cbn. split; intro; f_equal. - invst H. f_equal. rewrite St_swap_swap; reflexivity. - invst H. f_equal. apply St_swap_swap. Qed.
Lemma step_swap {tm st st0}: step (TM_swap tm) st = Some st0 <-> step tm (ExecState_swap st) = Some (ExecState_swap st0).
Proof. destruct st as [s t]. destruct st0 as [s0 t0]. unfold step, TM_swap, ExecState_swap, option_Trans_swap, Trans_swap. destruct (tm (St_swap s) (t 0%Z)) as [[s' d o]|]; split; intro H; try discriminate. - inversion H; subst. simpl. rewrite (St_swap_swap s'). reflexivity. - inversion H; subst. simpl. rewrite St_swap_swap. reflexivity. Qed.
Lemma tape_seg__repeat_Σ0 x d len: repeat Σ0 len = tape_seg (fun _ : Z => Σ0) x d len.
Proof. gd x. gd d. induction len; cbn; intros; cg. Qed.
Lemma tape_seg__repeat_Σ0 x d len: repeat Σ0 len = tape_seg (fun _ : Z => Σ0) x d len.
Proof. revert x. induction len as [|len' IH]; intros x. - simpl. reflexivity. - simpl. f_equal. apply IH. Qed.
Lemma tape_seg_hd h t1 t x d len: h :: t1 = tape_seg t x d len -> h = t x.
Proof. destruct len. - cbn. intro. cg. - cbn. intro. invst H. cg. Qed.
Lemma tape_seg_hd h t1 t x d len: h :: t1 = tape_seg t x d len -> h = t x.
Proof. destruct len as [|len']. - simpl. intros H. discriminate. - simpl. intros H. inversion H. reflexivity. Qed.
Lemma tape_seg_mov_upd t d o len: tape_seg t ((Dir_to_Z d)*2)%Z d len = tape_seg (mov Σ (upd Σ t o) d) (Dir_to_Z d) d len.
Proof. destruct (tape_seg_spec t (Dir_to_Z d * 2) d len) as [H0a H0b]. destruct (tape_seg_spec (mov Σ (upd Σ t o) d) (Dir_to_Z d) d len) as [H1a H1b]. apply list_eq__nth_error. 1: cg. intros. rewrite (H0a n). 2: lia. rewrite (H1a n). 2: lia. f_equal. unfold mov,upd. assert ((Dir_to_Z d + Dir_to_Z d * Z.of_nat n + Dir_to_Z d <> 0)%Z). { destruct d; unfold Dir_to_Z; lia. } rewrite <-Z.eqb_neq in H0. rewrite H0. f_equal. lia. Qed.
Lemma tape_seg_mov_upd t d o len: tape_seg t ((Dir_to_Z d)*2)%Z d len = tape_seg (mov Σ (upd Σ t o) d) (Dir_to_Z d) d len.
Proof. apply list_eq__nth_error. - repeat rewrite (proj2 (tape_seg_spec _ _ _ _)). reflexivity. - intros k Hk. rewrite (proj2 (tape_seg_spec _ _ _ _)) in Hk. rewrite (proj1 (tape_seg_spec _ _ _ _) k Hk). rewrite (proj1 (tape_seg_spec _ _ _ _) k Hk). f_equal. unfold mov, upd. assert (Hne: (Dir_to_Z d + Dir_to_Z d * Z.of_nat k + Dir_to_Z d)%Z <> 0%Z). { pose proof (Zle_0_nat k). destruct d; unfold Dir_to_Z; lia. } replace (Z.eqb (Dir_to_Z d + Dir_to_Z d * Z.of_nat k + Dir_to_Z d) 0) with false. 2:{ symmetry. rewrite Z.eqb_neq. exact Hne. } f_equal. lia. Qed.
Lemma tape_seg_mov_upd_2 hr r1 t d o len: hr :: r1 = tape_seg t (Dir_to_Z d) d len -> o :: pop_back hr r1 = tape_seg (mov Σ (upd Σ t o) (Dir_rev d)) (Dir_to_Z d) d len.
Proof. intros. destruct (tape_seg_spec t (Dir_to_Z d) d len) as [H0a H0b]. destruct (tape_seg_spec (mov Σ (upd Σ t o) (Dir_rev d)) (Dir_to_Z d) d len) as [H1a H1b]. assert (H':length (o::pop_back hr r1) = len). { cbn. rewrite pop_back_len. rewrite <-H in H0b. destruct len; cbn in H0b; cg. } apply list_eq__nth_error. 1: cg. rewrite H'. intros. rewrite H1a. 2: lia. destruct n. - cbn. f_equal. unfold mov,upd. destruct d; cbn; reflexivity. - cbn. cbn in H'. destruct len. 1: lia. rewrite <-H in H0a,H0b. cbn in H0b. rewrite pop_back__nth_error. 2: lia. rewrite H0a. 2: lia. unfold mov,upd. f_equal. assert (H2:(Dir_to_Z d + Dir_to_Z d * Z.pos (Pos.of_succ_nat n) + Dir_to_Z (Dir_rev d) <> 0)%Z). { destruct d; unfold Dir_rev,Dir_to_Z; lia. } rewrite <-Z.eqb_neq in H2. rewrite H2. f_equal. assert (H1:(Z.pos (Pos.of_succ_nat n) = 1+(Z.of_nat n))%Z) by lia. rewrite H1. destruct d; unfold Dir_to_Z,Dir_rev; lia. Qed.
Lemma tape_seg_mov_upd_2 hr r1 t d o len: hr :: r1 = tape_seg t (Dir_to_Z d) d len -> o :: pop_back hr r1 = tape_seg (mov Σ (upd Σ t o) (Dir_rev d)) (Dir_to_Z d) d len.
Proof. intros H. assert (Hlen: length (hr :: r1) = len). { rewrite H. apply (proj2 (tape_seg_spec _ _ _ _)). } simpl in Hlen. apply list_eq__nth_error. - simpl. rewrite pop_back_len. rewrite (proj2 (tape_seg_spec _ _ _ _)). lia. - intros k Hk. transitivity (nth_error (tape_seg (mov Σ (upd Σ t o) (Dir_rev d)) (Dir_to_Z d) d len) k). 2:{ reflexivity. } destruct k as [|k']. + (* k = 0 *) simpl. destruct len as [|len']; [lia|]. simpl. f_equal. unfold mov, upd. replace (Dir_to_Z d + Dir_to_Z (Dir_rev d))%Z with 0%Z by (destruct d; unfold Dir_to_Z, Dir_rev; lia). simpl. reflexivity. + (* k = S k' *) assert (q_135: k' < length r1). { simpl in Hk. rewrite pop_back_len in Hk. lia. } assert (Hk3: S k' < len) by lia. assert (Hk4: k' < len) by lia. transitivity (nth_error (hr :: r1) k'). { simpl. apply pop_back__nth_error. exact q_135. } rewrite H. rewrite (proj1 (tape_seg_spec t (Dir_to_Z d) d len) k' Hk4). symmetry. rewrite (proj1 (tape_seg_spec (mov Σ (upd Σ t o) (Dir_rev d)) (Dir_to_Z d) d len) (S k') Hk3). f_equal. unfold mov, upd. assert (Hne: (Dir_to_Z d + Dir_to_Z d * Z.of_nat (S k') + Dir_to_Z (Dir_rev d))%Z <> 0%Z). { destruct d; unfold Dir_to_Z, Dir_rev; lia. } replace (Z.eqb (Dir_to_Z d + Dir_to_Z d * Z.of_nat (S k') + Dir_to_Z (Dir_rev d)) 0) with false by (symmetry; rewrite Z.eqb_neq; exact Hne). f_equal. destruct d; unfold Dir_to_Z, Dir_rev; lia. Qed.
Lemma tape_seg_pop hl l1 t d len: hl :: l1 = tape_seg t (Dir_to_Z d) d len -> (l1 ++ t ((Dir_to_Z d)*(Z.of_nat (S len)))%Z :: nil) = (tape_seg t ((Dir_to_Z d)*2)%Z d len).
Proof. intro H. destruct (tape_seg_spec t (Dir_to_Z d) d len) as [H0a H0b]. destruct (tape_seg_spec t (Dir_to_Z d * 2) d len) as [H1a H1b]. rewrite <-H in H0a,H0b. destruct len. 1: cbn in H0b; cg. cbn in H0b. injection H0b; intro. apply list_eq__nth_error. - rewrite H1b. rewrite app_length,H0. cbn. lia. - rewrite app_length,H0. intros. cbn in H1. assert (n<length l1 \/ n=length l1) by lia. destruct H2 as [H2|H2]. + rewrite nth_error_app1. 2: assumption. specialize (H0a (S n)). cbn in H0a. rewrite H0a. 2: lia. specialize (H1a n). rewrite H1a. 2: lia. f_equal. f_equal. lia. + rewrite nth_error_app2. 2: lia. assert (H3:n-length l1 = 0) by lia. rewrite H3. specialize (H1a n). rewrite H1a. 2: lia. cbn. f_equal. f_equal. lia. Qed.
Lemma tape_seg_pop hl l1 t d len: hl :: l1 = tape_seg t (Dir_to_Z d) d len -> (l1 ++ t ((Dir_to_Z d)*(Z.of_nat (S len)))%Z :: nil) = (tape_seg t ((Dir_to_Z d)*2)%Z d len).
Proof. intros H. apply list_eq__nth_error. - rewrite app_length. simpl. assert (Hlen1: length (hl :: l1) = len). { rewrite H. apply (proj2 (tape_seg_spec _ _ _ _)). } simpl in Hlen1. rewrite (proj2 (tape_seg_spec _ _ _ _)). lia. - intros k Hk. rewrite app_length in Hk. simpl in Hk. assert (Hlen1: length (hl :: l1) = len). { rewrite H. apply (proj2 (tape_seg_spec _ _ _ _)). } assert (Hlen_l1: length l1 = len - 1). { simpl in Hlen1. lia. } destruct (Nat.lt_ge_cases k (length l1)) as [Hlt|Hge]. + (* k < length l1: element from l1 *) rewrite nth_error_app1 by exact Hlt. assert (Hk1: S k < len). { lia. } assert (Hhl: nth_error (hl :: l1) (S k) = nth_error l1 k) by reflexivity. rewrite H in Hhl. rewrite (proj1 (tape_seg_spec _ _ _ _) (S k) Hk1) in Hhl. rewrite <- Hhl. rewrite (proj1 (tape_seg_spec _ _ _ _) k). * f_equal. f_equal. lia. * lia. + (* k >= length l1: element is the last one *) assert (Hk_eq: k = length l1). { lia. } subst k. rewrite nth_error_app2 by lia. replace (length l1 - length l1) with 0 by lia. cbn [nth_error]. rewrite (proj1 (tape_seg_spec _ _ _ _) (length l1)). * do 2 f_equal. rewrite <- Z.mul_add_distr_l. f_equal. simpl in Hlen1. lia. * simpl in Hlen1. lia. Qed.
Lemma tape_seg_spec t x d len: (forall n:nat, n<len -> nth_error (tape_seg t x d len) n = Some (t (x+(Dir_to_Z d)*(Z.of_nat n))%Z))/\ length (tape_seg t x d len) = len.
Proof. split. { gd x. induction len. 1: lia. intros. destruct n. - cbn. repeat f_equal. lia. - assert (H0:n<len) by lia. cbn. rewrite (IHlen (x+(Dir_to_Z d))%Z n H0). f_equal; f_equal. lia. } { gd x. induction len. - intros. reflexivity. - intros. cbn. f_equal. apply IHlen. } Qed.
Lemma tape_seg_spec t x d len: (forall n:nat, n<len -> nth_error (tape_seg t x d len) n = Some (t (x+(Dir_to_Z d)*(Z.of_nat n))%Z))/\ length (tape_seg t x d len) = len.
Proof. revert x. induction len as [|len' IH]; intros x. - split. + intros n Hn. lia. + simpl. reflexivity. - split. + intros n Hn. simpl. destruct n as [|n']. * simpl. f_equal. f_equal. lia. * simpl. destruct (IH (x + Dir_to_Z d)%Z) as [IH1 IH2]. rewrite IH1 by lia. f_equal. f_equal. lia. + simpl. f_equal. apply (IH (x + Dir_to_Z d)%Z). Qed.
Lemma update_AES_Closed tm SI flag n: AES_impl_WF SI -> match update_AES tm (fst (mset' SI)) SI flag n with | (SI',flag',_) => AES_impl_WF SI' /\ (flag'=true -> (AES_isClosed tm (AES_impl_to_AES SI) /\ SI=SI')) end.
Proof. intros. destruct (update_AES tm (fst (mset' SI)) SI flag n) as [[SI' flag'] n0_] eqn:E. epose proof (update_AES_spec _ _ _ _ _ H) as H0. rewrite E in H0. destruct H0 as [H0 H1]. repeat split. 1: assumption. - intro; subst. specialize (H1 eq_refl). destruct H1 as [H1 [H2 H3]]; subst. apply AES_isClosed'_correct. unfold AES_isClosed'. destruct SI'. unfold AES_impl_to_AES. intros. apply H2; auto 1. cbn. cbn in H. destruct H as [_ [_ H]]. unfold mset_WF,set_WF in H. rewrite H in H1. apply H1. - apply H1,H2. Qed.
Lemma update_AES_Closed tm SI flag n: AES_impl_WF SI -> match update_AES tm (fst (mset' SI)) SI flag n with | (SI',flag',_) => AES_impl_WF SI' /\ (flag'=true -> (AES_isClosed tm (AES_impl_to_AES SI) /\ SI=SI')) end.
Proof. intro HSI. pose proof (update_AES_spec tm (fst (mset' SI)) SI flag n HSI) as Ha. destruct (update_AES tm (fst (mset' SI)) SI flag n) as [[SI' flag'] n'] eqn:Es7. destruct Ha as [HSI' Ha_imp]. split; [exact HSI'|]. intro Hflag'. destruct (Ha_imp Hflag') as [_ [Hmw_in Heq]]. split; [|exact Heq]. apply AES_isClosed'_correct. destruct SI as [ls rs ms]. simpl in *. destruct HSI as [Hls [Hrs Hms]]. unfold AES_isClosed'. simpl. intros mw Hmsmw. apply Hmw_in. apply Hms. exact Hmsmw. Qed.
Lemma update_AES_MidWord_spec tm q mw SI: AES_impl_WF SI -> match update_AES_MidWord tm q mw SI with | (q',SI',flag) => AES_impl_WF SI' /\ (flag=true -> (q'=q /\ SI'=SI /\ AES_CloseAt tm (AES_impl_to_AES SI) mw)) end.
Proof. destruct (update_AES_MidWord tm q mw SI) as [[q' SI'] flag] eqn:E. intros. destruct mw as [l0 r0 m0 s0]. destruct SI as [ls rs ms]. cbn in E. destruct l0 as [|hl l1]. 1: invst E; split; [assumption | intro; cg]. destruct r0 as [|hr r1]. 1: invst E; split; [assumption | intro; cg]. destruct (tm s0 m0) as [[s1 d o]|] eqn:E0. 2: invst E; split; [assumption | intro; cg]. destruct H as [H [H0 H1]]. destruct d. { destruct (xset_ins rs (hr :: r1)) as [rs' flag1] eqn:E1. destruct (mset_ins q ms true (fun x : Σ => {| l := l1 ++ x :: nil; r := o :: pop_back hr r1; m := hl; s := s1 |}) (xset_as_list ls l1)) as [[q'0 ms'] flag2] eqn:E2. invst E. clear E. rewrite Bool.andb_true_iff. destruct (xset_ins_spec _ _ _ _ _ H0 E1) as [H2a H2b]. destruct (mset_ins_spec _ _ _ _ _ _ _ _ H1 E2) as [H3a H3b]. unfold AES_impl_WF. split. 1: tauto. intro H2. destruct H2; subst. specialize (H2b eq_refl). specialize (H3b eq_refl). destruct H2b as [H2b H2c]. destruct H3b as [_ [H3b [H3c H3d]]]. subst. repeat split; cg. unfold AES_CloseAt,AES_impl_to_AES. rewrite E0. split. 1: assumption. intros x H2. apply H3d. apply xset_as_list_spec; assumption. } { destruct (xset_ins ls (hl :: l1)) as [ls' flag1] eqn:E1. destruct (mset_ins q ms true (fun x : Σ => {| l := o :: pop_back hl l1; r := r1 ++ x :: nil; m := hr; s := s1 |}) (xset_as_list rs r1)) as [[q'0 ms'] flag2] eqn:E2. invst E. clear E. rewrite Bool.andb_true_iff. destruct (xset_ins_spec _ _ _ _ _ H E1) as [H2a H2b]. destruct (mset_ins_spec _ _ _ _ _ _ _ _ H1 E2) as [H3a H3b]. unfold AES_impl_WF. split. 1: tauto. intro H2. destruct H2; subst. specialize (H2b eq_refl). specialize (H3b eq_refl). destruct H2b as [H2b H2c]. destruct H3b as [_ [H3b [H3c H3d]]]. subst. repeat split; cg. unfold AES_CloseAt,AES_impl_to_AES. rewrite E0. split. 1: assumption. intros x H2. apply H3d. apply xset_as_list_spec; assumption. } Qed.
Lemma update_AES_MidWord_spec tm q mw SI: AES_impl_WF SI -> match update_AES_MidWord tm q mw SI with | (q',SI',flag) => AES_impl_WF SI' /\ (flag=true -> (q'=q /\ SI'=SI /\ AES_CloseAt tm (AES_impl_to_AES SI) mw)) end.
Proof. destruct mw as [l0 r0 m0 s0]. destruct SI as [ls rs ms]. intro HSI. destruct HSI as [Hls [Hrs Hms]]. unfold update_AES_MidWord. destruct l0 as [|hl l1]. { split; [split; [exact Hls|split; [exact Hrs|exact Hms]]|intros; discriminate]. } destruct r0 as [|hr r1]. { split; [split; [exact Hls|split; [exact Hrs|exact Hms]]|intros; discriminate]. } destruct (tm s0 m0) as [tr|] eqn:Etm. 2:{ split; [split; [exact Hls|split; [exact Hrs|exact Hms]]|intros; discriminate]. } destruct tr as [s1 d o]. destruct d. - (* Dneg *) destruct (xset_ins rs (hr :: r1)) as [rs' flag1] eqn:Engr. pose proof (xset_ins_spec rs hr r1 rs' flag1 Hrs Engr) as [Hrs' Hflag1]. destruct (mset_ins q ms true (fun x => {| l := l1 ++ x :: nil; r := o :: pop_back hr r1; m := hl; s := s1 |}) (xset_as_list ls l1)) as [[q' ms'] flag2] eqn:Ebuv. pose proof (mset_ins_spec q ms true (fun x => {| l := l1 ++ x :: nil; r := o :: pop_back hr r1; m := hl; s := s1 |}) (xset_as_list ls l1) q' ms' flag2 Hms Ebuv) as [Hms' Hflag2]. split. + split; [exact Hls|split; [exact Hrs'|exact Hms']]. + intro Hflag. apply Bool.andb_true_iff in Hflag. destruct Hflag as [Hf1 Hf2]. destruct (Hflag1 Hf1) as [Hrs'eq Hd0]. subst rs'. destruct (Hflag2 Hf2) as [_ [Hq'eq [Hms'eq HIn]]]. subst q' ms'. split; [reflexivity|split; [reflexivity|]]. unfold AES_CloseAt, AES_impl_to_AES. rewrite Etm. split; [exact Hd0|]. intros x Hlsx. apply HIn. apply (xset_as_list_spec ls l1 x Hls Hlsx). - (* Dpos - symmetric *) destruct (xset_ins ls (hl :: l1)) as [ls' flag1] eqn:Engl. pose proof (xset_ins_spec ls hl l1 ls' flag1 Hls Engl) as [Hls' Hflag1]. destruct (mset_ins q ms true (fun x => {| l := o :: pop_back hl l1; r := r1 ++ x :: nil; m := hr; s := s1 |}) (xset_as_list rs r1)) as [[q' ms'] flag2] eqn:Ebuv. pose proof (mset_ins_spec q ms true (fun x => {| l := o :: pop_back hl l1; r := r1 ++ x :: nil; m := hr; s := s1 |}) (xset_as_list rs r1) q' ms' flag2 Hms Ebuv) as [Hms' Hflag2]. split. + split; [exact Hls'|split; [exact Hrs|exact Hms']]. + intro Hflag. apply Bool.andb_true_iff in Hflag. destruct Hflag as [Hf1 Hf2]. destruct (Hflag1 Hf1) as [Hls'eq Hd0]. subst ls'. destruct (Hflag2 Hf2) as [_ [Hq'eq [Hms'eq HIn]]]. subst q' ms'. split; [reflexivity|split; [reflexivity|]]. unfold AES_CloseAt, AES_impl_to_AES. rewrite Etm. split; [exact Hd0|]. intros x Hrsx. apply HIn. apply (xset_as_list_spec rs r1 x Hrs Hrsx). Qed.
Lemma update_AES_spec tm q SI flag n: AES_impl_WF SI -> match update_AES tm q SI flag n with | (SI',flag',_) => AES_impl_WF SI' /\ (flag'=true -> flag=true /\ (forall mw, In mw q -> AES_CloseAt tm (AES_impl_to_AES SI) mw) /\ SI=SI') end.
Proof. gd flag. gd SI. gd q. induction n; intros. - cbn. split; cg. - cbn. destruct q as [|mw q]. + split; cg. intros. repeat split; cg. intros. destruct H1. + cbn. destruct (update_AES_MidWord tm q mw SI) as [[q' SI'] flag'] eqn:E. specialize (IHn q' SI' (flag&&flag')%bool). destruct (update_AES tm q' SI' (flag && flag') n) as [[SI'0 flag'0] n0_] eqn:E0. pose proof (update_AES_MidWord_spec tm q mw SI H) as Hmw. rewrite E in Hmw. destruct Hmw as [Hmw0 Hmw1]. destruct (IHn Hmw0) as [IHn0 IHn1]. clear IHn. split. 1: assumption. intros H1. destruct (IHn1 H1) as [IHn1a [IHn1b IHn1d]]. clear IHn1. rewrite Bool.andb_true_iff in IHn1a. destruct IHn1a as [IHn1a IHn1c]. repeat split. 1: cg. * intros mw0 H2. specialize (IHn1b mw0). specialize (Hmw1 IHn1c). destruct Hmw1 as [Hmw1 [Hmw2 Hmw3]]; subst. destruct H2 as [H2|H2]; subst; tauto. * subst. destruct (Hmw1 eq_refl) as [_ [Hmw1a _]]. cg. Qed.
Lemma update_AES_spec tm q SI flag n: AES_impl_WF SI -> match update_AES tm q SI flag n with | (SI',flag',_) => AES_impl_WF SI' /\ (flag'=true -> flag=true /\ (forall mw, In mw q -> AES_CloseAt tm (AES_impl_to_AES SI) mw) /\ SI=SI') end.
Proof. revert q SI flag. induction n as [|n0 IH]; intros q SI flag HSI. - simpl. split; [exact HSI|discriminate]. - destruct q as [|mw ms0]. + simpl. split; [exact HSI|]. intro Hflag. split; [exact Hflag|]. split; [intros mw Hin; destruct Hin|reflexivity]. + simpl. pose proof (update_AES_MidWord_spec tm ms0 mw SI HSI) as Hpf. destruct (update_AES_MidWord tm ms0 mw SI) as [[q' SI'] flag'] eqn:Ews. destruct Hpf as [HSI' Hpf_imp]. pose proof (IH q' SI' (andb flag flag') HSI') as IHres. destruct (update_AES tm q' SI' (andb flag flag') n0) as [[SI'' flag''] n1]. destruct IHres as [HSI'' IH_imp]. split; [exact HSI''|]. intro Hflag''. destruct (IH_imp Hflag'') as [Handb [Hmw_in HSI'eq]]. apply Bool.andb_true_iff in Handb. destruct Handb as [Hflag_true Hflag'_true]. destruct (Hpf_imp Hflag'_true) as [Hq'eq [HSIeq Hib]]. subst q'. split; [exact Hflag_true|]. split. * intros mw0 Hin. destruct Hin as [Hmw0eq | Hin0]. -- subst mw0. exact Hib. -- rewrite HSIeq in Hmw_in. exact (Hmw_in mw0 Hin0). * rewrite <- HSIeq. exact HSI'eq. Qed.
Lemma verify_loop1_spec tm h1 h2 ls1 ls2 n d: (exists h0 ls0 n0 n1, sidpos_history_WF tm h0 ls0 /\ (h1::ls1) = skipn n0 (h0::ls0) /\ (h2::ls2) = skipn (S n1) (h1::ls1) /\ sidpos_history_period h0 ls0 n0 (S n1) /\ n0+n=(S n1)) -> verify_loop1 h1 h2 ls1 ls2 n d = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. gd ls2. gd h2. gd h1. gd n. induction ls1; intros. - cbn in H0. destruct h1,h2. repeat rewrite andb_shortcut_spec in H0. repeat rewrite Bool.andb_true_iff in H0. repeat rewrite orb_shortcut_spec in H0. repeat rewrite Bool.orb_true_iff in H0. destruct H0 as [H0a [H0b [H0c _]]]. destruct H as [h0 [ls0 [N [T [Ha [Hb [Hc [Hd He]]]]]]]]. destruct n; cg. cbn in Hc. rewrite skipn_nil in Hc. invst Hc. - cbn in H0. destruct h1,h2. repeat rewrite andb_shortcut_spec in H0. repeat rewrite Bool.andb_true_iff in H0. repeat rewrite orb_shortcut_spec in H0. repeat rewrite Bool.orb_true_iff in H0. destruct H0 as [H0a [H0b H0c]]. destruct H as [h0 [ls0 [N [T [Ha [Hb [Hc [Hd He]]]]]]]]. St_eq_dec (s l0) (s l1); cg. Σ_eq_dec (m l0) (m l1); cg. clrs. destruct ls2 as [|h2' ls2']; cg. + destruct H0c as [H0c|H0c]; cg. destruct n; cg. epose proof (sidpos_history_period_S Hb Hc Hd H H0). assert (N=S T) by lia; subst. eapply loop1_nonhalt'; eauto 1. + destruct H0c as [H0c|H0c]. * destruct n; cg. epose proof (sidpos_history_period_S Hb Hc Hd H H0). assert (N=S T) by lia; subst. eapply loop1_nonhalt'; eauto 1. * destruct n; cbn in H0c. { eapply IHls1; eauto 1. destruct ls0 as [|h0' ls0']. 1: destruct N; [lia | cbn in Hb; rewrite skipn_nil in Hb; invst Hb]. exists h0'. exists ls0'. exists N. exists T. repeat split; auto 1; try lia. 2,3: eapply skipn_S'; eauto 1. 1: eapply sidpos_history_WF_cdr,Ha. destruct N as [|N]. 1: lia. epose proof (sidpos_history_period_S' Hd) as Hd'. clear Hd. cbn in Hb. eapply sidpos_history_period_S; eauto 1. } { eapply IHls1; eauto 1. exists h0. exists ls0. exists (S N). exists T. repeat split; auto 1; try lia. 1,2: eapply skipn_S; eauto 1. apply (sidpos_history_period_S Hb Hc Hd H H0). } Qed.
Lemma verify_loop1_spec tm h1 h2 ls1 ls2 n d: (exists h0 ls0 n0 n1, sidpos_history_WF tm h0 ls0 /\ (h1::ls1) = skipn n0 (h0::ls0) /\ (h2::ls2) = skipn (S n1) (h1::ls1) /\ sidpos_history_period h0 ls0 n0 (S n1) /\ n0+n=(S n1)) -> verify_loop1 h1 h2 ls1 ls2 n d = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. revert h1 h2 ls2 n d. induction ls1 as [|h1a ls1a IH]; intros h1 h2 ls2 n d Hex HVm. - destruct Hex as [h0 [ls0 [n0 [n1 [HWhp [Hskip1 [Hskip2 [HK4ro Hn]]]]]]]]. exfalso. assert (Hnil: skipn (S n1) (h1 :: nil) = @nil (ListES * Z)). { destruct n1; simpl; reflexivity. } rewrite Hnil in Hskip2. discriminate. - destruct Hex as [h0 [ls0 [n0 [n1 [HWhp [Hskip1 [Hskip2 [HK4ro Hn]]]]]]]]. destruct h1 as [es1 d1]. destruct h2 as [es2 d2]. simpl in HVm. destruct (St_eqb (s es1) (s es2)) eqn:Elav; [|discriminate]. pose proof (St_eqb_spec (s es1) (s es2)) as Hs; rewrite Elav in Hs. destruct (Σ_eqb (m es1) (m es2)) eqn:Eeqb; [|discriminate]. pose proof (Σ_eqb_spec (m es1) (m es2)) as Hm; rewrite Eeqb in Hm. destruct (match n with | O => match d with | Z0 => (d2 =? d1)%Z | Z.pos _ => match r es2 with nil => (d2 <? d1)%Z | _ :: _ => false end | Z.neg _ => match l es2 with nil => (d1 <? d2)%Z | _ :: _ => false end end | S _ => false end) eqn:Ebase. + destruct n as [|n']; [|discriminate]. assert (Hn0: n0 = S n1) by lia. subst n0. assert (HK4ro': sidpos_history_period h0 ls0 (S (S n1)) (S n1)). { eapply sidpos_history_period_S; eauto. } eapply (loop1_nonhalt' tm es1 es2 d1 d2 h0 ls0 (h1a::ls1a) ls2 n1 d); eauto. + destruct ls2 as [|h2a ls2a]; [discriminate|]. destruct n as [|n']. * (* n=0: use verify_loop1_nonhalt_n0 *) assert (Hn0: n0 = S n1) by lia. subst n0. assert (HK4ro': sidpos_history_period h0 ls0 (S (S n1)) (S n1)). { eapply sidpos_history_period_S; eauto. } eapply (verify_loop1_nonhalt_n0 tm h0 ls0 h1a h2a ls1a ls2a (S (S n1)) n1 d). -- exact HWhp. -- exact (skipn_S Hskip1). -- exact (skipn_S' Hskip2). -- exact HK4ro'. -- lia. -- exact HVm. * (* n=S n': use IH *) eapply IH; eauto. exists h0, ls0, (S n0), n1. repeat split; auto. -- exact (skipn_S Hskip1). -- exact (skipn_S' Hskip2). -- eapply sidpos_history_period_S; eauto. -- simpl. lia. Qed.
Lemma xset_WF_1 xs x1 v: xset_WF xs -> PositiveMap.find (listΣ_enc x1) xs = Some v -> set_WF Σ_enc v.
Proof. unfold xset_WF. intros. unfold xset_in in H. unfold set_WF. intro x2. specialize (H x1 x2). destruct x1 as [|h t]; cbn in H. 2: rewrite pop_back'__push_back in H. 1,2: rewrite H0 in H; apply H. Qed.
Lemma xset_WF_1 xs x1 v: xset_WF xs -> PositiveMap.find (listΣ_enc x1) xs = Some v -> set_WF Σ_enc v.
Proof. intros Hxs Hfind. unfold set_WF. intro x2. specialize (Hxs x1 x2). rewrite Hfind in Hxs. pose proof (xset_in_unfold xs x1 x2) as Hunf. rewrite Hfind in Hunf. split. - intro Hvji. apply Hxs. apply Hunf. exact Hvji. - intro Hin. apply Hunf. apply Hxs. exact Hin. Qed.
Lemma xset_WF_2 xs x1 v': xset_WF xs -> set_WF Σ_enc v' -> xset_WF (PositiveMap.add (listΣ_enc x1) v' xs).
Proof. unfold xset_WF,xset_in,set_WF. intros. destruct x0 as [|h t]; cbn. - specialize (H nil x2). cbn in H. rewrite PositiveMapAdditionalFacts.gsspec. destruct (PositiveMap.E.eq_dec (listΣ_enc nil)); auto 1. - rewrite pop_back'__push_back. specialize (H (h::t) x2). cbn in H. rewrite pop_back'__push_back in H. rewrite PositiveMapAdditionalFacts.gsspec. destruct (PositiveMap.E.eq_dec (listΣ_enc (h :: t))); auto 1. Qed.
Lemma xset_WF_2 xs x1 v': xset_WF xs -> set_WF Σ_enc v' -> xset_WF (PositiveMap.add (listΣ_enc x1) v' xs).
Proof. intros Hxs Hv'. unfold xset_WF. intros y1 y2. pose proof (xset_in_unfold (PositiveMap.add (listΣ_enc x1) v' xs) y1 y2) as Hunf. destruct (Pos.eq_dec (listΣ_enc y1) (listΣ_enc x1)) as [Heq|Hneq]. - rewrite Heq in Hunf. rewrite PositiveMap.gss in Hunf. rewrite Heq. rewrite PositiveMap.gss. split. + intro Hd. apply Hv'. apply Hunf. exact Hd. + intro Hin. apply Hunf. apply Hv'. exact Hin. - rewrite PositiveMap.gso in Hunf by exact Hneq. rewrite PositiveMap.gso by exact Hneq. destruct (PositiveMap.find (listΣ_enc y1) xs) as [v0|] eqn:Efind. + pose proof (xset_WF_1 xs y1 v0 Hxs Efind) as Hv0. split. * intro Hd. apply Hv0. apply Hunf. exact Hd. * intro Hin. apply Hunf. apply Hv0. exact Hin. + exact Hunf. Qed.
Lemma xset_WF_empty: (xset_WF (PositiveMap.empty (list Σ * PositiveMap.tree unit))).
Proof. unfold xset_WF. intros. unfold xset_in. destruct x1; cbn; rewrite PositiveMap.gempty. 2: rewrite pop_back'__push_back. 2: rewrite PositiveMap.gempty. 1,2: tauto. Qed.
Lemma xset_WF_empty: (xset_WF (PositiveMap.empty (list Σ * PositiveMap.tree unit))).
Proof. unfold xset_WF. intros x1 x2. unfold xset_in. destruct (x1 ++ x2 :: nil) as [|h t] eqn:Eht. - destruct x1; simpl in Eht; discriminate. - destruct (pop_back' h t) as [a b]. repeat rewrite PositiveMap.gempty. tauto. Qed.
Lemma xset_as_list_spec xs x1 x2: xset_WF xs -> xset_in xs (x1 ++ x2 :: nil) -> In x2 (xset_as_list xs x1).
Proof. intros. unfold xset_WF in H. unfold xset_in in H0. unfold xset_as_list. destruct x1 as [|h t]. - specialize (H nil x2). assert (H1:nil++x2::nil = (x2::nil)) by reflexivity. rewrite H1 in H,H0. unfold pop_back' in H0. destruct (PositiveMap.find (listΣ_enc nil) xs) as [v|] eqn:E. 2: contradiction. rewrite <-H. unfold xset_in. unfold pop_back'. rewrite E. apply H0. - specialize (H (h::t) x2). assert (H1:(h::t)++x2::nil = h::(t++x2::nil)) by reflexivity. rewrite H1 in H,H0. rewrite pop_back'__push_back in H0. destruct (PositiveMap.find (listΣ_enc (h :: t)) xs) as [v|] eqn:E. 2: contradiction. rewrite <-H. cbn. rewrite pop_back'__push_back,E. apply H0. Qed.
Lemma xset_as_list_spec xs x1 x2: xset_WF xs -> xset_in xs (x1 ++ x2 :: nil) -> In x2 (xset_as_list xs x1).
Proof. intros Hxs Hd. unfold xset_WF in Hxs. specialize (Hxs x1 x2). apply Hxs in Hd. unfold xset_as_list. destruct (PositiveMap.find (listΣ_enc x1) xs) as [v|]; [exact Hd | destruct Hd]. Qed.
Lemma xset_ins_spec xs h t xs' flag: xset_WF xs -> xset_ins xs (h :: t) = (xs', flag) -> (xset_WF xs' /\ (flag=true -> (xs'=xs /\ xset_in xs (h :: t)))).
Proof. intros. cbn in H0. destruct (pop_back' h t) as [x1 x2] eqn:E. destruct (PositiveMap.find (listΣ_enc x1) xs) as [v|] eqn:E0. - unfold xset_ins0 in H0. destruct (set_ins Σ_enc v x2) as [v' flag0] eqn:E1. invst H0. clear H0. assert (W0:set_WF Σ_enc v). { eapply xset_WF_1. + apply H. + apply E0. } destruct (set_ins_spec _ Σ_enc_inj _ _ _ _ W0 E1) as [H0a H0b]. split. 1: apply xset_WF_2; assumption. intro; subst. specialize (H0b eq_refl). destruct H0b; subst. split. 1: apply PositiveMapAdditionalFacts.gsident,E0. cbn. rewrite E,E0. assumption. - unfold xset_ins0 in H0. destruct (set_ins Σ_enc (nil, PositiveMap.empty unit)) as [v' flag0] eqn:E1. invst H0. clear H0. destruct (set_ins_spec _ Σ_enc_inj _ _ _ _ (empty_set_WF Σ_enc) E1) as [H0a H0b]. split. 1: apply xset_WF_2; assumption. intro; subst. specialize (H0b eq_refl). destruct H0b; subst. unfold set_ins in E1. cbn in E1. rewrite PositiveMap.gempty in E1. invst E1. Qed.
Lemma xset_ins_spec xs h t xs' flag: xset_WF xs -> xset_ins xs (h :: t) = (xs', flag) -> (xset_WF xs' /\ (flag=true -> (xs'=xs /\ xset_in xs (h :: t)))).
Proof. intros Hxs Heq. unfold xset_ins in Heq. destruct (pop_back' h t) as [x1 x2] eqn:Edec. destruct (PositiveMap.find (listΣ_enc x1) xs) as [v|] eqn:Efind. - unfold xset_ins0 in Heq. destruct (set_ins Σ_enc v x2) as [v' flag'] eqn:Etr. inversion Heq as [[Hxs' Hflag]]. subst xs' flag. pose proof (xset_WF_1 xs x1 v Hxs Efind) as Hvlnt. pose proof (set_ins_spec Σ_enc Σ_enc_inj v x2 v' flag' Hvlnt Etr) as [Hv'lnt Hflag']. split. + apply xset_WF_2; assumption. + intro Htrue. destruct (Hflag' Htrue) as [Hveq Hvji]. subst v'. rewrite PositiveMap_add_find_eq by exact Efind. split; [reflexivity|]. unfold xset_in. rewrite Edec. rewrite Efind. exact Hvji. - unfold xset_ins0 in Heq. destruct (set_ins Σ_enc (nil, PositiveMap.empty unit) x2) as [v' flag'] eqn:Etr. inversion Heq as [[Hxs' Hflag]]. subst xs' flag. pose proof (empty_set_WF Σ_enc) as Hempty. pose proof (set_ins_spec Σ_enc Σ_enc_inj _ x2 v' flag' Hempty Etr) as [Hv'lnt Hflag']. split. + apply xset_WF_2; assumption. + intro Htrue. destruct (Hflag' Htrue) as [Hveq Hvji]. subst v'. unfold set_in in Hvji. simpl in Hvji. rewrite PositiveMap.gempty in Hvji. discriminate. Qed.
Lemma xset_matches_mov_upd_1 t ls d o len: xset_matches t ls d len -> xset_matches (mov Σ (upd Σ t o) d) ls d len.
Proof. unfold xset_matches. intros. assert (1<1+n) as H1 by lia. specialize (H (1+n) H1). destruct H as [ls0 [Ha Hb]]. exists ls0. split. 1: assumption. rewrite Hb. destruct (tape_seg_spec t (Z.of_nat (1 + n) * Dir_to_Z d) d len) as [H0a H0b]. destruct (tape_seg_spec (mov Σ (upd Σ t o) d) (Z.of_nat n * Dir_to_Z d) d len) as [H1a H1b]. apply list_eq__nth_error. 1: lia. rewrite H0b. intros. rewrite H0a. 2: assumption. rewrite H1a. 2: assumption. f_equal. unfold mov,upd. assert (H2:(Z.of_nat n * Dir_to_Z d + Dir_to_Z d * Z.of_nat n0 + Dir_to_Z d <> 0)%Z). { destruct d; unfold Dir_to_Z; lia. } rewrite <-Z.eqb_neq in H2. rewrite H2. f_equal. lia. Qed.
Lemma xset_matches_mov_upd_1 t ls d o len: xset_matches t ls d len -> xset_matches (mov Σ (upd Σ t o) d) ls d len.
Proof. unfold xset_matches. intros H n Hn. destruct (H (S n) ltac:(lia)) as [xs [Hxs Heq]]. exists xs. split; [exact Hxs|]. rewrite Heq. replace (Z.of_nat (S n) * Dir_to_Z d)%Z with (Z.of_nat n * Dir_to_Z d + Dir_to_Z d)%Z by (rewrite Nat2Z.inj_succ; lia). rewrite tape_seg_shift. apply list_eq__nth_error. - repeat rewrite (proj2 (tape_seg_spec _ _ _ _)). reflexivity. - intros k Hk. rewrite (proj2 (tape_seg_spec _ _ _ _)) in Hk. rewrite (proj1 (tape_seg_spec _ _ _ _) k Hk). rewrite (proj1 (tape_seg_spec _ _ _ _) k Hk). f_equal. unfold mov, upd. assert (Hne: (Z.of_nat n * Dir_to_Z d + Dir_to_Z d * Z.of_nat k + Dir_to_Z d)%Z <> 0%Z). { pose proof (Zle_0_nat n). pose proof (Zle_0_nat k). destruct d; unfold Dir_to_Z; lia. } replace (Z.eqb (Z.of_nat n * Dir_to_Z d + Dir_to_Z d * Z.of_nat k + Dir_to_Z d) 0) with false by (symmetry; rewrite Z.eqb_neq; exact Hne). reflexivity. Qed.
Lemma xset_matches_mov_upd_2 t rs d o len: xset_matches t rs d len -> rs (tape_seg t (Dir_to_Z d) d len) -> xset_matches (mov Σ (upd Σ t o) (Dir_rev d)) rs d len.
Proof. unfold xset_matches. intros. destruct n. 1: lia. assert (H2:1<n\/n=1) by lia. destruct H2 as [H2|H2]. - specialize (H n H2). destruct H as [ls [Ha Hb]]. exists ls. split. 1: assumption. rewrite Hb. destruct (tape_seg_spec t (Z.of_nat n * Dir_to_Z d) d len) as [H0a H0b]. destruct (tape_seg_spec (mov Σ (upd Σ t o) (Dir_rev d)) (Z.of_nat (S n) * Dir_to_Z d) d len) as [H1a H1b]. apply list_eq__nth_error. 1: lia. rewrite H0b. intros. rewrite H0a. 2: lia. rewrite H1a. 2: lia. f_equal. unfold mov,upd. assert (H3:(Z.of_nat (S n) * Dir_to_Z d + Dir_to_Z d * Z.of_nat n0 + Dir_to_Z (Dir_rev d) <> 0)%Z) by (destruct d; unfold Dir_to_Z,Dir_rev; lia). rewrite <-Z.eqb_neq in H3. rewrite H3. f_equal. destruct d; unfold Dir_to_Z,Dir_rev; lia. - eexists. split. 1: apply H0. subst. destruct (tape_seg_spec t (Dir_to_Z d) d len) as [H0a H0b]. destruct (tape_seg_spec (mov Σ (upd Σ t o) (Dir_rev d)) (Z.of_nat 2 * Dir_to_Z d) d len) as [H1a H1b]. apply list_eq__nth_error. 1: lia. rewrite H0b. intros. rewrite H0a. 2: lia. rewrite H1a. 2: lia. f_equal. unfold mov,upd. assert (H3:((Z.of_nat 2 * Dir_to_Z d + Dir_to_Z d * Z.of_nat n + Dir_to_Z (Dir_rev d) <> 0))%Z) by (destruct d; unfold Dir_to_Z,Dir_rev; lia). rewrite <-Z.eqb_neq in H3. rewrite H3. f_equal. destruct d; unfold Dir_to_Z,Dir_rev; lia. Qed.
Lemma xset_matches_mov_upd_2 t rs d o len: xset_matches t rs d len -> rs (tape_seg t (Dir_to_Z d) d len) -> xset_matches (mov Σ (upd Σ t o) (Dir_rev d)) rs d len.
Proof. unfold xset_matches. intros H Hrs1 n Hn. destruct n as [|[|n']]; [lia|lia|]. (* n = S (S n') >= 2 *) assert (Hex: exists xs, rs xs /\ xs = tape_seg t (Z.of_nat (S n') * Dir_to_Z d) d len). { destruct n' as [|n'']. - exists (tape_seg t (Dir_to_Z d) d len). split; [exact Hrs1|]. f_equal. destruct d; unfold Dir_to_Z; simpl; lia. - apply H. lia. } destruct Hex as [xs [Hxs Heq]]. exists xs. split; [exact Hxs|]. rewrite Heq. apply list_eq__nth_error. - repeat rewrite (proj2 (tape_seg_spec _ _ _ _)). reflexivity. - intros k Hk. rewrite (proj2 (tape_seg_spec _ _ _ _)) in Hk. rewrite (proj1 (tape_seg_spec _ _ _ _) k Hk). rewrite (proj1 (tape_seg_spec _ _ _ _) k Hk). f_equal. unfold mov, upd. assert (Hne: (Z.of_nat (S (S n')) * Dir_to_Z d + Dir_to_Z d * Z.of_nat k + Dir_to_Z (Dir_rev d))%Z <> 0%Z). { pose proof (Zle_0_nat k). destruct d; unfold Dir_to_Z, Dir_rev; lia. } replace (Z.eqb (Z.of_nat (S (S n')) * Dir_to_Z d + Dir_to_Z d * Z.of_nat k + Dir_to_Z (Dir_rev d)) 0) with false by (symmetry; rewrite Z.eqb_neq; exact Hne). f_equal. destruct d; unfold Dir_to_Z, Dir_rev; lia. Qed.
Lemma Σ_enc_inj: is_inj Σ_enc.
Proof. intros x1 x2. destruct x1,x2; cbn; cg. Qed.
Lemma Σ_enc_inj: is_inj Σ_enc.
Proof. intros x1 x2. destruct x1,x2; cbn; cg. Qed.
Lemma Σ_eqb_spec i1 i2:
if Σ_eqb i1 i2 then i1=i2 else i1<>i2.
Proof. destruct i1,i2; cbn; congruence. Qed.
Lemma Σ_eqb_spec i1 i2:
if Σ_eqb i1 i2 then i1=i2 else i1<>i2.
Proof. destruct i1, i2; simpl; congruence. Qed.
Lemma Σ_history_enc_inj: is_inj Σ_history_enc.
Proof. intros x1 x2 H. destruct x1 as [a1 b1]. destruct x2 as [a2 b2]. cbn in H. destruct a1,a2; invst H; f_equal; apply listStΣ_enc_inj,H1. Qed.
Lemma Σ_history_enc_inj: is_inj Σ_history_enc.
Proof. unfold is_inj. intros [a0 a1] [b0 b1] H. unfold Σ_history_enc in H. destruct a0, b0; try discriminate; inversion H; f_equal; apply listStΣ_enc_inj; assumption. Qed.
Lemma Σ_list_spec: forall s, In s Σ_list.
Proof. intro s. destruct s; cbn; tauto. Qed.
Lemma Σ_list_spec: forall s, In s Σ_list.
Proof. destruct s; simpl; auto. Qed.
Not in original file
Lemma PositiveMap_add_find_eq{A} k (v:A) m: PositiveMap.find k m = Some v -> PositiveMap.add k v m = m.
Proof. revert m. induction k; intros m Hfind; destruct m as [|l o r]; simpl in *; try discriminate. - rewrite (IHk r Hfind). reflexivity. - rewrite (IHk l Hfind). reflexivity. - inversion Hfind. subst. reflexivity. Qed.
Not in original file
Lemma RepW_prepend wv mc ic fh: RepW_match {|w:=wv; min_cnt:=mc; is_const:=ic|} fh -> RepW_match {|w:=wv; min_cnt:=S mc; is_const:=ic|} (wv ++ fh).
Proof. intro H. destruct ic. - apply RepW_match_S0. exact H. - remember {|w:=wv; min_cnt:=mc; is_const:=false|} as v eqn:Ev. destruct H; inversion Ev; subst; clear Ev. apply (RepW_match_S1 wv (wv ++ w1) (S mc) (S n0)); [lia|]. apply RepW_match_S0. exact H0. Qed.
Not in original file
Lemma RepW_weaken wv mc mc' ic fh: RepW_match {|w:=wv; min_cnt:=mc; is_const:=ic|} fh -> mc' <= mc -> RepW_match {|w:=wv; min_cnt:=mc'; is_const:=false|} fh.
Proof. intros H Hle. destruct ic. - apply (RepW_match_S1 wv fh mc' mc); [lia|exact H]. - remember {|w:=wv; min_cnt:=mc; is_const:=false|} as v eqn:Ev. destruct H; inversion Ev; subst; clear Ev. apply (RepW_match_S1 wv w1 mc' n0); [lia|exact H0]. Qed.
Not in original file
Lemma Steps_le {tm m n st st0}: m <= n -> Steps tm n st st0 -> exists stm, Steps tm m st stm.
Proof. revert m st st0. induction n; intros m st st0 Hle Hn. - assert (m = 0) by lia. subst. exists st0. exact Hn. - destruct (Nat.eq_dec m (S n)). + subst. exists st0. exact Hn. + assert (Hle': m <= n) by lia. inversion Hn; subst. eapply IHn; eassumption. Qed.
Not in original file
Lemma Steps_swap_fwd tm n st st0: Steps (TM_swap tm) n st st0 -> Steps tm n (ExecState_swap st) (ExecState_swap st0).
Proof. intro H. remember (TM_swap tm) as tm0. induction H as [|tm1 n0 sta stb stc Hsteps IH Hstep]; subst. - constructor. - apply step_swap in Hstep. eapply steps_S; [apply IH; reflexivity | exact Hstep]. Qed.
Not in original file
Lemma append_inj a1 a2 b1 b2: positive_len a1 = positive_len a2 -> append a1 b1 = append a2 b2 -> a1 = a2 /\ b1 = b2.
Proof. revert a2 b1 b2. induction a1; destruct a2; simpl; intros; try congruence; try lia. - injection H0 as H0'. apply IHa1 in H0'. destruct H0'; subst; auto. lia. - injection H0 as H0'. apply IHa1 in H0'. destruct H0'; subst; auto. lia. Qed.
Not in original file
Lemma enc_pair_not_xH : forall p, enc_pair p <> xH.
Proof. intros [x1 x2]. unfold enc_pair. destruct (enc_v1 (Pos.of_succ_nat (positive_len x1))) eqn:E; simpl; discriminate. Qed.
Not in original file
Lemma nil_match wv fh: RepW_match {|w:=wv; min_cnt:=0; is_const:=true|} fh -> fh = nil.
Proof. intro H. remember {|w:=wv; min_cnt:=0; is_const:=true|} as v eqn:Ev. destruct H; inversion Ev; subst. reflexivity. Qed.
Not in original file
Lemma nth_Sigma0_nil (n:nat): nth n (@nil Σ) Σ0 = nth n (Σ0 :: @nil Σ) Σ0.
Proof. destruct n as [|[|n']]; reflexivity. Qed.
Not in original file
Lemma nth_shift_eq (n1 n2:nat) (a b c:Σ) (tl:list Σ): n1 >= 1 -> n2 >= 2 -> n1 - 1 = n2 - 2 -> nth n1 (a :: tl) Σ0 = nth n2 (b :: c :: tl) Σ0.
Proof. intros. destruct n1 as [|n1']; [lia|]. destruct n2 as [|[|n2']]; try lia. simpl. replace n1' with n2' by lia. reflexivity. Qed.
Not in original file
Lemma pos_to_nat_pred_double (p:positive): Pos.to_nat (Pos.pred_double p) = 2 * Pos.to_nat p - 1.
Proof. rewrite Pos.pred_double_spec. assert ((1 < p~0)%positive) by lia. rewrite (Pos2Nat.inj_pred _ H). rewrite Pos2Nat.inj_xO. lia. Qed.
Not in original file
Lemma q_200_WF_step q: SearchQueue_WF (N.to_nat BB) q root -> SearchQueue_WF (N.to_nat BB) (q_suc q) root.
Proof. intro H. unfold q_suc. apply SearchQueue_upds_spec. exact H. exact decider_all_spec. Qed.
Not in original file
Lemma q_200_WF_steps n q: SearchQueue_WF (N.to_nat BB) q root -> SearchQueue_WF (N.to_nat BB) (Nat.iter n q_suc q) root.
Proof. induction n as [|n' IH]. - exact (fun h => h). - intro H. simpl. apply q_200_WF_step. apply IH. exact H. Qed.
Not in original file
Lemma sidpos_history_WF_skipn tm h ls h' ls' p: sidpos_history_WF tm h ls -> h'::ls' = skipn p (h::ls) -> sidpos_history_WF tm h' ls'.
Proof. revert h ls. induction p; intros h ls Hwhp Hskip. - simpl in Hskip. injection Hskip; intros; subst. exact Hwhp. - simpl in Hskip. destruct ls as [|h1 ls1]. + rewrite skipn_nil in Hskip. discriminate. + eapply IHp; [exact (sidpos_history_WF_cdr _ _ _ _ Hwhp)|exact Hskip]. Qed.
Not in original file
Lemma sidpos_history_period_skipn h0 ls0 h ls p N T: sidpos_history_period h0 ls0 (p + N) T -> h::ls = skipn p (h0::ls0) -> sidpos_history_period h ls N T.
Proof. unfold sidpos_history_period. intros HK Hskip n Hn. specialize (HK (p + n) ltac:(lia)). rewrite Hskip. rewrite !Coq.Lists.List.nth_error_skipn. replace (p + (T + n)) with (T + (p + n)) by lia. exact HK. Qed.
Not in original file
Lemma step_rev_fwd tm st st0: step (TM_rev tm) st = Some st0 -> step tm (ExecState_rev st) = Some (ExecState_rev st0).
Proof. destruct st as [s tape]. destruct st0 as [s0 tape0]. unfold step, TM_rev, ExecState_rev, option_Trans_rev, Trans_rev, Tape_rev. replace (tape (- 0)%Z) with (tape 0%Z) by (f_equal; lia). destruct (tm s (tape 0%Z)) as [[s' d o]|]; intro H; [|discriminate]. inversion H; subst; clear H. do 2 f_equal. extensionality x. unfold mov, upd, Tape_rev. destruct d; simpl; [ destruct (Z.eqb_spec (- x + 1)%Z 0%Z); destruct (Z.eqb_spec (x + -1)%Z 0%Z) | destruct (Z.eqb_spec (- x + -1)%Z 0%Z); destruct (Z.eqb_spec (x + 1)%Z 0%Z) ]; try reflexivity; try (f_equal; lia); exfalso; lia. Qed.
Not in original file
Lemma strip_one wv mc fh: RepW_match {|w:=wv; min_cnt:=S mc; is_const:=true|} fh -> exists tail, fh = wv ++ tail /\ RepW_match {|w:=wv; min_cnt:=mc; is_const:=true|} tail.
Proof. intro H. remember {|w:=wv; min_cnt:=S mc; is_const:=true|} as v eqn:Ev. destruct H; inversion Ev; subst. exists w1. split; [reflexivity|exact H]. Qed.
Not in original file
Lemma tape_eq m0 w2 (ft l1:nat->Σ) sgn0: make_tape'' l1 nil (app_halftape (m0::w2) ft) sgn0 = make_tape'' l1 (m0::w2) ft sgn0.
Proof. unfold make_tape''. replace ((app_halftape (m0 :: w2) ft) 0) with m0 by (unfold app_halftape; simpl; reflexivity). rewrite <- app_halftape_skipn_cdr. change (S (length w2)) with (length (m0::w2)). rewrite app_halftape_skipn. destruct sgn0. - rewrite make_tape'_split_l. simpl app. reflexivity. - rewrite make_tape'_split_r. simpl app. reflexivity. Qed.
Not in original file
Lemma tape_seg_shift t x y d len: tape_seg t (x + y)%Z d len = tape_seg (fun z => t (z + y)%Z) x d len.
Proof. revert x. induction len as [|len' IH]; intros x. - simpl. reflexivity. - simpl. f_equal. rewrite <- (IH (x + Dir_to_Z d)%Z). f_equal. lia. Qed.
Not in original file
Lemma verify_loop1_nonhalt_n0 tm h0 ls0 h1 h2 ls1 ls2 N T d: sidpos_history_WF tm h0 ls0 -> (h1::ls1) = skipn N (h0::ls0) -> (h2::ls2) = skipn (S T) (h1::ls1) -> sidpos_history_period h0 ls0 N (S T) -> N >= S (S T) -> verify_loop1 h1 h2 ls1 ls2 0 d = true -> ~ HaltsFromInit Σ Σ0 tm.
Proof. revert h1 h2 ls2 N. induction ls1 as [|h1a ls1a IH]; intros h1 h2 ls2 N HWhp Hskip1 Hskip2 HK4ro HNge HVm. - exfalso. assert (Hnil: skipn (S T) (h1 :: nil) = @nil (ListES * Z)). { destruct T; simpl; reflexivity. } rewrite Hnil in Hskip2. discriminate. - destruct h1 as [es1 d1]. destruct h2 as [es2 d2]. simpl in HVm. destruct (St_eqb (s es1) (s es2)) eqn:Elav; [|discriminate]. pose proof (St_eqb_spec (s es1) (s es2)) as Hs; rewrite Elav in Hs. destruct (Σ_eqb (m es1) (m es2)) eqn:Eeqb; [|discriminate]. pose proof (Σ_eqb_spec (m es1) (m es2)) as Hm; rewrite Eeqb in Hm. destruct (match d with | Z0 => (d2 =? d1)%Z | Z.pos _ => match r es2 with nil => (d2 <? d1)%Z | _ :: _ => false end | Z.neg _ => match l es2 with nil => (d1 <? d2)%Z | _ :: _ => false end end) eqn:Ebase. + assert (HK4ro': sidpos_history_period h0 ls0 (S N) (S T)). { eapply sidpos_history_period_S; eauto. } set (p := N - S T). destruct (skipn p (h0::ls0)) as [|h_mid ls_mid] eqn:Hskip_mid. * exfalso. assert (h1_eq: (es1,d1)::h1a::ls1a = skipn (S T) (skipn p (h0::ls0))). { rewrite skipn_skipn. replace (S T + p) with N by (unfold p; lia). exact Hskip1. } rewrite Hskip_mid in h1_eq. destruct T; simpl in h1_eq; discriminate. * symmetry in Hskip_mid. eapply (loop1_nonhalt' tm es1 es2 d1 d2 h_mid ls_mid (h1a::ls1a) ls2 T d). -- eapply sidpos_history_WF_skipn; eauto. -- eapply sidpos_history_period_skipn with (p := p). ++ replace (p + S (S T)) with (S N) by (unfold p; lia). exact HK4ro'. ++ exact Hskip_mid. -- rewrite Hskip_mid. rewrite skipn_skipn. replace (S T + p) with N by (unfold p; lia). exact Hskip1. -- exact Hskip2. -- exact Ebase. + destruct ls2 as [|h2a ls2a]; [discriminate|]. eapply (IH h1a h2a ls2a (S N)). * exact HWhp. * exact (skipn_S Hskip1). * exact (skipn_S' Hskip2). * eapply sidpos_history_period_S; eauto. * lia. * exact HVm. Qed.
Not in original file
Lemma xset_in_unfold xs y1 y2: xset_in xs (y1 ++ y2 :: nil) <-> match PositiveMap.find (listΣ_enc y1) xs with | Some v => set_in Σ_enc v y2 | None => False end.
Proof. unfold xset_in. destruct y1 as [|h t]. - simpl. tauto. - change ((h :: t) ++ y2 :: nil) with (h :: (t ++ y2 :: nil)). cbv beta iota. rewrite pop_back'__push_back. tauto. Qed.