End self_loops.
Section no_self_loops.
Variables (n : nat).
Definition mm_no_self_loops (Q : nat * list (mm_instr n)) := forall i x, ~ (i,DEC x i::nil) <sc Q.
Implicit Types (P Q : list (mm_instr n)).
Fact mm_no_self_loops_app i P Q : mm_no_self_loops (i,P)
-> mm_no_self_loops (length P +i,Q)
-> mm_no_self_loops (i,P++Q).
End no_self_loops.
Section remove_self_loops.
(** To safely remove self loops from (1,P) 1/ we map them to 2+lP 2/ we map outside jumps to 0 3/ we append to P to 3 following instructions 1+lP: DEC nv 0; DEC nv 3+lP; DEC nv 2+lP  where nv is a new and unused variable *)
Variables (n : nat).
Implicit Types (P Q : list (mm_instr n)).
Let f k i (ρ : mm_instr n) :=
match ρ with
| INC x   => INC (pos_nxt x)
| DEC x j => DEC (pos_nxt x) (if eq_nat_dec i j     then 1+k
else if le_lt_dec k j then 0
else j)
end.
Let Fixpoint g k i P :=
match P with
| nil  => nil
| ρ::P => f k i ρ :: g k (S i) P
end.
Let g_app k i P Q : g k i (P++Q) = g k i P ++ g k (length P + i) Q.
Let g_app_inv k i P l r : g k i P = l ++ r -> exists L R, P = L++R /\ l = g k i L /\ r = g k (length l+i) R.
Let length_g l i P : length (g l i P) = length P.
Let subcode_g k i P j ρ : (j,ρ::nil) <sc (i,g k i P) -> exists ρ', (j,ρ'::nil) <sc (i,P) /\ ρ = f k j ρ'.
Let g_loops k i P : 1 <= i -> i+length P <= k -> mm_no_self_loops (i,g k i P).
Variable P : list (mm_instr n).
Notation lP := (length P).
Let R : list (mm_instr (S n)) := DEC pos0 0
:: DEC pos0 (3+lP)
:: DEC pos0 (2+lP)
:: nil.
Let sc_R_1 : (1+lP, DEC pos0 0 :: nil) <sc (1+lP, R).
Let R_sc i rho : (i,rho::nil) <sc (1+lP,R) -> i = 1+lP /\ rho = DEC pos0 0
\/ i = 2+lP /\ rho = DEC pos0 (3+lP)
\/ i = 3+lP /\ rho = DEC pos0 (2+lP).
Let R_no_self_loops : mm_no_self_loops (1+lP,R).
Let Q := g (1+lP) 1 P ++ R.
Let Q_no_self_loops : mm_no_self_loops (1,Q).
Let sc_Q_1 j ρ : (j,ρ::nil) <sc (1,P) -> (j, f (1+lP) j ρ::nil) <sc (1,Q).
Let Q_length : length Q = length P + 3.
Let Q_bound i x j : (i,DEC x j::nil) <sc (1,Q) -> j < 1+length Q.
Let P_imp_Q s s0 : in_code (fst s) (1,P) -> (1,P) // s ~~> s0 -> (1,Q) // (fst s, 0##snd s) ↓.
Let Q_imp_P s s0 : in_code (fst s) (1,P) -> (snd s)#>pos0 = 0 -> (1,Q) // s ~~> s0 -> (1,P) // (fst s, vec_tail (snd s)) ↓.

(* Specifications: *)
Theorem mm_remove_self_loops : { Q |  mm_no_self_loops (1,Q)
/\ (forall i x j, (i,DEC x j::nil) <sc (1,Q) -> j < 1+length Q)
/\ forall v, (1,P) // (1,v) ↓ <-> (1,Q) // (1,0##v) ↓ }.