(* 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 set.Fset.
Require set.SetImp.

Axiom vertex : Type.
Parameter vertex_WhyType : WhyType vertex.
Existing Instance vertex_WhyType.

Parameter eq: vertex -> vertex -> Prop.

Axiom eq'spec : forall (x:vertex) (y:vertex), eq x y <-> (x = y).

Parameter succ: vertex -> set.Fset.fset vertex.

(* Why3 assumption *)
Inductive path: vertex -> vertex -> Numbers.BinNums.Z -> Prop :=
  | path_empty : forall (v:vertex), path v v 0%Z
  | path_succ :
      forall (v1:vertex) (v2:vertex) (v3:vertex) (n:Numbers.BinNums.Z),
      path v1 v2 n -> set.Fset.mem v3 (succ v2) -> path v1 v3 (n + 1%Z)%Z.

Axiom path_nonneg :
  forall (v1:vertex) (v2:vertex) (n:Numbers.BinNums.Z), path v1 v2 n ->
  (0%Z <= n)%Z.

Axiom path_inversion :
  forall (v1:vertex) (v3:vertex) (n:Numbers.BinNums.Z), (0%Z <= n)%Z ->
  path v1 v3 (n + 1%Z)%Z ->
  exists v2:vertex, path v1 v2 n /\ set.Fset.mem v3 (succ v2).

Axiom path_closure :
  forall (s:set.Fset.fset vertex),
  (forall (x:vertex), set.Fset.mem x s ->
   (forall (y:vertex), set.Fset.mem y (succ x) -> set.Fset.mem y s)) ->
  forall (v1:vertex) (v2:vertex) (n:Numbers.BinNums.Z), path v1 v2 n ->
  set.Fset.mem v1 s -> set.Fset.mem v2 s.

(* Why3 assumption *)
Definition shortest_path (v1:vertex) (v2:vertex) (n:Numbers.BinNums.Z) : Prop :=
  path v1 v2 n /\ (forall (m:Numbers.BinNums.Z), (m < n)%Z -> ~ path v1 v2 m).

Axiom set : Type.
Parameter set_WhyType : WhyType set.
Existing Instance set_WhyType.

Parameter to_fset: set -> set.Fset.fset vertex.

Parameter choose: set -> vertex.

Axiom choose'spec :
  forall (s:set), ~ set.Fset.is_empty (to_fset s) ->
  set.Fset.mem (choose s) (to_fset s).

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

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

(* Why3 assumption *)
Definition inv (s:vertex) (t:vertex) (visited:set.Fset.fset vertex)
    (current:set.Fset.fset vertex) (next:set.Fset.fset vertex)
    (d:Numbers.BinNums.Z) : Prop :=
  set.Fset.subset current visited /\
  (forall (x:vertex), set.Fset.mem x current -> shortest_path s x d) /\
  set.Fset.subset next visited /\
  (forall (x:vertex), set.Fset.mem x next -> shortest_path s x (d + 1%Z)%Z) /\
  (forall (x:vertex) (m:Numbers.BinNums.Z), path s x m -> (m <= d)%Z ->
   set.Fset.mem x visited) /\
  (forall (x:vertex), set.Fset.mem x visited ->
   (exists m:Numbers.BinNums.Z, path s x m /\ (m <= (d + 1%Z)%Z)%Z)) /\
  (forall (x:vertex), shortest_path s x (d + 1%Z)%Z ->
   set.Fset.mem x next \/ ~ set.Fset.mem x visited) /\
  (set.Fset.mem t visited -> set.Fset.mem t current \/ set.Fset.mem t next).

(* Why3 assumption *)
Definition closure (visited:set.Fset.fset vertex)
    (current:set.Fset.fset vertex) (next:set.Fset.fset vertex) (x:vertex) :
    Prop :=
  set.Fset.mem x visited -> ~ set.Fset.mem x current ->
  ~ set.Fset.mem x next -> forall (y:vertex), set.Fset.mem y (succ x) ->
  set.Fset.mem y visited.

(* Why3 goal *)
Theorem bfs'vc :
  forall (s:vertex) (t:vertex), forall (visited:set),
  ((to_fset visited) = (set.Fset.empty : set.Fset.fset vertex)) /\
  ((set.Fset.cardinal (to_fset visited)) = 0%Z) -> forall (o:set),
  ((to_fset o) = (set.Fset.empty : set.Fset.fset vertex)) /\
  ((set.Fset.cardinal (to_fset o)) = 0%Z) -> forall (o1:set),
  ((to_fset o1) = (set.Fset.empty : set.Fset.fset vertex)) /\
  ((set.Fset.cardinal (to_fset o1)) = 0%Z) -> forall (visited1:set),
  ((to_fset visited1) = (set.Fset.add s (to_fset visited))) /\
  (set.Fset.mem s (to_fset visited) /\
   ((set.Fset.cardinal (to_fset visited1)) =
    (set.Fset.cardinal (to_fset visited))) \/
   ~ set.Fset.mem s (to_fset visited) /\
   ((set.Fset.cardinal (to_fset visited1)) =
    ((set.Fset.cardinal (to_fset visited)) + 1%Z)%Z)) ->
  forall (current:set),
  ((to_fset current) = (set.Fset.add s (to_fset o))) /\
  (set.Fset.mem s (to_fset o) /\
   ((set.Fset.cardinal (to_fset current)) = (set.Fset.cardinal (to_fset o))) \/
   ~ set.Fset.mem s (to_fset o) /\
   ((set.Fset.cardinal (to_fset current)) =
    ((set.Fset.cardinal (to_fset o)) + 1%Z)%Z)) ->
  forall (d:Numbers.BinNums.Z) (next:set) (current1:set) (visited2:set),
  inv s t (to_fset visited2) (to_fset current1) (to_fset next) d /\
  (set.Fset.is_empty (to_fset current1) -> set.Fset.is_empty (to_fset next)) /\
  (forall (x:vertex),
   closure (to_fset visited2) (to_fset current1) (to_fset next) x) /\
  (0%Z <= d)%Z -> set.Fset.is_empty (to_fset current1) ->
  ~ set.Fset.mem t (to_fset visited2) -> forall (d1:Numbers.BinNums.Z),
  ~ path s t d1.
Proof.
intros s t1 visited h1 o h2 o1 h3 visited1 h4 current h5 d next current1
visited2 (h6,(h7,(h8,h9))) h10 h11 d1 H.
assert (Fset.mem t1 (to_fset visited2)).
apply path_closure with s d1; auto.
unfold closure in h8.
intros x hx.
apply h8.
intuition.
rewrite (Fset.empty_is_empty _ h10). apply Fset.is_empty_empty.
rewrite (Fset.empty_is_empty _ (h7 h10)). apply Fset.is_empty_empty.
red in h6; decompose [and] h6.
apply H4 with 0%Z.
apply path_empty.
assumption.
exact (h11 H0).
Qed.