(** The divisibility results are no so complicated when we do not need to show that encode_state is injective ... *)
Local Fact divides_from_eq x y t : x*y = t -> divides x t.
Local Fact prime_div_mult4 p w x y z : prime p -> divides p (w*x*y*z) -> divides p w \/ divides p x \/ divides p y \/ divides p z.
Local Hint Resolve encode_mm_instr_regular'.

(* Specifications: *)
Lemma one_step_backward m i P i1 v1 st :
@mm_no_self_loops m (i, P)
-> encode_mm_instr i P /F/ @encode_state m (i1,v1) → st
-> exists i2 v2, st = @encode_state m (i2,v2)
/\ (i, P) /MM/ (i1, v1) → (i2,v2).
Lemma steps_backward m i P i1 v1 k st :
@mm_no_self_loops m (i, P)
->               encode_mm_instr i P /F/ encode_state (i1,v1) -[k]-> st
-> exists i2 v2, (i, P) /MM/ (i1, v1) -[k]-> (i2,v2)
/\ st = encode_state (i2,v2).
Theorem mm_fractran_simulation n P v :
@mm_no_self_loops n (1, P)
-> (1,P) /MM/ (1,v) ↓ <-> encode_mm_instr 1 P /F/ ps 1 * exp 0 v ↓.
Theorem mm_fractran_n n (P : list (mm_instr n)) :
{ l |  Forall (fun c => snd c <> 0) l
/\ forall v, (1,P) /MM/ (1,v) ↓ <-> l /F/ ps 1 * exp 1 v ↓ }.
Theorem mm_fractran n (P : list (mm_instr (S n))) :
{ l | forall x, (1,P) /MM/ (1,x##vec_zero) ↓ <-> l /F/ ps 1 * qs 1^x ↓ }.