(**************************************************************)
(*   Copyright Dominique Larchey-Wendling [*]                 *)
(*                                                            *)
(*                             [*] Affiliation LORIA -- CNRS  *)
(**************************************************************)
(*      This file is distributed under the terms of the       *)
(*         CeCILL v2 FREE SOFTWARE LICENSE AGREEMENT          *)
(**************************************************************)
(** ** Definition of FRACTRAN *)
Set Implicit Arguments.
Section fractran.
Implicit Type (l : list (nat*nat)).
(** One step of a Fractran program computation. Notice that the two rule are INCOMPATIBLE, making the computation deterministic (except) when (_,0) belongs to l *)
Reserved Notation "l '//' x → y" (at level 70, no associativity).
Inductive fractran_step : list (nat*nat) -> nat -> nat -> Prop :=
| in_ft_0 : forall p q l x y, q*y = p*x -> (p,q)::l // x → y
| in_ft_1 : forall p q l x y, ~ divides q (p*x) -> l // x → y -> (p,q)::l // x → y
where "l // x → y" := (fractran_step l x y).
Definition fractran_regular l := Forall (fun c => snd c <> 0) l.
Fact fractran_step_nil_inv x y : nil // x → y <-> False.
Fact mul_pos_inj_l q x y : q <> 0 -> q*x = q*y -> x = y.

(* Specifications: *)
Lemma fractran_step_inv P x y :
P // x → y
-> exists l p q r, P = l++(p,q)::r
/\ (forall u v, In (u,v) l -> ~ divides v (u*x))
/\ q*y=p*x.