Section MM2_ndMM2.
Notation STOP := (@ndmm2_stop _).
Notation INC  := (@ndmm2_inc _).
Notation DEC  := (@ndmm2_dec _).
Notation ZERO := (@ndmm2_zero _).
Notation α := true.
Notation β := false.
Definition mm2_instr_enc i ρ :=
match ρ with
| mm2_inc_a   => INC α i (1+i) :: nil
| mm2_inc_b   => INC β i (1+i) :: nil
| mm2_dec_a j => DEC α i j :: ZERO true  i (1+i) :: nil
| mm2_dec_b j => DEC β i j :: ZERO false i (1+i) :: nil
end.
Fixpoint mm2_linstr_enc i l :=
match l with
| nil => nil
| ρ::l => mm2_instr_enc i ρ ++ mm2_linstr_enc (1+i) l
end.
Fact mm2_linstr_enc_app i l m : mm2_linstr_enc i (l++m) = mm2_linstr_enc i l ++ mm2_linstr_enc (length l+i) m.
Fact mm2_linstr_enc_In i P c :
In c (mm2_linstr_enc i P)
-> exists l r ρ, P = l++ρ::r /\ In c (mm2_instr_enc (length l+i) ρ).
Notation "Σ // a ⊕ b ⊦ u" := (ndmm2_accept Σ a b u) (at level 70, no associativity).
Local Fact mm2_instr_enc_sound Σ ρ s1 s2 :
mm2_atom ρ s1 s2
-> match s1, s2 with
| (i,(a,b)), (j,(a',b')) => incl (mm2_instr_enc i ρ) Σ
-> Σ // a' ⊕ b' ⊦ j
-> Σ // a  ⊕ b  ⊦ i
end.
Local Fact mm2_step_linstr_sound Σ P s1 s2 :
mm2_step P s1 s2
-> match s1, s2 with
| (i,(a,b)), (j,(a',b')) => incl (mm2_linstr_enc 1 P) Σ
-> Σ // a' ⊕ b' ⊦ j
-> Σ // a  ⊕ b  ⊦ i
end.
Notation "P // x ↠ y" := (clos_refl_trans _ (mm2_step P) x y) (at level 70).
Variable P : list mm2_instr.
Definition mm2_prog_enc := STOP 0 :: mm2_linstr_enc 1 P.
Notation Σ := mm2_prog_enc.
Local Lemma mm2_prog_enc_compute s1 s2 :
P // s1 ↠ s2
-> match s1, s2 with
| (i,(a,b)), (j,(a',b')) => Σ // a' ⊕ b' ⊦ j
-> Σ // a  ⊕ b  ⊦ i
end.
Local Lemma mm2_prog_enc_stop : Σ // 0 ⊕ 0 ⊦ 0.
End MM2_ndMM2.

Theorem reduction : MM2_HALTS_ON_ZERO ⪯ @ndMM2_ACCEPT nat.