(* This file is generated by Why3's Coq driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.
Require HighOrd.
Require int.Int.
Require map.Map.

Axiom set : forall (a:Type), Type.
Parameter set_WhyType : forall (a:Type) {a_WT:WhyType a}, WhyType (set a).
Existing Instance set_WhyType.

Parameter mem: forall {a:Type} {a_WT:WhyType a}, a -> (set a) -> Prop.

Parameter infix_eqeq:
  forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) -> Prop.

Axiom infix_eqeq_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (infix_eqeq s1 s2) -> forall (x:a),
  (mem x s1) -> mem x s2.

Axiom infix_eqeq_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (infix_eqeq s1 s2) -> forall (x:a),
  (mem x s2) -> mem x s1.

Axiom infix_eqeq_spec2 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (forall (x:a), (mem x s1) <-> (mem x s2)) ->
  infix_eqeq s1 s2.

Axiom extensionality :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (infix_eqeq s1 s2) -> (s1 = s2).

Parameter subset:
  forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) -> Prop.

Axiom subset_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (subset s1 s2) -> forall (x:a), (mem x s1) ->
  mem x s2.

Axiom subset_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (forall (x:a), (mem x s1) -> mem x s2) ->
  subset s1 s2.

Axiom subset_refl :
  forall {a:Type} {a_WT:WhyType a}, forall (s:set a), subset s s.

Axiom subset_trans :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a) (s3:set a), (subset s1 s2) ->
  (subset s2 s3) -> subset s1 s3.

Parameter is_empty: forall {a:Type} {a_WT:WhyType a}, (set a) -> Prop.

Axiom is_empty_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), (is_empty s) -> forall (x:a), ~ (mem x s).

Axiom is_empty_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), (forall (x:a), ~ (mem x s)) -> is_empty s.

Parameter empty: forall {a:Type} {a_WT:WhyType a}, set a.

Axiom empty_def : forall {a:Type} {a_WT:WhyType a}, is_empty (empty : set a).

Parameter add: forall {a:Type} {a_WT:WhyType a}, a -> (set a) -> set a.

Axiom add_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), forall (y:a), (mem y (add x s)) ->
  (y = x) \/ (mem y s).

Axiom add_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), forall (y:a), ((y = x) \/ (mem y s)) ->
  mem y (add x s).

Parameter remove: forall {a:Type} {a_WT:WhyType a}, a -> (set a) -> set a.

Axiom remove_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), forall (y:a), (mem y (remove x s)) -> ~ (y = x).

Axiom remove_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), forall (y:a), (mem y (remove x s)) -> mem y s.

Axiom remove_spec2 :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), forall (y:a), (~ (y = x) /\ (mem y s)) ->
  mem y (remove x s).

Axiom add_remove :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), (mem x s) -> ((add x (remove x s)) = s).

Axiom remove_add :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), ((remove x (add x s)) = (remove x s)).

Axiom subset_remove :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a) (s:set a), subset (remove x s) s.

Parameter union:
  forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) -> set a.

Axiom union_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), (mem x (union s1 s2)) ->
  (mem x s1) \/ (mem x s2).

Axiom union_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), ((mem x s1) \/ (mem x s2)) ->
  mem x (union s1 s2).

Parameter inter:
  forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) -> set a.

Axiom inter_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), (mem x (inter s1 s2)) ->
  mem x s1.

Axiom inter_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), (mem x (inter s1 s2)) ->
  mem x s2.

Axiom inter_spec2 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), ((mem x s1) /\ (mem x s2)) ->
  mem x (inter s1 s2).

Parameter diff:
  forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) -> set a.

Axiom diff_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), (mem x (diff s1 s2)) ->
  mem x s1.

Axiom diff_spec1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), (mem x (diff s1 s2)) ->
  ~ (mem x s2).

Axiom diff_spec2 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), forall (x:a), ((mem x s1) /\ ~ (mem x s2)) ->
  mem x (diff s1 s2).

Axiom subset_diff :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), subset (diff s1 s2) s1.

Parameter choose: forall {a:Type} {a_WT:WhyType a}, (set a) -> a.

Axiom choose_spec :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), ~ (is_empty s) -> mem (choose s) s.

Parameter cardinal: forall {a:Type} {a_WT:WhyType a}, (set a) -> Z.

Axiom cardinal_nonneg :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), (0%Z <= (cardinal s))%Z.

Axiom cardinal_empty :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), ((cardinal s) = 0%Z) -> is_empty s.

Axiom cardinal_empty1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), (is_empty s) -> ((cardinal s) = 0%Z).

Axiom cardinal_add :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a), forall (s:set a), ~ (mem x s) ->
  ((cardinal (add x s)) = (1%Z + (cardinal s))%Z).

Axiom cardinal_remove :
  forall {a:Type} {a_WT:WhyType a},
  forall (x:a), forall (s:set a), (mem x s) ->
  ((cardinal s) = (1%Z + (cardinal (remove x s)))%Z).

Axiom cardinal_subset :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (subset s1 s2) ->
  ((cardinal s1) <= (cardinal s2))%Z.

Axiom subset_eq :
  forall {a:Type} {a_WT:WhyType a},
  forall (s1:set a) (s2:set a), (subset s1 s2) ->
  ((cardinal s1) = (cardinal s2)) -> infix_eqeq s1 s2.

Axiom cardinal1 :
  forall {a:Type} {a_WT:WhyType a},
  forall (s:set a), ((cardinal s) = 1%Z) -> forall (x:a), (mem x s) ->
  (x = (choose s)).

Parameter min_elt: (set Z) -> Z.

Axiom min_elt_spec : forall (s:set Z), ~ (is_empty s) -> mem (min_elt s) s.

Axiom min_elt_spec1 :
  forall (s:set Z), ~ (is_empty s) -> forall (x:Z), (mem x s) ->
  ((min_elt s) <= x)%Z.

Parameter max_elt: (set Z) -> Z.

Axiom max_elt_spec : forall (s:set Z), ~ (is_empty s) -> mem (max_elt s) s.

Axiom max_elt_spec1 :
  forall (s:set Z), ~ (is_empty s) -> forall (x:Z), (mem x s) ->
  (x <= (max_elt s))%Z.

Parameter interval: Z -> Z -> set Z.

Axiom interval_spec :
  forall (l:Z) (r:Z), forall (x:Z), (mem x (interval l r)) -> (l <= x)%Z.

Axiom interval_spec1 :
  forall (l:Z) (r:Z), forall (x:Z), (mem x (interval l r)) -> (x < r)%Z.

Axiom interval_spec2 :
  forall (l:Z) (r:Z), forall (x:Z), ((l <= x)%Z /\ (x < r)%Z) ->
  mem x (interval l r).

Axiom cardinal_interval :
  forall (l:Z) (r:Z),
  ((l <= r)%Z -> ((cardinal (interval l r)) = (r - l)%Z)) /\
  (~ (l <= r)%Z -> ((cardinal (interval l r)) = 0%Z)).

Parameter succ: (set Z) -> set Z.

Axiom succ_spec :
  forall (s:set Z), forall (i:Z), (mem i (succ s)) -> (1%Z <= i)%Z.

Axiom succ_spec1 :
  forall (s:set Z), forall (i:Z), (mem i (succ s)) -> mem (i - 1%Z)%Z s.

Axiom succ_spec2 :
  forall (s:set Z), forall (i:Z), ((1%Z <= i)%Z /\ (mem (i - 1%Z)%Z s)) ->
  mem i (succ s).

Parameter pred: (set Z) -> set Z.

Axiom pred_spec :
  forall (s:set Z), forall (i:Z), (mem i (pred s)) -> (0%Z <= i)%Z.

Axiom pred_spec1 :
  forall (s:set Z), forall (i:Z), (mem i (pred s)) -> mem (i + 1%Z)%Z s.

Axiom pred_spec2 :
  forall (s:set Z), forall (i:Z), ((0%Z <= i)%Z /\ (mem (i + 1%Z)%Z s)) ->
  mem i (pred s).

(* Why3 assumption *)
Inductive ref (a:Type) :=
  | mk_ref : a -> ref a.
Axiom ref_WhyType : forall (a:Type) {a_WT:WhyType a}, WhyType (ref a).
Existing Instance ref_WhyType.
Implicit Arguments mk_ref [[a]].

(* Why3 assumption *)
Definition contents {a:Type} {a_WT:WhyType a} (v:ref a) : a :=
  match v with
  | mk_ref x => x
  end.

Parameter n: Z.

(* Why3 assumption *)
Definition solution := Z -> Z.

(* Why3 assumption *)
Definition eq_prefix {a:Type} {a_WT:WhyType a} (t:Z -> a) (u:Z -> a) 
    (i:Z) : Prop :=
  forall (k:Z), ((0%Z <= k)%Z /\ (k < i)%Z) -> ((t k) = (u k)).

(* Why3 assumption *)
Definition partial_solution (k:Z) (s:Z -> Z) : Prop :=
  forall (i:Z), ((0%Z <= i)%Z /\ (i < k)%Z) ->
  ((0%Z <= (s i))%Z /\ ((s i) < n)%Z) /\
  forall (j:Z), ((0%Z <= j)%Z /\ (j < i)%Z) ->
  ~ ((s i) = (s j)) /\
  (~ (((s i) - (s j))%Z = (i - j)%Z) /\ ~ (((s i) - (s j))%Z = (j - i)%Z)).

Axiom partial_solution_eq_prefix :
  forall (u:Z -> Z) (t:Z -> Z) (k:Z), (partial_solution k t) ->
  (eq_prefix t u k) -> partial_solution k u.

(* Why3 assumption *)
Definition lt_sol (s1:Z -> Z) (s2:Z -> Z) : Prop :=
  exists i:Z,
  ((0%Z <= i)%Z /\ (i < n)%Z) /\ ((eq_prefix s1 s2 i) /\ ((s1 i) < (s2 i))%Z).

(* Why3 assumption *)
Definition solutions := Z -> Z -> Z.

(* Why3 assumption *)
Definition sorted (s:Z -> Z -> Z) (a:Z) (b:Z) : Prop :=
  forall (i:Z) (j:Z), ((a <= i)%Z /\ ((i < j)%Z /\ (j < b)%Z)) ->
  lt_sol (s i) (s j).

Axiom no_duplicate :
  forall (s:Z -> Z -> Z) (a:Z) (b:Z), (sorted s a b) -> forall (i:Z) (j:Z),
  ((a <= i)%Z /\ ((i < j)%Z /\ (j < b)%Z)) -> ~ (eq_prefix (s i) (s j) n).

(* Why3 goal *)
Theorem VC_t3 :
  forall (col:Z -> Z) (k:Z) (sol:Z -> Z -> Z) (s:Z),
  forall (a:set Z) (b:set Z) (c:set Z),
  ((0%Z <= k)%Z /\
   (((k + (cardinal a))%Z = n) /\
    ((0%Z <= s)%Z /\
     ((forall (i:Z),
       (mem i a) <->
       (((0%Z <= i)%Z /\ (i < n)%Z) /\
        forall (j:Z), ((0%Z <= j)%Z /\ (j < k)%Z) -> ~ ((col j) = i))) /\
      ((forall (i:Z), (0%Z <= i)%Z ->
        ~ (mem i b) <->
        forall (j:Z), ((0%Z <= j)%Z /\ (j < k)%Z) ->
        ~ ((col j) = ((i + j)%Z - k)%Z)) /\
       ((forall (i:Z), (0%Z <= i)%Z ->
         ~ (mem i c) <->
         forall (j:Z), ((0%Z <= j)%Z /\ (j < k)%Z) ->
         ~ ((col j) = ((i + k)%Z - j)%Z)) /\
        (partial_solution k col))))))) ->
  ((is_empty a) <-> forall (x:Z), ~ (mem x a)) -> ~ (is_empty a) ->
  let o := diff a b in
  (forall (x:Z), (mem x o) <-> ((mem x a) /\ ~ (mem x b))) ->
  let o1 := diff o c in
  (forall (x:Z), (mem x o1) <-> ((mem x o) /\ ~ (mem x c))) ->
  (forall (u:Z -> Z), ((partial_solution n u) /\ (eq_prefix col u k)) ->
   mem (u k) o1) ->
  forall (f:Z) (e:set Z) (s1:Z) (sol1:Z -> Z -> Z) (k1:Z) (col1:Z -> Z),
  ((((f = (s1 - s)%Z) /\ (0%Z <= (s1 - s)%Z)%Z) /\
    ((k1 = k) /\
     ((subset e (diff (diff a b) c)) /\
      ((partial_solution k1 col1) /\
       ((sorted sol1 s s1) /\
        forall (i:Z) (j:Z), (mem i (diff o1 e)) -> (mem j e) -> (i < j)%Z))))) /\
   ((forall (i:Z), ((s <= i)%Z /\ (i < s1)%Z) ->
     (partial_solution n (sol1 i)) /\
     ((eq_prefix col1 (sol1 i) k1) /\ (mem ((sol1 i) k1) (diff o1 e)))) /\
    ((forall (t:Z -> Z),
      ((partial_solution n t) /\
       ((eq_prefix col1 t k1) /\ (mem (t k1) (diff o1 e)))) ->
      (mem (t k1) o1) /\
      (~ (mem (t k1) e) /\
       exists i:Z, ((s <= i)%Z /\ (i < s1)%Z) /\ (eq_prefix t (sol1 i) n))) /\
     ((eq_prefix col col1 k1) /\ (eq_prefix sol sol1 s))))) ->
  ((is_empty e) <-> forall (x:Z), ~ (mem x e)) -> ~ (is_empty e) ->
  let d := min_elt e in
  ((mem d e) /\ forall (x:Z), (mem x e) -> (d <= x)%Z) ->
  forall (col2:Z -> Z), (col2 = (map.Map.set col1 k1 d)) -> forall (k2:Z),
  (k2 = (k1 + 1%Z)%Z) ->
  let o2 := add d c in
  (forall (y:Z), (mem y o2) <-> ((y = d) \/ (mem y c))) ->
  (forall (i:Z),
   (mem i (pred o2)) <-> ((0%Z <= i)%Z /\ (mem (i + 1%Z)%Z o2))) ->
  let o3 := add d b in
  (forall (y:Z), (mem y o3) <-> ((y = d) \/ (mem y b))) ->
  (forall (i:Z),
   (mem i (succ o3)) <-> ((1%Z <= i)%Z /\ (mem (i - 1%Z)%Z o3))) ->
  (forall (y:Z), (mem y (remove d a)) <-> (~ (y = d) /\ (mem y a))) ->
  forall (s2:Z) (sol2:Z -> Z -> Z) (k3:Z) (col3:Z -> Z),
  ((0%Z <= (s2 - s1)%Z)%Z /\
   ((k3 = k2) /\
    ((sorted sol2 s1 s2) /\
     ((forall (t:Z -> Z),
       ((partial_solution n t) /\ (eq_prefix col3 t k3)) <->
       exists i:Z, ((s1 <= i)%Z /\ (i < s2)%Z) /\ (eq_prefix t (sol2 i) n)) /\
      ((eq_prefix col2 col3 k3) /\ (eq_prefix sol1 sol2 s1)))))) ->
  forall (f1:Z), (f1 = (f + (s2 - s1)%Z)%Z) -> forall (k4:Z),
  (k4 = (k3 - 1%Z)%Z) ->
  let o4 := remove d e in
  (forall (y:Z), (mem y o4) <-> (~ (y = d) /\ (mem y e))) ->
  forall (e1:set Z), (e1 = o4) -> sorted sol2 s s2.
(* Why3 intros col k sol s a b c (h1,(h2,(h3,(h4,(h5,(h6,h7)))))) h8 h9 o h10
        o1 h11 h12 f e s1 sol1 k1 col1
        (((h13,h14),(h15,(h16,(h17,(h18,h19))))),(h20,(h21,(h22,h23)))) h24
        h25 d (h26,h27) col2 h28 k2 h29 o2 h30 h31 o3 h32 h33 h34 s2 sol2 k3
        col3 (h35,(h36,(h37,(h38,(h39,h40))))) f1 h41 k4 h42 o4 h43 e1 h44. *)
Proof.
intros col k sol s a b c (h1,(h2,(h3,(h4,(h5,(h6,h7)))))) h8 h9 o h10 o1 h11
h12 f e s1 sol1 k1 col1
(((h13,h14),(h15,(h16,(h17,(h18,h19))))),(h20,(h21,(h22,h23)))) h24 h25 d
(h26,h27) col2 h28 k2 h29 o2 h30 h31 o3 h32 h33 h34 s2 sol2 k3 col3
(h35,(h36,(h37,(h38,(h39,h40))))) f1 h41 k4 h42 o4 h43 e1 h44.
red; intros i j hij.
assert (case: (j < s1 \/ s1 <= j)%Z) by omega. destruct case.
do 2 (rewrite <- h40; try omega).
apply h18; omega.
assert (case: (s1 <= i \/ i < s1)%Z) by omega. destruct case.
apply h37; omega.
(* s1 <= i < s2 <= j < s3 *)
red.
subst k1. (* rename k1 into k.*)
assert (k < n)%Z.
generalize (cardinal_nonneg a).
generalize (cardinal_empty a).
intuition.
assert (case: (cardinal a = 0 \/ cardinal a > 0)%Z) by omega. destruct case.
absurd (is_empty a); auto.
omega.


assert (ha: eq_prefix col1 (sol1 i) k /\ 
       mem (sol1 i k) (diff o1 e)).
  apply (h20 i).
  omega.
destruct ha as (ha,hb).

destruct (h38 (sol2 j)) as (_,hj).
destruct hj.
exists j; intuition.
red; intuition.
clear h37.

exists k; intuition.
(* eq_prefix ... *)
rewrite <- h40; try omega.
red; intros l hl.
rewrite <- H3; try omega.
rewrite <- h39; try omega.
subst col2.
generalize (Map.set_def col1 k d l).
intros (_,h).
rewrite h.
rewrite <- ha; omega.
omega.
(* s[i][k] < s[j][k] *)
apply h19.
rewrite <- h40; try omega.
auto.
rewrite <- H3; try omega.
rewrite <- h39; try omega.
subst col2.
generalize (Map.set_def col1 k d k).
intros (h,_).
rewrite h; try omega.
generalize (min_elt_spec e); intuition.
Qed.

