Require Import Orders.
Require Import Equivalence.
Require Import EquivDec.
Require Import Permutation.
Require Import Compare_dec.
Require Import Lia.
Require Import String.
Require Import List.
Require Import ZArith.
Require Import CoqLibAdd.
Require Import StringAdd.
Require Import Lift.
Require Import LiftIterators.
Require Import Bindings.
Require Import SortingAdd.
Section SortableItem.
Inductive sdata :=
|
sdnat :
Z ->
sdata
|
sdstring :
string ->
sdata
.
Equality is decidable for sdata
Lemma sdata_eq_dec :
forall x y:
sdata, {
x=
y}+{
x<>
y}.
Proof.
destruct x;
destruct y;
try solve[
right;
inversion 1].
-
destruct (
Z.eq_dec z z0).
+
left;
f_equal;
trivial.
+
right;
intro;
apply n;
inversion H;
trivial.
-
destruct (
string_dec s s0).
+
left;
f_equal;
trivial.
+
right;
intro;
apply n;
inversion H;
trivial.
Defined.
Global Instance sdata_eqdec :
EqDec sdata eq :=
sdata_eq_dec.
End SortableItem.
Module SortableDataOrder <:
OrderedTypeFull with Definition t:=
sdata.
Definition t:=
sdata.
Definition eq := @
eq t.
Definition eq_equiv : (
Equivalence eq) :=
eq_equivalence.
Definition eq_dec :=
sdata_eq_dec.
Definition compare (
d1 d2:
t) :
comparison :=
match d1,
d2 with
|
sdnat n,
sdstring s =>
Lt
|
sdstring s,
sdnat n =>
Gt
|
sdnat n1,
sdnat n2 =>
Z.compare n1 n2
|
sdstring s1,
sdstring s2 =>
StringOrder.compare s1 s2
end.
Definition lt (
d1 d2:
sdata) :
Prop
:=
compare d1 d2 =
Lt.
Lemma compare_spec :
forall x y :
sdata,
CompareSpec (
eq x y) (
lt x y) (
lt y x) (
compare x y).
Proof.
Lemma trichotemy a b : {
lt a b} + {
eq a b} + {
lt b a}.
Proof.
generalize (
compare_spec a b);
intros nc.
destruct (
compare a b);
[
left;
right|
left;
left|
right];
inversion nc;
trivial.
Defined.
Lemma compare_refl_eq a:
compare a a =
Eq.
Proof.
Lemma compare_eq_iff a b:
compare a b =
Eq <->
a =
b.
Proof.
Global Instance lt_strorder :
StrictOrder lt.
Proof.
Lemma lt_compat :
Proper (
eq ==>
eq ==>
iff)
lt.
Proof.
Program Definition lt_dec (
a b:
sdata) : {
lt a b} + {~
lt a b}
:=
match compare a b with
|
Lt =>
left _
|
Eq =>
right _
|
Gt =>
right _
end.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
trivial.
Qed.
Next Obligation.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
intro l2.
apply (
asymmetry H0 l2).
Qed.
Definition le (
a b:
sdata) :=
match compare a b with
|
Lt =>
True
|
Eq =>
True
|
Gt =>
False
end.
Definition gt (
a b:
sdata) :=
match compare a b with
|
Lt =>
False
|
Eq =>
False
|
Gt =>
True
end.
Lemma le_lteq :
forall x y :
t,
le x y <->
lt x y \/
eq x y.
Proof.
intros.
generalize (
compare_spec x y);
inversion 1;
unfold le,
lt,
eq in *;
case_eq (
compare x y);
intuition congruence.
Qed.
Program Definition le_dec (
a b:
sdata) : {
le a b} + {~
le a b}
:=
match compare a b with
|
Lt =>
left _
|
Eq =>
left _
|
Gt =>
right _
end.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
apply le_lteq.
intuition.
Qed.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
apply le_lteq.
intuition.
Qed.
Next Obligation.
Lemma le_not_gt a b :
le a b -> ~(
gt a b).
Proof.
unfold not;
intros.
unfold le,
gt in *.
destruct (
compare a b);
simpl in *;
congruence.
Qed.
Lemma compare_transitive x y z c:
compare x y =
c ->
compare y z =
c ->
compare x z =
c.
Proof.
End SortableDataOrder.
Section LexicographicData.
Equality is decidable for lists of sortable data
Lemma list_sdata_eq_dec :
forall x y:
list sdata, {
x=
y}+{
x<>
y}.
Proof.
induction x;
destruct y;
try solve[
right;
inversion 1].
-
left;
reflexivity.
-
destruct (
sdata_eq_dec a s).
+
subst.
destruct (
IHx y);
subst.
left;
reflexivity.
right;
inversion 1;
auto.
+
right;
inversion 1;
auto.
Defined.
Global Instance list_sdata_eqdec :
EqDec (
list sdata)
eq :=
list_sdata_eq_dec.
End LexicographicData.
Module LexicographicDataOrder <:
OrderedTypeFull with Definition t:=
list sdata.
Definition t :=
list sdata.
Definition eq := @
eq t.
Definition eq_equiv : (
Equivalence eq) :=
eq_equivalence.
Definition eq_dec :=
list_sdata_eq_dec.
Fixpoint compare (
l1 l2:
list sdata) :
comparison :=
match l1,
l2 with
|
nil,
nil =>
Eq
|
nil,
_ ::
_ =>
Lt
|
_ ::
_,
nil =>
Gt
|
d1 ::
l1',
d2 ::
l2' =>
match SortableDataOrder.compare d1 d2 with
|
Lt =>
Lt
|
Eq =>
compare l1'
l2'
|
Gt =>
Gt
end
end.
Definition lt (
l1 l2:
t) :
Prop
:=
compare l1 l2 =
Lt.
Lemma compare_spec :
forall x y :
t,
CompareSpec (
eq x y) (
lt x y) (
lt y x) (
compare x y).
Proof.
Lemma trichotemy a b : {
lt a b} + {
eq a b} + {
lt b a}.
Proof.
generalize (
compare_spec a b);
intros nc.
destruct (
compare a b);
[
left;
right|
left;
left|
right];
inversion nc;
trivial.
Defined.
Lemma compare_refl_eq a:
compare a a =
Eq.
Proof.
Lemma compare_eq_iff a b:
compare a b =
Eq <->
a =
b.
Proof.
Lemma compare_transitive x y z c:
compare x y =
c ->
compare y z =
c ->
compare x z =
c.
Proof.
Global Instance lt_strorder :
StrictOrder lt.
Proof.
Lemma lt_compat :
Proper (
eq ==>
eq ==>
iff)
lt.
Proof.
Program Definition lt_dec (
a b:
list sdata) : {
lt a b} + {~
lt a b}
:=
match compare a b with
|
Lt =>
left _
|
Eq =>
right _
|
Gt =>
right _
end.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
trivial.
Qed.
Next Obligation.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
intro l2.
apply (
asymmetry H0 l2).
Qed.
Definition le (
a b:
t) :=
match compare a b with
|
Lt =>
True
|
Eq =>
True
|
Gt =>
False
end.
Lemma le_lteq :
forall x y :
t,
le x y <->
lt x y \/
eq x y.
Proof.
intros.
generalize (
compare_spec x y);
inversion 1;
unfold le,
lt,
eq in *;
case_eq (
compare x y);
intuition congruence.
Qed.
Program Definition le_dec (
a b:
t) : {
le a b} + {~
le a b}
:=
match compare a b with
|
Lt =>
left _
|
Eq =>
left _
|
Gt =>
right _
end.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
apply le_lteq.
intuition.
Qed.
Next Obligation.
generalize (
compare_spec a b);
rewrite <-
Heq_anonymous;
inversion 1.
apply le_lteq.
intuition.
Qed.
Next Obligation.
Lemma lt_transitive (
x y z:
t) :
lt x y ->
lt y z ->
lt x z.
Proof.
Lemma le_transitive (
x y z:
t) :
le x y ->
le y z ->
le x z.
Proof.
repeat (
rewrite le_lteq);
intros.
elim H;
elim H0;
intros;
clear H;
clear H0.
-
left;
revert H2 H1;
apply StrictOrder_Transitive.
-
rewrite H1 in H2;
left;
assumption.
-
rewrite H2;
left;
assumption.
-
rewrite H1 in H2;
rewrite H2;
right;
reflexivity.
Qed.
Lemma flip_not_le l l0:
~
le l l0 ->
le l0 l.
Proof.
intros.
unfold le in *.
unfold not in *.
case_eq (
compare l l0);
intros;
rewrite H0 in H;
try congruence.
-
assert False by (
apply H;
trivial);
contradiction.
-
assert False by (
apply H;
trivial);
contradiction.
-
case_eq (
compare l0 l);
intros;
try trivial.
assert (
compare l l =
Gt)
by (
apply (
compare_transitive l l0 l);
assumption).
assert (
compare l l =
Eq).
rewrite compare_eq_iff;
reflexivity.
congruence.
Qed.
End LexicographicDataOrder.
Section DictSort.
Program Instance ODT_lexdata : (@
ODT (
list sdata))
:=
mkODT _ _ LexicographicDataOrder.lt
LexicographicDataOrder.lt_strorder
LexicographicDataOrder.lt_dec
LexicographicDataOrder.compare _.
Next Obligation.
Can be sorted:
- Empty collection
- Collection of integers
- Collection of strings
Context {
A:
Set}.
Definition sortable_data :
Set := (
list sdata) *
A.
Definition sortable_coll :
Set :=
list sortable_data.
Definition dict_field_le (
a b:
sortable_data) :=
LexicographicDataOrder.le (
fst a) (
fst b).
Lemma dict_field_le_dec (
a b:
sortable_data) :
{
dict_field_le a b} + {~
dict_field_le a b}.
Proof.
Lemma dict_field_le_transitive :
forall x y z :
sortable_data,
dict_field_le x y ->
dict_field_le y z ->
dict_field_le x z.
Proof.
Definition dict_sort :=
@
insertion_sort ((
list sdata)*
A)
dict_field_le dict_field_le_dec.
Lemma dict_sort_sorted (
l:
sortable_coll) :
is_list_sorted dict_field_le_dec (
dict_sort l) =
true.
Proof.
Lemma dict_sort_StronglySorted (
l:
sortable_coll) :
StronglySorted dict_field_le (
dict_sort l).
Proof.
Definition sort_sortable_coll (
sc:
sortable_coll) :
sortable_coll :=
dict_sort sc.
Definition coll_of_sortable_coll (
sc:
sortable_coll) :
list A :=
map snd sc.
Lemma dict_field_le_anti :
forall x y :
sortable_data, ~
dict_field_le x y -> ~
dict_field_le y x ->
x =
y.
Proof.
Lemma in_sort_sortable d l :
In d (
sort_sortable_coll l) <->
In d l.
Proof.
Lemma in_csc_ssc d l :
In d (
coll_of_sortable_coll (
sort_sortable_coll l)) <->
In d (
coll_of_sortable_coll l).
Proof.
Lemma in_csc_cons d s l :
In d (
coll_of_sortable_coll (
s ::
l)) <->
(
d =
snd s \/
In d (
coll_of_sortable_coll l)).
Proof.
unfold coll_of_sortable_coll.
repeat rewrite in_map_iff.
destruct s;
simpl.
split;
intros ind.
-
destruct ind as [[? ?] [?
ind]];
simpl in *;
subst.
destruct ind.
+
invcs H;
tauto.
+
right.
exists (
l1,
d);
auto.
-
destruct ind as [| [[??] [??]]].
+
subst.
exists (
l0,
a);
auto.
+
simpl in *;
subst.
exists (
l1,
d);
auto.
Qed.
Lemma flip_not_dict_field_le a a0:
~
dict_field_le a a0 ->
dict_field_le a0 a.
Proof.
Lemma insertion_sort_insert_perm (
l:
list sortable_data) (
a:
sortable_data) :
Permutation (
a::
l) (
insertion_sort_insert dict_field_le_dec a l).
Proof.
Lemma insertion_sort_on_perm_insert_perm (
l l':
list sortable_data) (
a:
sortable_data) :
Permutation l l' ->
Permutation (
a::
l) (
insertion_sort_insert dict_field_le_dec a l').
Proof.
Lemma dict_sort_permutation l :
Permutation (
dict_sort l)
l.
Proof.
End DictSort.
Section SortByGen.
Definition fget_criterias {
A:
Set}
(
d:
A) (
fl:
list (
A ->
option sdata)) :
option (
list sdata) :=
lift_map (
fun f =>
f d)
fl.
Definition fsortable_data_of_data {
A:
Set}
(
d:
A) (
fl:
list (
A ->
option sdata)) :
option sortable_data :=
lift (
fun c => (
c,
d)) (
fget_criterias d fl).
Definition fsortable_coll_of_coll {
A:
Set}
(
fl:
list (
A ->
option sdata)) (
coll:
list A) :
option (
list sortable_data)
:=
lift_map (
fun d =>
fsortable_data_of_data d fl)
coll.
Definition table_sort {
A:
Set} (
scl:
list (
A ->
option sdata))
(
coll:
list A) :
option (
list A) :=
lift coll_of_sortable_coll
(
lift sort_sortable_coll
(
fsortable_coll_of_coll scl coll)).
Lemma sort_sortable_coll_sorted {
A:
Set} (
l: @
sortable_coll A):
is_list_sorted dict_field_le_dec (
sort_sortable_coll l) =
true.
Proof.
Lemma lift_sort_sortable_coll_sorted {
A:
Set} (
scl:
list (
A ->
option sdata)) (
l1:
list A)
(
l2:
sortable_coll):
lift sort_sortable_coll (
fsortable_coll_of_coll scl l1) =
Some l2 ->
is_list_sorted dict_field_le_dec l2 =
true.
Proof.
Lemma sort_sortable_coll_StronglySorted {
A:
Set} (
l: @
sortable_coll A):
StronglySorted dict_field_le (
sort_sortable_coll l).
Proof.
Lemma lift_sort_sortable_coll_StronglySorted {
A:
Set} (
scl:
list (
A ->
option sdata))
(
l1:
list A)
(
l2:
sortable_coll) :
lift sort_sortable_coll (
fsortable_coll_of_coll scl l1) =
Some l2 ->
StronglySorted dict_field_le l2.
Proof.
Lemma fsortable_data_of_data_snd {
A:
Set} (
scl:
list (
A ->
option sdata))
a s :
fsortable_data_of_data a scl =
Some s ->
a =
snd s.
Proof.
Lemma lift_map_sortable_data_perm {
A:
Set} (
scl:
list (
A ->
option sdata))
l l':
lift_map (
fun d :
A =>
fsortable_data_of_data d scl)
l =
Some l' ->
Permutation (
map snd l')
l.
Proof.
Lemma sort_sortable_coll_permuation {
A:
Set} (
scl:
list (
A ->
option sdata))
l l1 :
fsortable_coll_of_coll scl l1 =
Some l ->
Permutation l1 (
coll_of_sortable_coll (
sort_sortable_coll l)).
Proof.
End SortByGen.