(* QuickChick Prelude *)
Set Warnings "-extraction-opaque-accessed,-extraction".
Set Warnings "-notation-overridden,-parsing".
Set Bullet Behavior "Strict Subproofs".
(* End prelude *)
Inductive ev : nat -> Prop :=
| ev_0 : ev 0
| ev_SS : forall n : nat, ev n -> ev (S (S n)).
Derive ArbitrarySizedSuchThat for (fun n => ev n).
Derive SizedProofEqs for (fun n => ev n).
Derive SizeMonotonicSuchThatOpt for (fun n => ev n).
Derive GenSizedSuchThatCorrect for (fun n => ev n).
Derive GenSizedSuchThatSizeMonotonicOpt for (fun n => ev n).
(* Future work: Before relevant software foundations testing book, this needs to be automated... *)
Instance dec_ev (n : nat) : Dec (ev n) :=
{| dec := let fix aux n :=
let n' := n in
let Heq := erefl n' : n' = n in
match n as n'' return (n' = n'' -> _) with
| O => fun H => left _
| S O => fun H => right _
| S (S n) => fun H => _ (aux n)
end Heq in
aux n |}.
Admitted. (* QuickChick ev_plus4. *)
Admitted. (* (*N*) QuickChick ev_minus2. *)
Admitted. (* (*N*) QuickChick ev_minus2'. *)
Admitted. (* OUT-OF-SCOPE *)
(* existential dummy *)
Definition double_reverse n : nat := n.
Instance dec_ex_double n : Dec (exists k, n = double k).
constructor; unfold decidable.
left; exists (double_reverse n).
eapply double_reverse_correct.
Defined.
Admitted. (* QuickChick ev_even_firsttry. (* Existential *) *)
Global Instance testSuchThat_swap_2 {A B : Type} {pre : A -> Prop}
{prop : A -> B -> Type}
`{Checkable (forall a, pre a -> forall b, prop a b)} :
Checkable (forall a b, pre a -> prop a b ) :=
{| checker f := @checker (forall a, pre a -> forall b, prop a b) _ _ |}.
Inductive ev' : nat -> Prop :=
| ev'_0 : ev' 0
| ev'_2 : ev' 2
| ev'_sum : forall n m, ev' n -> ev' m -> ev' (n + m).
Admitted. (* OUT-OF-SCOPE *)
Admitted. (* OUT-OF-SCOPE *)
Admitted. (* OUT-OF-SCOPE *)
Inductive next_nat : nat -> nat -> Prop :=
| nn : forall n:nat, next_nat n (S n).
Derive ArbitrarySizedSuchThat for (fun n => next_nat n m).
Derive SizeMonotonicSuchThatOpt for (fun n => next_nat n m).
Derive GenSizedSuchThatSizeMonotonicOpt for (fun n => next_nat n m).
Derive SizedProofEqs for (fun n => next_nat n m).
Derive GenSizedSuchThatCorrect for (fun n => next_nat n m).
Derive ArbitrarySizedSuchThat for (fun n => next_nat m n).
Derive SizeMonotonicSuchThatOpt for (fun n => next_nat m n).
Derive GenSizedSuchThatSizeMonotonicOpt for (fun n => next_nat n m).
Derive SizedProofEqs for (fun n => next_nat n m).
Derive GenSizedSuchThatCorrect for (fun n => next_nat n m).
Inductive next_even : nat -> nat -> Prop :=
| ne_1 : forall n, ev (S n) -> next_even n (S n)
| ne_2 : forall n, ev (S (S n)) -> next_even n (S (S n)).
Derive ArbitrarySizedSuchThat for (fun n => next_even n m).
Derive SizeMonotonicSuchThatOpt for (fun n => next_even n m).
Derive GenSizedSuchThatSizeMonotonicOpt for (fun n => next_even n m).
Derive SizedProofEqs for (fun n => next_even n m).
Derive GenSizedSuchThatCorrect for (fun n => next_even n m).
Derive ArbitrarySizedSuchThat for (fun n => next_even m n).
Derive SizeMonotonicSuchThatOpt for (fun n => next_even m n).
Derive GenSizedSuchThatSizeMonotonicOpt for (fun n => next_even n m).
Derive SizedProofEqs for (fun n => next_even n m).
Derive GenSizedSuchThatCorrect for (fun n => next_even n m).
Admitted. (* OUT-OF-SCOPE *)
Admitted. (* QuickChick O_le_n. *)
Admitted. (* OUT-OF-SCOPE *)
Admitted. (* OUT-OF-SCOPE *)
Admitted. (* QuickChick le_plus_l. *)
Admitted. (* OUT-OF-SCOPE *)
Admitted. (* OUT-OF-SCOPE *)
Inductive reg_exp (T : Type) : Type :=
| EmptySet : reg_exp T
| EmptyStr : reg_exp T
| Char : T -> reg_exp T
| App : reg_exp T -> reg_exp T -> reg_exp T
| Union : reg_exp T -> reg_exp T -> reg_exp T
| Star : reg_exp T -> reg_exp T.
Arguments EmptySet {T}.
Arguments EmptyStr {T}.
Arguments Char {T} _.
Arguments App {T} _ _.
Arguments Union {T} _ _.
Arguments Star {T} _.
Derive (Arbitrary, Show) for reg_exp.
Derive (Sized, CanonicalSized) for reg_exp.
Derive SizeMonotonic for reg_exp using genSreg_exp.
Derive SizedMonotonic for reg_exp.
Derive SizedCorrect for reg_exp using genSreg_exp and SizeMonotonicreg_exp.
Inductive exp_match {T} : list T -> reg_exp T -> Prop :=
| MEmpty : exp_match [] EmptyStr
| MChar : forall x, exp_match [x] (Char x)
| MApp : forall s1 re1 s2 re2,
exp_match s1 re1 ->
exp_match s2 re2 ->
exp_match (s1 ++ s2) (App re1 re2)
| MUnionL : forall s1 re1 re2,
exp_match s1 re1 ->
exp_match s1 (Union re1 re2)
| MUnionR : forall re1 s2 re2,
exp_match s2 re2 ->
exp_match s2 (Union re1 re2)
| MStar0 : forall re, exp_match [] (Star re)
| MStarApp : forall s1 s2 re,
exp_match s1 re ->
exp_match s2 (Star re) ->
exp_match (s1 ++ s2) (Star re).
Notation "s =~ re" := (exp_match s re) (at level 80).
(* Leo: TODO *)
(* Derive ArbitrarySizedSuchThat for (fun n => exp_match n re). Derive SizedProofEqs for (fun n => exp_match n re). Derive SizeMonotonicSuchThatOpt for (fun n => exp_match n re). Derive GenSizedSuchThatCorrect for (fun n => exp_match n re). Derive GenSizedSuchThatSizeMonotonicOpt for (fun n => exp_match n re).   Fixpoint reg_exp_of_list {T} (l : list T) := match l with | [] => EmptyStr | x :: l' => App (Char x) (reg_exp_of_list l') end.  Lemma MStar1 : forall T s (re : reg_exp T) , s =~ re -> s =~ Star re. Admitted. (* Leo: TODO *)
*)
(** **** Exercise: 4 stars (re_not_empty)  *)
(** Write a recursive function [re_not_empty] that tests whether a regular expression matches some string. Prove that your function is correct. *)
Fixpoint re_not_empty {T : Type} (re : reg_exp T) : bool
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.  Lemma re_not_empty_correct : forall T (re : reg_exp T), (exists s, s =~ re) <-> re_not_empty re = true.  (** **** Exercise: 4 stars (exp_match_ex2)  *)
(** The [MStar''] lemma below (combined with its converse, the [MStar'] exercise above), shows that our definition of [exp_match] for [Star] is equivalent to the informal one given previously. *)
(** Now, the pumping lemma itself says that, if [s =~ re] and if the length of [s] is at least the pumping constant of [re], then [s] can be split into three substrings [s1 ++ s2 ++ s3] in such a way that [s2] can be repeated any number of times and the result, when combined with [s1] and [s3] will still match [re].  Since [s2] is also guaranteed not to be the empty string, this gives us a (constructive!) way to generate strings matching [re] that are as long as we like. *)

Lemma pumping : forall T (re : reg_exp T) s,
s =~ re ->
pumping_constant re <= length s ->
exists s1 s2 s3,
s = s1 ++ s2 ++ s3 /\
s2 <> [] /\
forall m, s1 ++ napp m s2 ++ s3 =~ re.