*)

(* Specifications: *)
(** **** Exercise: 2 stars, recommended (assign_aequiv)  *)
Theorem assign_aequiv : forall X e,
aequiv (AId X) e ->
cequiv SKIP (X ::= e).
Lemma iff_trans : forall (P1 P2 P3 : Prop),
(P1 <-> P2) -> (P2 <-> P3) -> (P1 <-> P3).
Theorem CWhile_congruence : forall b1 b1' c1 c1',
bequiv b1 b1' -> cequiv c1 c1' ->
cequiv (WHILE b1 DO c1 END) (WHILE b1' DO c1' END).
Corollary backtrackSizeMonotonic {A : Type} (lg : seq (nat * G (option A))) :
lg \subset [set x | SizeMonotonic x.2 ] ->
SizeMonotonic (backtrack lg).
Corollary backtrackSizeMonotonicOpt {A : Type} (lg : seq (nat * G (option A))) :
lg \subset [set x | SizeMonotonicOpt x.2 ] ->
SizeMonotonicOpt (backtrack lg).
Lemma semBacktrackFuel {A} tot fuel (l : list (nat * G (option A))) size :
sum_fst l = tot -> length l = fuel ->
semGenSize (backtrackFuel fuel tot l) size <-->
(\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: (semGenSize x.2 size))) :|:
([set None] :&: (\bigcap_(x in l :&: (fun x => x.1 <> 0)) (semGenSize x.2 size))).
Lemma semBacktrackSize {A} (l : list (nat * G (option A))) size :
semGenSize (backtrack l) size <-->
(\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: (semGenSize x.2 size))) :|:
([set None] :&: (\bigcap_(x in l :&: (fun x => x.1 <> 0)) (semGenSize x.2 size))).
Lemma bigcup_cons_setI_subset_compat_backtrack {A}
(n : nat) (g g' : G (option A)) (l l' : seq (nat * G (option A))) s :
isSome :&: semGenSize g s  \subset isSome :&: semGenSize g' s ->
\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s) \subset
\bigcup_(x in (l' :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s) ->
\bigcup_(x in (((n, g) :: l) :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s) \subset
\bigcup_(x in (((n, g') :: l') :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s).
Lemma bigcup_cons_setI_subset_pres_backtrack {A}
(n : nat) (g : G (option A)) (l l' : seq (nat * G (option A))) s :
\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s) \subset
\bigcup_(x in (l' :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s) ->
\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: semGenSize x.2 s) \subset
\bigcup_(x in ((n, g) :: l') :&: (fun x => x.1 <> 0)) (isSome :&: semGenSize x.2 s).
Lemma semBacktrack_sound :
forall (A : Type) (l : seq (nat * G (option A))),
semGen (backtrack l) \subset
(\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: (semGen x.2))) :|:
([set None] :&: (\bigcap_(x in l :&: (fun x => x.1 <> 0)) (semGen x.2))).
Lemma semBacktrack_complete :
forall (A : Type) (l : seq (nat * G (option A))),
\bigcup_(x in (l :&: (fun x => x.1 <> 0))) (isSome :&: (semGen x.2)) \subset
semGen (backtrack l).
Lemma semFoldGen_right :
forall {A B : Type} (f : A -> B -> G A) (bs : list B) (a0 : A) (s : nat),
semGenSize (foldGen f bs a0) s <-->
[ set an |
foldr (fun b p => [set a_prev | exists a, a \in (semGenSize (f a_prev b) s :&: p)])
[set an] bs a0].