(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)
Set Asymmetric Patterns.
Unset Standard Proposition Elimination Names.
Require Export ZArith.
Require Export Omega.
(**********************************************************************  CONFIGURATION  **********************************************************************)
Section CONFIGURATION.
Definition counter := Z.
Record Config : Set := mkconfig {co : counter}.
Variable x : Z.
Definition mk_init_config := mkconfig x.
End CONFIGURATION.
(**********************************************************************  TRANSITIONS  **********************************************************************)
Section TRANSITIONS.
Definition decrement_trans (c : Config) := mkconfig (co c - 1)%Z.
Definition divide_trans (c : Config) := mkconfig (Zeven.Zdiv2 (co c)).
Inductive transition (c : Config) : Set :=
| decrement : (co c > 0)%Z -> Zeven.Zodd (co c) -> transition c
| divide : (co c > 0)%Z -> Zeven.Zeven (co c) -> transition c.
Definition next_config (c : Config) (t : transition c) :=
match t with
| decrement h1 h2 => decrement_trans c
| divide h1 h2 => divide_trans c
end.
Variable x : Z.
Inductive legal : Config -> Prop :=
| begin : legal (mk_init_config x)
| after :
forall (c : Config) (t : transition c),
legal c -> legal (next_config c t).
End TRANSITIONS.
(* positive *)

(* Specifications: *)
Lemma Zdiv2_positive :
forall x : Z, Zeven.Zeven x -> (x >= 0)%Z -> (Zeven.Zdiv2 x >= 0)%Z.
Lemma x_gt_Zdiv2 :
forall x : Z, Zeven.Zeven x -> (x > 0)%Z -> (x > Zeven.Zdiv2 x)%Z.
Lemma counter_remains_positive_or_null :
forall (x : Z) (c : Config), (x >= 0)%Z -> legal x c -> (co c >= 0)%Z.
Lemma decreasing_measure :
forall (c : Config) (t : transition c), (co c > co (next_config c t))%Z.
Lemma liveness :
forall (x : Z) (c : Config),
legal x c ->
(co c > 0)%Z -> exists t : transition c, legal x (next_config c t).
Lemma blocked :
forall c : Config, (co c <= 0)%Z -> ~ (exists t : transition c, True).
Lemma recur2 :
forall P : nat -> Prop,
(forall n : nat, (forall p : nat, p < n -> P p) -> P n) ->
forall m : nat, P m.
Lemma natgen_ind :
forall P : Z -> Prop,
(forall x : Z,
(0 <= x)%Z -> (forall y : Z, (0 <= y)%Z -> (y < x)%Z -> P y) -> P x) ->
forall x : Z, (0 <= x)%Z -> P x.
Lemma rec2_princ :
forall P : Z -> Prop,
P 0%Z ->
(forall x : Z, Zeven.Zeven x -> (x > 0)%Z -> P (Zeven.Zdiv2 x) -> P x) ->
(forall x : Z, Zeven.Zodd x -> (x > 0)%Z -> P (x - 1)%Z -> P x) ->
forall x : Z, (x >= 0)%Z -> P x.
Lemma legal_x_x : forall x : Z, legal x (mkconfig x).
Lemma simpl_config : forall c : Config, mkconfig (co c) = c.
Lemma legal_trans :
forall (x : Z) (c c' : Config), legal x c -> legal (co c) c' -> legal x c'.
Lemma legal_decrement :
forall (x : Z) (c : Config),
(x > 0)%Z -> Zeven.Zodd x -> legal (x - 1) c -> legal x c.
Lemma legal_divide :
forall (x : Z) (c : Config),
(x > 0)%Z -> Zeven.Zeven x -> legal (Zeven.Zdiv2 x) c -> legal x c.
Lemma fin_O : forall x : Z, (x >= 0)%Z -> legal x (mkconfig 0%Z).
Lemma termination :
forall x : Z,
exists c : Config, legal x c /\ ~ (exists t : transition c, True).