(* This file is generated by Why3's Coq driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.
Require int.Int.
Require list.List.
Require list.Length.
Require list.Mem.
Require list.Append.
Require list.Reverse.

(* Why3 assumption *)
Definition unit := unit.

(* Why3 assumption *)
Inductive tree :=
  | Leaf : tree
  | Node : tree -> tree -> tree.
Axiom tree_WhyType : WhyType tree.
Existing Instance tree_WhyType.

(* Why3 assumption *)
Fixpoint depths (d:Z) (t:tree) {struct t}: (list Z) :=
  match t with
  | Leaf => (Init.Datatypes.cons d Init.Datatypes.nil)
  | (Node l r) => (Init.Datatypes.app (depths (d + 1%Z)%Z
      l) (depths (d + 1%Z)%Z r))
  end.

Axiom depths_head : forall (t:tree) (d:Z), match (depths d
  t) with
  | (Init.Datatypes.cons x _) => (d <= x)%Z
  | Init.Datatypes.nil => False
  end.

Axiom depths_unique : forall (t1:tree) (t2:tree) (d:Z) (s1:(list Z))
  (s2:(list Z)), ((Init.Datatypes.app (depths d
  t1) s1) = (Init.Datatypes.app (depths d t2) s2)) -> ((t1 = t2) /\
  (s1 = s2)).

Axiom depths_prefix : forall (t:tree) (d1:Z) (d2:Z) (s1:(list Z))
  (s2:(list Z)), ((Init.Datatypes.app (depths d1
  t) s1) = (Init.Datatypes.app (depths d2 t) s2)) -> (d1 = d2).

Axiom depths_prefix_simple : forall (t:tree) (d1:Z) (d2:Z), ((depths d1
  t) = (depths d2 t)) -> (d1 = d2).

Axiom depths_subtree : forall (t1:tree) (t2:tree) (d1:Z) (d2:Z)
  (s1:(list Z)), ((Init.Datatypes.app (depths d1 t1) s1) = (depths d2 t2)) ->
  (d2 <= d1)%Z.

Axiom depths_unique2 : forall (t1:tree) (t2:tree) (d1:Z) (d2:Z), ((depths d1
  t1) = (depths d2 t2)) -> ((d1 = d2) /\ (t1 = t2)).

(* Why3 assumption *)
Fixpoint forest_depths (f:(list (Z* tree)%type)) {struct f}: (list Z) :=
  match f with
  | Init.Datatypes.nil => Init.Datatypes.nil
  | (Init.Datatypes.cons (d, t) r) => (Init.Datatypes.app (depths d
      t) (forest_depths r))
  end.

Axiom forest_depths_append : forall (f1:(list (Z* tree)%type)) (f2:(list (Z*
  tree)%type)),
  ((forest_depths (Init.Datatypes.app f1 f2)) = (Init.Datatypes.app (forest_depths f1) (forest_depths f2))).

(* Why3 assumption *)
Fixpoint greedy (d:Z) (d1:Z) (t1:tree) {struct t1}: Prop := (~ (d = d1)) /\
  match t1 with
  | Leaf => True
  | (Node l1 _) => (greedy d (d1 + 1%Z)%Z l1)
  end.

(* Why3 assumption *)
Inductive g: (list (Z* tree)%type) -> Prop :=
  | Gnil : (g Init.Datatypes.nil)
  | Gone : forall (d:Z) (t:tree), (g (Init.Datatypes.cons (d,
      t) Init.Datatypes.nil))
  | Gtwo : forall (d1:Z) (d2:Z) (t1:tree) (t2:tree) (l:(list (Z*
      tree)%type)), (greedy d1 d2 t2) -> ((g (Init.Datatypes.cons (d1,
      t1) l)) -> (g (Init.Datatypes.cons (d2, t2) (Init.Datatypes.cons (d1,
      t1) l)))).

Require Import Why3. 
Ltac z := why3 "Z3,4.4.0," timelimit 5;admit.

(* Why3 goal *)
Theorem g_append : forall (l1:(list (Z* tree)%type)) (l2:(list (Z*
  tree)%type)), (g (Init.Datatypes.app l1 l2)) -> (g l1).
(* Why3 intros l1 l2 h1. *)
induction l1; simpl.
z.
intros l2.
change (cons a (app l1 l2)) with (app (cons a l1) l2).
inversion 1.
z.
assert (g l1) by z.
destruct l1.
z.
destruct p.
apply Gtwo; auto.
simpl in H1.
z.
Admitted.

