(** the computation is stopped at x, no step is possible from x *)

  Definition fractran_stop l x := forall z, ~ l // x → z.Fact fractan_stop_nil_inv x : fractran_stop nil x <-> True.Fact fractan_stop_cons_inv p q l x : fractran_stop ((p,q)::l) x <-> ~ divides q (p*x) /\ fractran_stop l x.Fact fractran_step_dec l x : { y | l // x → y } + { fractran_stop l x }.Definition fractran_steps l := rel_iter (fractran_step l).Definition fractran_compute l x y := exists n, fractran_steps l n x y.Definition fractran_terminates l x := exists y, fractran_compute l x y /\ fractran_stop l y.(* The Halting problem for a FRACTRAN instance (l,x) is determining if
     there is y related via (fractran_step l)* to x and maximal for (fractran_step l) *) 

  Definition FRACTRAN_PROBLEM := (list (nat*nat) * nat)%type.Definition FRACTRAN_HALTING (P : FRACTRAN_PROBLEM) := let (l,x) := P in fractran_terminates l x.Fact fractran_step_head_not_zero p q l y : q <> 0 -> (p,q)::l // 0 → y -> y = 0.Fact fractran_rt_head_not_zero p q l n y : q <> 0 -> fractran_steps ((p,q)::l) n 0 y -> y = 0.

Lemma FRACTRAN_HALTING_on_zero_first_no_zero_den p q l : q <> 0 -> FRACTRAN_HALTING ((p,q)::l,0) <-> False.