(********************************************************************)
(*                                                                  *)
(*  The Why3 Verification Platform   /   The Why3 Development Team  *)
(*  Copyright 2010-2018   --   Inria - CNRS - Paris-Sud University  *)
(*                                                                  *)
(*  This software is distributed under the terms of the GNU Lesser  *)
(*  General Public License version 2.1, with the special exception  *)
(*  on linking described in file LICENSE.                           *)
(*                                                                  *)
(********************************************************************)

(* This file is generated by Why3's Coq-realize driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.

Require Import ClassicalEpsilon.

Lemma predicate_extensionality:
  forall A (P Q : A -> Prop),
    (forall x, P x <-> Q x) -> P = Q.
Admitted.
(* "it is folklore that the two together are consistent" *)

(* Why3 goal *)
Definition set : forall (a:Type), Type.
intros.
exact (a -> Prop).
Defined.

Global Instance set_WhyType : forall (a:Type) {a_WT:WhyType a}, WhyType (set a).
Proof.
intros.
split.
exact (fun _ => False).
intros x y.
apply excluded_middle_informative.
Qed.

(* Why3 goal *)
Definition mem: forall {a:Type} {a_WT:WhyType a}, a -> (set a) -> Prop.
intros a a_WT x s.
exact (s x).
Defined.

Hint Unfold mem.

(* Why3 assumption *)
Definition infix_eqeq {a:Type} {a_WT:WhyType a} (s1:(set a)) (s2:(set
  a)): Prop := forall (x:a), (mem x s1) <-> (mem x s2).

Notation "x == y" := (infix_eqeq x y) (at level 70, no associativity).

(* Why3 goal *)
Lemma extensionality : forall {a:Type} {a_WT:WhyType a}, forall (s1:(set a))
  (s2:(set a)), (infix_eqeq s1 s2) -> (s1 = s2).
Proof.
intros a a_WT s1 s2 h1.
now apply predicate_extensionality.
Qed.

(* Why3 assumption *)
Definition subset {a:Type} {a_WT:WhyType a} (s1:(set a)) (s2:(set
  a)): Prop := forall (x:a), (mem x s1) -> (mem x s2).

(* Why3 goal *)
Lemma subset_refl : forall {a:Type} {a_WT:WhyType a}, forall (s:(set a)),
  (subset s s).
Proof.
now intros a a_WT s x.
Qed.

(* Why3 goal *)
Lemma 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)).
Proof.
intros a a_WT s1 s2 s3 h1 h2 x H.
now apply h2, h1.
Qed.

(* Why3 goal *)
Definition empty: forall {a:Type} {a_WT:WhyType a}, (set a).
intros.
exact (fun _ => False).
Defined.

(* Why3 assumption *)
Definition is_empty {a:Type} {a_WT:WhyType a} (s:(set a)): Prop :=
  forall (x:a), ~ (mem x s).

(* Why3 goal *)
Lemma empty_def1 : forall {a:Type} {a_WT:WhyType a}, (is_empty (empty : (set
  a))).
Proof.
now intros a a_WT x.
Qed.

(* Why3 goal *)
Lemma mem_empty : forall {a:Type} {a_WT:WhyType a}, forall (x:a), ~ (mem x
  (empty : (set a))).
Proof.
now intros a a_WT x.
Qed.

(* Why3 goal *)
Definition add: forall {a:Type} {a_WT:WhyType a}, a -> (set a) -> (set a).
intros a a_WT x s.
exact (fun y => x = y \/ s y).
Defined.

(* Why3 goal *)
Lemma add_def1 : forall {a:Type} {a_WT:WhyType a}, forall (x:a) (y:a),
  forall (s:(set a)), (mem x (add y s)) <-> ((x = y) \/ (mem x s)).
Proof.
intros a a_WT x y s.
unfold add, mem; intuition.
Qed.

(* Why3 goal *)
Definition remove: forall {a:Type} {a_WT:WhyType a}, a -> (set a) -> (set a).
intros a a_WT x s.
exact (fun y => x <> y /\ s y).
Defined.

(* Why3 goal *)
Lemma remove_def1 : forall {a:Type} {a_WT:WhyType a}, forall (x:a) (y:a)
  (s:(set a)), (mem x (remove y s)) <-> ((~ (x = y)) /\ (mem x s)).
Proof.
intros a a_WT x y s.
unfold remove, mem; intuition.
Qed.

(* Why3 goal *)
Lemma add_remove : forall {a:Type} {a_WT:WhyType a}, forall (x:a) (s:(set
  a)), (mem x s) -> ((add x (remove x s)) = s).
Proof.
intros a a_WT x s h1.
apply extensionality; intro y.
rewrite add_def1.
rewrite remove_def1.
destruct (why_decidable_eq y x) as [->|H] ; intuition.
Qed.

(* Why3 goal *)
Lemma remove_add : forall {a:Type} {a_WT:WhyType a}, forall (x:a) (s:(set
  a)), ((remove x (add x s)) = (remove x s)).
Proof.
intros a a_WT x s.
apply extensionality; intro y.
rewrite remove_def1.
rewrite remove_def1.
rewrite add_def1.
destruct (why_decidable_eq y x) as [->|H] ; intuition.
Qed.

(* Why3 goal *)
Lemma subset_remove : forall {a:Type} {a_WT:WhyType a}, forall (x:a) (s:(set
  a)), (subset (remove x s) s).
Proof.
intros a a_WT x s y.
rewrite remove_def1.
now intros [_ H].
Qed.

(* Why3 goal *)
Definition union: forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) ->
  (set a).
intros a a_WT s1 s2.
exact (fun x => s1 x \/ s2 x).
Defined.

(* Why3 goal *)
Lemma union_def1 : forall {a:Type} {a_WT:WhyType a}, forall (s1:(set a))
  (s2:(set a)) (x:a), (mem x (union s1 s2)) <-> ((mem x s1) \/ (mem x s2)).
Proof.
now intros a a_WT s1 s2 x.
Qed.

(* Why3 goal *)
Definition inter: forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) ->
  (set a).
intros a a_WT s1 s2.
exact (fun x => s1 x /\ s2 x).
Defined.

(* Why3 goal *)
Lemma inter_def1 : forall {a:Type} {a_WT:WhyType a}, forall (s1:(set a))
  (s2:(set a)) (x:a), (mem x (inter s1 s2)) <-> ((mem x s1) /\ (mem x s2)).
Proof.
now intros a a_WT s1 s2 x.
Qed.

(* Why3 goal *)
Definition diff: forall {a:Type} {a_WT:WhyType a}, (set a) -> (set a) -> (set
  a).
intros a a_WT s1 s2.
exact (fun x => s1 x /\ ~(s2 x)).
Defined.

(* Why3 goal *)
Lemma diff_def1 : forall {a:Type} {a_WT:WhyType a}, forall (s1:(set a))
  (s2:(set a)) (x:a), (mem x (diff s1 s2)) <-> ((mem x s1) /\ ~ (mem x s2)).
Proof.
now intros a a_WT s1 s2 x.
Qed.

(* Why3 goal *)
Lemma subset_diff : forall {a:Type} {a_WT:WhyType a}, forall (s1:(set a))
  (s2:(set a)), (subset (diff s1 s2) s1).
Proof.
intros a a_WT s1 s2 x.
rewrite diff_def1.
now intros [H _].
Qed.

(* Why3 goal *)
Definition choose: forall {a:Type} {a_WT:WhyType a}, (set a) -> a.
intros a a_WT s.
assert (i: inhabited a) by (apply inhabits, why_inhabitant).
exact (epsilon i (fun x => mem x s)).
Defined.

(* Why3 goal *)
Lemma choose_def : forall {a:Type} {a_WT:WhyType a}, forall (s:(set a)),
  (~ (is_empty s)) -> (mem (choose s) s).
Proof.
intros a a_WT s h.
unfold choose.
apply epsilon_spec.
now apply not_all_not_ex.
Qed.

(* Why3 goal *)
Definition all: forall {a:Type} {a_WT:WhyType a}, (set a).
intros a a_WT.
exact (fun x => True).
Defined.

(* Why3 goal *)
Lemma all_def : forall {a:Type} {a_WT:WhyType a}, forall (x:a), (mem x
  (all : (set a))).
Proof.
now intros a a_WT x.
Qed.

