(* This file was originally generated by why.
   It can be modified; only the generated parts will be overwritten. *)

Require Import Why.
Require Import Sumbool.

Require Export Match.
Require Export Next.
Require Import ZArithRing.
Require Import Omega.
Require Export Lex.

Ltac Omega' := abstract omega.

Parameter A : Set.
Axiom A_eq_dec : forall x y:A, {x = y} + {x <> y}.
Definition A_eq_bool (x y:A) := bool_of_sumbool (A_eq_dec x y).

Axiom M_positive : (0 <= M)%Z.

Proof.
intuition.
Qed.

Proof.
intros; exact lexZ_well_founded.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition.
subst i2 j2.
apply match_right_extension.
replace (i1 + 1 - (j1 + 1))%Z with (i1 - j1)%Z.
 assumption.
 Omega'.
  Omega'.
 Omega'.
  ring (i1 + 1 - (j1 + 1) + j1)%Z.
 ring (0 + j1)%Z.
 assumption.
  absurd (match_ p (i1 + 1 - (z - 1)) p 0 (z - 1)).
  red; apply H11; Omega'.
  apply match_right_weakening with (n := z).
  replace (i1 + 1 - (z - 1))%Z with (i1 + 1 + 1 - z)%Z.
  subst i2; assumption.
 Omega'.
 Omega'.
  elim (Z_lt_ge_dec k (i1 + 1)); intro Hk'.
    subst next2; rewrite store_def_2.
  apply H13; Omega'.
 Omega'.
 Omega'.
 Omega'.
  cut ((i1 + 1)%Z = k).
 intro Heq.
   subst next2 i2; rewrite Heq.
 rewrite store_def_1.
  rewrite <- Heq.
 apply Next_cons.
 Omega'.
  subst j2; replace (i1 + 1 - (j1 + 1))%Z with (i1 - j1)%Z.
  apply match_right_extension; Omega' || (try assumption).
  ring (i1 - j1 + j1)%Z; ring (0 + j1)%Z; assumption.
 Omega'.
  intros z Hz.
   red; apply H11; Omega'.
  Omega'.
 Omega'.
  ArraySubst next2.
unfold lexZ, lex, Zwf, pairZ; left; Omega'.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition.
  rewrite Test4.
  apply match_empty.
 Omega'.
 Omega'.
  elim (Z_lt_ge_dec (j1 + 2) z); intro.
  absurd (match_ p (i1 + 1 - (z - 1)) p 0 (z - 1)).
  red; apply H11; Omega'.
  apply match_right_weakening with (n := z).
  subst i2.
  replace (i1 + 1 - (z - 1))%Z with (i1 + 1 + 1 - z)%Z;
   [ assumption | Omega' ].
 Omega'.
  absurd (access p i1 = access p j1); [ assumption | idtac ].
  decompose [match_] H18.
  replace i1 with (i1 + 1 + 1 - 2 + j1)%Z; [ idtac | Omega' ].
  replace (access p j1) with (access p (0 + j1));
   [ idtac | ring (0 + j1)%Z; reflexivity ].
  cut (z = 2%Z); [ intro Heq | Omega' ].
  rewrite <- Heq.
 rewrite <- Post5; apply H22; Omega'.
  elim (Z_lt_ge_dec k (i1 + 1)); intro.
  subst next2.
 AccessOther.
  apply H13; Omega'.
   cut ((i1 + 1)%Z = k); [ intro Heq | Omega' ].
  rewrite Post6; rewrite Post5; rewrite Heq.
 AccessSame.
  rewrite <- Heq.
 apply Next_cons.
 Omega'.
  apply match_empty; Omega'.
  intros z Hz.
  elim (Z_lt_ge_dec 1 z); intro.
  (* 1 < z  *)
  red; apply H11; Omega'.
  (* z = 1 *)
  red; intro.
  absurd (access p i1 = access p j1); [ assumption | rewrite Test4 ].
  decompose [match_] H17.
  replace 0%Z with (0 + 0)%Z; [ idtac | Omega' ].
  replace i1 with (i1 + 1 - z + 0)%Z; [ idtac | Omega' ].
  apply H22; Omega'.
  ArraySubst next2.
unfold lexZ, lex, Zwf, pairZ.
 left; Omega'.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition cut (j1 <> 0%Z); [ clear Test3; intro Test3 | assumption ].
  subst j2.
  elim (H15 j1); Omega'.
  elim (H15 j1); Omega'.
  elim (H15 j1); Omega'.
  subst j2.
  apply match_trans with (t2 := p) (i2 := (j1 - access next1 j1)%Z).
  apply match_left_weakening with (n := j1).
  replace (i1 - access next1 j1 - (j1 - access next1 j1))%Z with
   (i1 - j1)%Z; [ idtac | Omega' ].
  replace (j1 - access next1 j1 - (j1 - access next1 j1))%Z with 0%Z;
   [ assumption | Omega' ].
  elim (H15 j1); Omega'.
 elim (H15 j1); auto; Omega'.

  elim (Z_lt_ge_dec (j1 + 1) z); intro.
  (* j0+1 < z < i0+1 *)
  apply (H13 z); assumption || Omega'.
  elim (Z_ge_lt_dec z (j1 + 1)); intro.
  (* z = j0+1 *)
  absurd (access p i1 = access p j1); [ assumption | idtac ].
  decompose [match_] H18.
  replace i1 with (i1 + 1 - z + j1)%Z; [ idtac | Omega' ].
  replace j1 with (0 + j1)%Z; [ idtac | Omega' ].
  apply H22; Omega'.
  (* next[j0]+1 < z < j0+1 *)
  absurd (match_ p (j1 - (z - 1)) p 0 (z - 1)).
  decompose [match_] H18.
  elim (H15 j1); Omega' || intros.
  apply H25; Omega'.
  apply match_trans with (t2 := p) (i2 := (i1 - (z - 1))%Z).
  apply match_sym.
  apply match_left_weakening with (n := j1).
  replace (i1 - (z - 1) - (j1 - (z - 1)))%Z with (i1 - j1)%Z;
   [ idtac | Omega' ].
  ring (j1 - (z - 1) - (j1 - (z - 1)))%Z.
 assumption.
  Omega'.
  apply match_right_weakening with (n := z).
  replace (i1 - (z - 1))%Z with (i1 + 1 - z)%Z; [ assumption | Omega' ].
  Omega'.
unfold lexZ, lex, Zwf, pairZ.
 elim (H15 j1); [ intros | Omega' ].
right.
 Omega'.
Qed.

Proof.
intuition.
rewrite Pre13; assumption.
Qed.

Proof.
intuition.
subst i j.
apply match_empty; Omega'.
replace k with 1%Z; [ subst next0; rewrite store_def_1 | Omega' ].
apply next_1_0; Omega'.
Omega'.
ArraySubst next0.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition.
absurd (0 < j)%Z; Omega'.
Qed.


(*Why type*) Definition farray: Set ->Set.
Admitted.

(*Why logic*) Definition access : forall (A1:Set), (array A1) -> Z -> A1.
Admitted.
Implicit Arguments access.

(*Why logic*) Definition update :
  forall (A1:Set), (array A1) -> Z -> A1 -> (array A1).
Admitted.
Implicit Arguments update.

(*Why axiom*) Lemma access_update :
  forall (A1:Set),
  (forall (a:(array A1)),
   (forall (i:Z), (forall (v:A1), (access (update a i v) i) = v))).
Admitted.

(*Why axiom*) Lemma access_update_neq :
  forall (A1:Set),
  (forall (a:(array A1)),
   (forall (i:Z),
    (forall (j:Z),
     (forall (v:A1), (i <> j -> (access (update a i v) j) = (access a j)))))).
Admitted.

(*Why logic*) Definition array_length : forall (A1:Set), (array A1) -> Z.
Admitted.
Implicit Arguments array_length.

(*Why predicate*) Definition sorted_array  (t:(array Z)) (i:Z) (j:Z)
  := (forall (k1:Z),
      (forall (k2:Z),
       ((i <= k1 /\ k1 <= k2) /\ k2 <= j -> (access t k1) <= (access t k2)))).

(*Why predicate*) Definition exchange (A105:Set) (a1:(array A105)) (a2:(array A105)) (i:Z) (j:Z)
  := (array_length a1) = (array_length a2) /\
     (access a1 i) = (access a2 j) /\ (access a2 i) = (access a1 j) /\
     (forall (k:Z), (k <> i /\ k <> j -> (access a1 k) = (access a2 k))).
Implicit Arguments exchange.

(*Why logic*) Definition permut :
  forall (A1:Set), (array A1) -> (array A1) -> Z -> Z -> Prop.
Admitted.
Implicit Arguments permut.

(*Why axiom*) Lemma permut_refl :
  forall (A1:Set),
  (forall (t:(array A1)), (forall (l:Z), (forall (u:Z), (permut t t l u)))).
Admitted.

(*Why axiom*) Lemma permut_sym :
  forall (A1:Set),
  (forall (t1:(array A1)),
   (forall (t2:(array A1)),
    (forall (l:Z), (forall (u:Z), ((permut t1 t2 l u) -> (permut t2 t1 l u)))))).
Admitted.

(*Why axiom*) Lemma permut_trans :
  forall (A1:Set),
  (forall (t1:(array A1)),
   (forall (t2:(array A1)),
    (forall (t3:(array A1)),
     (forall (l:Z),
      (forall (u:Z),
       ((permut t1 t2 l u) -> ((permut t2 t3 l u) -> (permut t1 t3 l u)))))))).
Admitted.

(*Why axiom*) Lemma permut_exchange :
  forall (A1:Set),
  (forall (a1:(array A1)),
   (forall (a2:(array A1)),
    (forall (l:Z),
     (forall (u:Z),
      (forall (i:Z),
       (forall (j:Z),
        (l <= i /\ i <= u ->
         (l <= j /\ j <= u -> ((exchange a1 a2 i j) -> (permut a1 a2 l u)))))))))).
Admitted.

(*Why axiom*) Lemma exchange_upd :
  forall (A1:Set),
  (forall (a:(array A1)),
   (forall (i:Z),
    (forall (j:Z),
     (exchange a (update (update a i (access a j)) j (access a i)) i j)))).
Admitted.

(*Why axiom*) Lemma permut_weakening :
  forall (A1:Set),
  (forall (a1:(array A1)),
   (forall (a2:(array A1)),
    (forall (l1:Z),
     (forall (r1:Z),
      (forall (l2:Z),
       (forall (r2:Z),
        ((l1 <= l2 /\ l2 <= r2) /\ r2 <= r1 ->
         ((permut a1 a2 l2 r2) -> (permut a1 a2 l1 r1))))))))).
Admitted.

(*Why axiom*) Lemma permut_eq :
  forall (A1:Set),
  (forall (a1:(array A1)),
   (forall (a2:(array A1)),
    (forall (l:Z),
     (forall (u:Z),
      (l <= u ->
       ((permut a1 a2 l u) ->
        (forall (i:Z), (i < l \/ u < i -> (access a2 i) = (access a1 i))))))))).
Admitted.

(*Why predicate*) Definition permutation (A114:Set) (a1:(array A114)) (a2:(array A114))
  := (permut a1 a2 0 ((array_length a1) - 1)).
Implicit Arguments permutation.

(*Why axiom*) Lemma array_length_update :
  forall (A1:Set),
  (forall (a:(array A1)),
   (forall (i:Z),
    (forall (v:A1), (array_length (update a i v)) = (array_length a)))).
Admitted.

(*Why axiom*) Lemma permut_array_length :
  forall (A1:Set),
  (forall (a1:(array A1)),
   (forall (a2:(array A1)),
    (forall (l:Z),
     (forall (u:Z),
      ((permut a1 a2 l u) -> (array_length a1) = (array_length a2)))))).
Admitted.

(*Why type*) Definition A: Set.
Admitted.

(*Why logic*) Definition M : Z.
Admitted.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Axiom N_positive : (0 <= N)%Z.


Proof.
intuition.
Qed.

Proof.
intros; exact lexZ_well_founded.
Qed.

Proof.
intuition simple induction result1; tauto.
Qed.

Proof.
simple induction result1; intuition; discriminate Post5.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition discriminate H18 || auto with *.
subst j2 i2.
  apply match_right_extension.
  replace (i1 + 1 - (j1 + 1))%Z with (i1 - j1)%Z.
 assumption.
 Omega'.
  Omega'.
 Omega'.
  ring (i1 + 1 - (j1 + 1) + j1)%Z.
 ring (0 + j1)%Z.
 assumption.
  replace (i1 + 1 - (j1 + 1))%Z with (i1 - j1)%Z.
   apply (H18 k); assumption || Omega'.
  Omega'.
  unfold lexZ, lex, Zwf, pairZ.
 left; Omega'.
Qed.

Proof.
intuition discriminate H18 || auto with *.
  subst j1.
  apply match_empty.
 Omega'.
 Omega'.
  elim (Z_le_lt_eq_dec k (i1 - j1)).
  intro.
 apply (H18 k); assumption || Omega'.
  intro.
 generalize H19.
 apply match_contradiction_at_first.
 Omega'.
  rewrite b.
 subst j1.
 ring (i1 - 0)%Z.
 assumption.
  Omega'.
unfold lexZ, lex, Zwf, pairZ.
 left; Omega'.
Qed.

Proof.
intuition.
Qed.

Proof.
intuition assert (j1 <> 0%Z); auto with *.
  (* invariant *)
  elim (H5 j1); intros.
 Omega'.
  Omega'.
  elim (H5 j1); intros; Omega'.
  elim (H5 j1); intros; Omega'.
  apply next_iteration with (j := j1).
  Omega'.
  Omega'.
  assumption.
  subst j2; apply (H5 j1); Omega'.
  (* ~(match a k p `0` M) *)
  elim (Z_lt_ge_dec k (i1 - j1)); intro Hck.
  (* k < i0-j0 *)
  apply (H20 k); assumption || Omega'.
  elim (Z_ge_lt_dec (i1 - j1) k); intro Hck'.
  (* k = i0-j0 *)
  generalize H21.
 replace k with (i1 - j1)%Z.
  apply match_contradiction_at_i with (i := j1).
  Omega'.
 Omega'.
 ring (i1 - j1 + j1)%Z.
 ring (0 + j1)%Z.
 assumption.
 Omega'.
   (* i0-j0 < k *)
  generalize H21.
 rewrite <- H.
  apply next_is_maximal with (i := i1) (j := j1) (n := access next0 j1).
   Omega'.
 Omega'.
 Omega'.
  assumption.
  apply (H5 j1); Omega'.
  unfold lexZ, lex, Zwf, pairZ.
   elim (H5 j1).
 intros.
  right.
 Omega'.
 Omega'.
Qed.

Proof.
intuition; rewrite Pre13; assumption.
Qed.

Definition first_occur (p a:array A) (r:Z) :=
  ((0 <= r < array_length a)%Z -> match_ a r p 0 (array_length p)) /\
  (forall k:Z, (0 <= k < r)%Z -> ~ match_ a k p 0 (array_length p)).

Proof.
intuition.
generalize M_positive; Omega'.
generalize N_positive; Omega'.
subst i j.
apply match_empty.
generalize N_positive; Omega'.
 generalize M_positive; Omega'.
Qed.

Proof.
intros.
decompose [and] Inv.
unfold first_occur.
 split.
 intro.
 rewrite <- Test10.
  replace (array_length p) with j1.
 assumption.
 Omega'.
replace (i1 - M)%Z with (i1 - j1)%Z.
 replace (array_length p) with M.
 assumption.
 Omega'.
Omega'.
Qed.

Proof.
intros.
 unfold first_occur.
 decompose [and] Inv.
split.
 intro.
 absurd (i1 < N)%Z; Omega'.
intros k Hk.
 elim (Z_lt_ge_dec k (i1 - j1)); intro Hk'.
replace (array_length p) with M.
apply H6; Omega'.
 Omega'.
red; intro.
 decompose [match_] H4.
absurd (k <= N - M)%Z; Omega'.
Qed.


Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.



(*Why type*) Definition prodZZ: Set.
Admitted.

(*Why logic*) Definition match_ :
  (array A) -> Z -> (array A) -> Z -> Z -> Prop.
Admitted.

(*Why logic*) Definition Next : (array A) -> Z -> Z -> Prop.
Admitted.

(*Why logic*) Definition pairZ : Z -> Z -> prodZZ.
Admitted.

(*Why logic*) Definition N : Z.
Admitted.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.

Proof.
(* FILL PROOF HERE *)
Save.



(*Why logic*) Definition first_occur : (array A) -> (array A) -> Z -> Prop.
Admitted.

