%{
This is an extended example of a proof of correctness of mergesort for lists without duplicates. In particular, it is an example of showing that an implementation of sorting (mergesort) matches up with a declarative definition that relates a list to its sort (i.e. the sorted list is a permutation of the unsorted list).
}%
%{
=== Definitions ===
==== Declarative definitions ====
We must first define natural numbers, lists of natural numbers, comparison on natural numbers, and what it means for one list to be the sorted version of another.
}%
nat : type.
z : nat.
s : nat -> nat.
nat-less : nat -> nat -> type.
nat-less/z : nat-less z (s _).
nat-less/s : nat-less (s N) (s N')
<- nat-less N N'.
nat-list : type.
nat-list/nil : nat-list.
nat-list/cons : nat -> nat-list -> nat-list.
nat-list-head-less : nat -> nat-list -> type.
nat-list-head-less/nil : nat-list-head-less N nat-list/nil.
nat-list-head-less/cons : nat-list-head-less N (nat-list/cons N' _)
<- nat-less N N'.
nat-list-sorted : nat-list -> type.
nat-list-sorted/nil : nat-list-sorted nat-list/nil.
nat-list-sorted/cons : nat-list-sorted (nat-list/cons N NL)
<- nat-list-head-less N NL
<- nat-list-sorted NL.
in-nat-list : nat -> nat-list -> type.
in-nat-list/hit : in-nat-list N (nat-list/cons N NL).
in-nat-list/miss: in-nat-list N (nat-list/cons N' NL)
<- in-nat-list N NL.
all-in-nat-list : nat-list -> nat-list -> type.
all-in-nat-list/nil : all-in-nat-list nat-list/nil NL.
all-in-nat-list/cons : all-in-nat-list (nat-list/cons N NL) NL'
<- in-nat-list N NL'
<- all-in-nat-list NL NL'.
%{
For the purposes of this proof, we use a set-theoretic extensional definition of permutation, where two lists are permutations of each other if they contain the same set of elements. This is only a proper definition of permutation if we assume both lists contain no duplicates. This invariant is baked into both our definition of sorted and our definition of mergesort.
}%
nat-list-permute : nat-list -> nat-list -> type.
nat-list-permute/i : nat-list-permute NL NL'
<- all-in-nat-list NL NL'
<- all-in-nat-list NL' NL.
nat-list-declarative-sort : nat-list -> nat-list -> type.
nat-list-declarative-sort/i : nat-list-declarative-sort NL NL'
<- nat-list-permute NL NL'
<- nat-list-sorted NL'.
%{
==== Definitions used to define mergesort ====
}%
split : nat-list -> nat-list -> nat-list -> type.
split/nil : split nat-list/nil nat-list/nil nat-list/nil.
split/1 : split (nat-list/cons N nat-list/nil) (nat-list/cons N nat-list/nil)
nat-list/nil.
split/cons : split (nat-list/cons N (nat-list/cons N' NL))
(nat-list/cons N NL1)
(nat-list/cons N' NL2)
<- split NL NL1 NL2.
merge : nat-list -> nat-list -> nat-list -> type.
merge/nil-1 : merge nat-list/nil N N.
merge/nil-2 : merge (nat-list/cons N NL) nat-list/nil (nat-list/cons N NL).
merge/cons-1 : merge (nat-list/cons N1 NL1)
(nat-list/cons N2 NL2)
(nat-list/cons N1 NL)
<- nat-less N1 N2
<- merge NL1 (nat-list/cons N2 NL2) NL.
merge/cons-2 : merge (nat-list/cons N1 NL1)
(nat-list/cons N2 NL2)
(nat-list/cons N2 NL)
<- nat-less N2 N1
<- merge NL2 (nat-list/cons N1 NL1) NL.
mergesort : nat-list -> nat-list -> type.
mergesort/nil : mergesort nat-list/nil nat-list/nil.
mergesort/1 : mergesort (nat-list/cons N nat-list/nil)
(nat-list/cons N nat-list/nil).
mergesort/cons : mergesort NL1 NL2
<- split NL1 NLA NLB
<- mergesort NLA NLA'
<- mergesort NLB NLB'
<- merge NLA' NLB' NL2.
%{ === Helper definitions used in proofs ===
all-in-2 N1 N2 N3 is a judgment that holds when all the elements in N1 are in the union of N1 and N2/
}%
% all-in-2 N1 N2 N3, everything in N1 is either in N2 or N3
all-in-2 : nat-list -> nat-list -> nat-list -> type.
all-in-2/nil : all-in-2 nat-list/nil NL1 NL2.
all-in-2/cons-1 : all-in-2 (nat-list/cons N NL) NL1 NL2
<- in-nat-list N NL1
<- all-in-2 NL NL1 NL2.
all-in-2/cons-2 : all-in-2 (nat-list/cons N NL) NL1 NL2
<- in-nat-list N NL2
<- all-in-2 NL NL1 NL2.
%{ === Proof that mergesort returns a sorted result === }%
nat-less-trans : nat-less N1 N2
-> nat-less N2 N3
-> nat-less N1 N3
-> type.
%mode nat-less-trans +D1 +D2 -D3.
- : nat-less-trans nat-less/z D1 nat-less/z.
- : nat-less-trans (nat-less/s D1) (nat-less/s D2) (nat-less/s D3)
<- nat-less-trans D1 D2 D3.
%worlds () (nat-less-trans _ _ _).
%total (D1) (nat-less-trans D1 _ _).
merge-head-less : nat-list-head-less N NL
-> nat-less N N'
-> merge NL (nat-list/cons N' NL') NL''
-> nat-list-head-less N NL''
-> type.
%mode merge-head-less +D1 +D2 +D3 -D4.
- : merge-head-less _ DL merge/nil-1 (nat-list-head-less/cons DL).
- : merge-head-less _ DL (merge/cons-2 _ _)
(nat-list-head-less/cons DL).
- : merge-head-less (nat-list-head-less/cons DL) _
(merge/cons-1 _ _)
(nat-list-head-less/cons DL).
%worlds () (merge-head-less _ _ _ _).
%total (D1) (merge-head-less _ _ D1 _).
merge-sorted : nat-list-sorted NL1
-> nat-list-sorted NL2
-> merge NL1 NL2 NL3
-> nat-list-sorted NL3
-> type.
%mode merge-sorted +D1 +D2 +D3 -D4.
- : merge-sorted _ D1 merge/nil-1 D1.
- : merge-sorted D1 _ merge/nil-2 D1.
- : merge-sorted (nat-list-sorted/cons D1 DHL) D2
(merge/cons-1 DM DL)
(nat-list-sorted/cons DS DHL')
<- merge-head-less DHL DL DM DHL'
<- merge-sorted D1 D2 DM DS.
- : merge-sorted D2 (nat-list-sorted/cons D1 DHL)
(merge/cons-2 DM DL)
(nat-list-sorted/cons DS DHL')
<- merge-head-less DHL DL DM DHL'
<- merge-sorted D1 D2 DM DS.
%worlds () (merge-sorted _ _ _ _).
%total (D1) (merge-sorted _ _ D1 _).
mergesort-sorted : mergesort NL NL'
-> nat-list-sorted NL'
-> type.
%mode mergesort-sorted +D1 -D2.
- : mergesort-sorted mergesort/nil nat-list-sorted/nil.
- : mergesort-sorted mergesort/1 (nat-list-sorted/cons nat-list-sorted/nil nat-list-head-less/nil).
- : mergesort-sorted (mergesort/cons DM D2 D1 _) DS
<- mergesort-sorted D1 DS1
<- mergesort-sorted D2 DS2
<- merge-sorted DS1 DS2 DM DS.
%worlds () (mergesort-sorted _ _).
%total (D1) (mergesort-sorted D1 _).
%{ === Proof that mergesort returns a permutation of the input === }%
all-in-2-wkn-l : {N}
all-in-2 NL NA NB
-> all-in-2 NL (nat-list/cons N NA) NB
-> type.
%mode all-in-2-wkn-l +D1 +D2 -D3.
- : all-in-2-wkn-l _ all-in-2/nil all-in-2/nil.
- : all-in-2-wkn-l _ (all-in-2/cons-1 DHL DIN)
(all-in-2/cons-1 DHL' (in-nat-list/miss DIN))
<- all-in-2-wkn-l _ DHL DHL'.
- : all-in-2-wkn-l _ (all-in-2/cons-2 DHL DIN)
(all-in-2/cons-2 DHL' DIN)
<- all-in-2-wkn-l _ DHL DHL'.
%worlds () (all-in-2-wkn-l _ _ _).
%total (D1) (all-in-2-wkn-l _ D1 _).
all-in-2-wkn-r : {N}
all-in-2 NL NA NB
-> all-in-2 NL NA (nat-list/cons N NB)
-> type.
%mode all-in-2-wkn-r +D1 +D2 -D3.
- : all-in-2-wkn-r _ all-in-2/nil all-in-2/nil.
- : all-in-2-wkn-r _ (all-in-2/cons-2 DHL DIN)
(all-in-2/cons-2 DHL' (in-nat-list/miss DIN))
<- all-in-2-wkn-r _ DHL DHL'.
- : all-in-2-wkn-r _ (all-in-2/cons-1 DHL DIN)
(all-in-2/cons-1 DHL' DIN)
<- all-in-2-wkn-r _ DHL DHL'.
%worlds () (all-in-2-wkn-r _ _ _).
%total (D1) (all-in-2-wkn-r _ D1 _).
split-all-in-2 : split NL NA NB
-> all-in-2 NL NA NB
-> type.
%mode split-all-in-2 +D1 -D2.
- : split-all-in-2 split/nil all-in-2/nil.
- : split-all-in-2 split/1
(all-in-2/cons-1 all-in-2/nil in-nat-list/hit).
- : split-all-in-2 (split/cons DS1)
(all-in-2/cons-1
(all-in-2/cons-2 DS1''' in-nat-list/hit) in-nat-list/hit)
<- split-all-in-2 DS1 DS1'
<- all-in-2-wkn-l _ DS1' DS1''
<- all-in-2-wkn-r _ DS1'' DS1'''.
%worlds () (split-all-in-2 _ _).
%total (D1) (split-all-in-2 D1 _).
all-in-nat-list-wkn : {N}
all-in-nat-list NL NL'
-> all-in-nat-list NL (nat-list/cons N NL')
-> type.
%mode all-in-nat-list-wkn +D1 +D2 -D3.
- : all-in-nat-list-wkn _ all-in-nat-list/nil all-in-nat-list/nil.
- : all-in-nat-list-wkn _ (all-in-nat-list/cons DAS DIN)
(all-in-nat-list/cons DAS' (in-nat-list/miss DIN))
<- all-in-nat-list-wkn _ DAS DAS'.
%worlds () (all-in-nat-list-wkn _ _ _).
%total (D1) (all-in-nat-list-wkn _ D1 _).
all-in-nat-list-refl : {NL}
all-in-nat-list NL NL
-> type.
%mode all-in-nat-list-refl +D1 -D2.
- : all-in-nat-list-refl _ all-in-nat-list/nil.
- : all-in-nat-list-refl (nat-list/cons _ NL)
(all-in-nat-list/cons DHL' in-nat-list/hit)
<- all-in-nat-list-refl NL DHL
<- all-in-nat-list-wkn _ DHL DHL'.
%worlds () (all-in-nat-list-refl _ _).
%total (D1) (all-in-nat-list-refl D1 _).
merge-all-in : merge NLA NLB NL
-> all-in-nat-list NLA NL
-> all-in-nat-list NLB NL
-> type.
%mode merge-all-in +D1 -D2 -D3.
- : merge-all-in merge/nil-1 all-in-nat-list/nil D1
<- all-in-nat-list-refl _ D1.
- : merge-all-in merge/nil-2 D1 all-in-nat-list/nil
<- all-in-nat-list-refl _ D1.
- : merge-all-in (merge/cons-1 DM1 DL)
(all-in-nat-list/cons DHL1' in-nat-list/hit)
DHL2'
<- merge-all-in DM1 DHL1 DHL2
<- all-in-nat-list-wkn _ DHL1 DHL1'
<- all-in-nat-list-wkn _ DHL2 DHL2'.
- : merge-all-in (merge/cons-2 DM1 DL)
DHL1'
(all-in-nat-list/cons DHL2' in-nat-list/hit)
<- merge-all-in DM1 DHL2 DHL1
<- all-in-nat-list-wkn _ DHL1 DHL1'
<- all-in-nat-list-wkn _ DHL2 DHL2'.
%worlds () (merge-all-in _ _ _).
%total (D1) (merge-all-in D1 _ _).
in-nat-list-trans : in-nat-list N NL
-> all-in-nat-list NL NL'
-> in-nat-list N NL'
-> type.
%mode in-nat-list-trans +D1 +D2 -D3.
- : in-nat-list-trans in-nat-list/hit
(all-in-nat-list/cons _ D1) D1.
- : in-nat-list-trans (in-nat-list/miss D1)
(all-in-nat-list/cons D _)
D1'
<- in-nat-list-trans D1 D D1'.
%worlds () (in-nat-list-trans _ _ _).
%total (D1) (in-nat-list-trans D1 _ _).
all-in-2-trans : all-in-2 NL NA NB
-> all-in-nat-list NA NL'
-> all-in-nat-list NB NL'
-> all-in-nat-list NL NL'
-> type.
%mode all-in-2-trans +D1 +D2 +D3 -D4.
- : all-in-2-trans all-in-2/nil _ _ all-in-nat-list/nil.
- : all-in-2-trans (all-in-2/cons-1 DHL DIN)
DA DB
(all-in-nat-list/cons DHL' DIN')
<- all-in-2-trans DHL DA DB DHL'
<- in-nat-list-trans DIN DA DIN'.
- : all-in-2-trans (all-in-2/cons-2 DHL DIN)
DA DB
(all-in-nat-list/cons DHL' DIN')
<- all-in-2-trans DHL DA DB DHL'
<- in-nat-list-trans DIN DB DIN'.
%worlds () (all-in-2-trans _ _ _ _).
%total (D1) (all-in-2-trans D1 _ _ _).
all-in-2-trans-a : all-in-2 NL NA NB
-> all-in-nat-list NA NA'
-> all-in-nat-list NB NB'
-> all-in-2 NL NA' NB'
-> type.
%mode all-in-2-trans-a +D1 +D2 +D3 -D4.
- : all-in-2-trans-a all-in-2/nil _ _ all-in-2/nil.
- : all-in-2-trans-a (all-in-2/cons-1 DHL DIN)
DA DB
(all-in-2/cons-1 DHL' DIN')
<- all-in-2-trans-a DHL DA DB DHL'
<- in-nat-list-trans DIN DA DIN'.
- : all-in-2-trans-a (all-in-2/cons-2 DHL DIN)
DA DB
(all-in-2/cons-2 DHL' DIN')
<- all-in-2-trans-a DHL DA DB DHL'
<- in-nat-list-trans DIN DB DIN'.
%worlds () (all-in-2-trans-a _ _ _ _).
%total (D1) (all-in-2-trans-a D1 _ _ _).
mergesort-all-in : mergesort NL1 NL2
-> all-in-nat-list NL1 NL2
-> type.
%mode mergesort-all-in +D1 -D2.
- : mergesort-all-in mergesort/nil all-in-nat-list/nil.
- : mergesort-all-in mergesort/1 (all-in-nat-list/cons all-in-nat-list/nil in-nat-list/hit).
- : mergesort-all-in (mergesort/cons Dmerge Dms2 Dms1 Dsplit)
DHLtwo''
<- split-all-in-2 Dsplit
(DHLtwo : all-in-2 NL NA NB)
<- mergesort-all-in Dms1
(DHL1 : all-in-nat-list NA NA')
<- mergesort-all-in Dms2 DHL2
<- merge-all-in Dmerge DHL3 DHL4
<- all-in-2-trans-a DHLtwo DHL1 DHL2 DHLtwo'
<- all-in-2-trans DHLtwo' DHL3 DHL4 DHLtwo''.
%worlds () (mergesort-all-in _ _).
%total (D1) (mergesort-all-in D1 _).
all-in-2-refl-r : {NL} {NL'}
all-in-2 NL NL' NL
-> type.
%mode all-in-2-refl-r +D1 +D2 -D3.
- : all-in-2-refl-r _ _ all-in-2/nil.
- : all-in-2-refl-r (nat-list/cons N NL) _
(all-in-2/cons-2 DHL' in-nat-list/hit)
<- all-in-2-refl-r NL _ DHL
<- all-in-2-wkn-r _ DHL DHL'.
%worlds () (all-in-2-refl-r _ _ _).
%total (D1) (all-in-2-refl-r D1 _ _).
all-in-2-refl-l : {NL} {NL'}
all-in-2 NL NL NL'
-> type.
%mode all-in-2-refl-l +D1 +D2 -D3.
- : all-in-2-refl-l _ _ all-in-2/nil.
- : all-in-2-refl-l (nat-list/cons N NL) _
(all-in-2/cons-1 DHL' in-nat-list/hit)
<- all-in-2-refl-l NL _ DHL
<- all-in-2-wkn-l _ DHL DHL'.
%worlds () (all-in-2-refl-l _ _ _).
%total (D1) (all-in-2-refl-l D1 _ _).
all-in-2-sym : all-in-2 NL NA NB
-> all-in-2 NL NB NA
-> type.
%mode all-in-2-sym +D1 -D2.
- : all-in-2-sym all-in-2/nil all-in-2/nil.
- : all-in-2-sym (all-in-2/cons-1 DHL DIN)
(all-in-2/cons-2 DHL' DIN)
<- all-in-2-sym DHL DHL'.
- : all-in-2-sym (all-in-2/cons-2 DHL DIN)
(all-in-2/cons-1 DHL' DIN)
<- all-in-2-sym DHL DHL'.
%worlds () (all-in-2-sym _ _).
%total (D1) (all-in-2-sym D1 _).
merge-all-in-2 : merge NA NB NL
-> all-in-2 NL NA NB
-> type.
%mode merge-all-in-2 +D1 -D2.
- : merge-all-in-2 merge/nil-1 D1
<- all-in-2-refl-r _ _ D1.
- : merge-all-in-2 merge/nil-2 D1
<- all-in-2-refl-l _ _ D1.
- : merge-all-in-2 (merge/cons-1 DM _)
(all-in-2/cons-1 DHL' in-nat-list/hit)
<- merge-all-in-2 DM DHL
<- all-in-2-wkn-l _ DHL DHL'.
- : merge-all-in-2 (merge/cons-2 DM _)
(all-in-2/cons-2 DHL'' in-nat-list/hit)
<- merge-all-in-2 DM DHL
<- all-in-2-wkn-l _ DHL DHL'
<- all-in-2-sym DHL' DHL''.
%worlds () (merge-all-in-2 _ _).
%total (D1) (merge-all-in-2 D1 _).
split-all-in : split NL NLA NLB
-> all-in-nat-list NLA NL
-> all-in-nat-list NLB NL
-> type.
%mode split-all-in +D1 -D2 -D3.
- : split-all-in split/nil all-in-nat-list/nil all-in-nat-list/nil.
- : split-all-in split/1 (all-in-nat-list/cons all-in-nat-list/nil in-nat-list/hit) all-in-nat-list/nil.
- : split-all-in (split/cons DS)
(all-in-nat-list/cons DHL'' in-nat-list/hit)
(all-in-nat-list/cons DBL'' (in-nat-list/miss in-nat-list/hit))
<- split-all-in DS DHL DBL
<- all-in-nat-list-wkn _ DHL DHL'
<- all-in-nat-list-wkn _ DHL' DHL''
<- all-in-nat-list-wkn _ DBL DBL'
<- all-in-nat-list-wkn _ DBL' DBL''.
%worlds () (split-all-in _ _ _).
%total (D1) (split-all-in D1 _ _).
mergesort-all-in-r : mergesort NLA NLB
-> all-in-nat-list NLB NLA
-> type.
%mode mergesort-all-in-r +D1 -D2.
- : mergesort-all-in-r mergesort/nil all-in-nat-list/nil.
- : mergesort-all-in-r mergesort/1 (all-in-nat-list/cons all-in-nat-list/nil in-nat-list/hit).
- : mergesort-all-in-r (mergesort/cons Dmerge Dms2 Dms1 Dsplit)
DHLtwo''
<- merge-all-in-2 Dmerge
(DHLtwo : all-in-2 NL NA NB)
<- mergesort-all-in-r Dms1
(DHL1 : all-in-nat-list NA NA')
<- mergesort-all-in-r Dms2 DHL2
<- split-all-in Dsplit DHL3 DHL4
<- all-in-2-trans-a DHLtwo DHL1 DHL2 DHLtwo'
<- all-in-2-trans DHLtwo' DHL3 DHL4 DHLtwo''.
%worlds () (mergesort-all-in-r _ _).
%total (D1) (mergesort-all-in-r D1 _).
mergesort-permute : mergesort N1 N2
-> nat-list-permute N1 N2
-> type.
%mode mergesort-permute +D1 -D2.
- : mergesort-permute D1 (nat-list-permute/i DB DA)
<- mergesort-all-in D1 DA
<- mergesort-all-in-r D1 DB.
%worlds () (mergesort-permute _ _).
%total {} (mergesort-permute _ _).
%{ === Final result ===
Showing the final result merely requires composing the two big intermediate results, namely that mergesort produces a sorted output and that mergesort's output is a permutation of the input.
}%
mergesort-correct : mergesort N1 N2
-> nat-list-declarative-sort N1 N2
-> type.
%mode mergesort-correct +D1 -D2.
- : mergesort-correct D1 (nat-list-declarative-sort/i Dsorted Dpermute)
<- mergesort-permute D1 Dpermute
<- mergesort-sorted D1 Dsorted.
%worlds () (mergesort-correct _ _).
%total {} (mergesort-correct _ _).
%{
----
== Equivalence of definitions of permutations ==
We can also show that nat-list-permute under the right constraints (implied by nat-list-sorted is equivalent to a definition of permutations as a composition of swaps.
Note: Maybe this should be its own article?
}%
all-in-nat-list-trans : all-in-nat-list N1 N2
-> all-in-nat-list N2 N3
-> all-in-nat-list N1 N3
-> type.
%mode all-in-nat-list-trans +D1 +D2 -D3.
- : all-in-nat-list-trans all-in-nat-list/nil _ all-in-nat-list/nil.
- : all-in-nat-list-trans (all-in-nat-list/cons D2 D1) D3
(all-in-nat-list/cons D5 D4)
<- in-nat-list-trans D1 D3 D4
<- all-in-nat-list-trans D2 D3 D5.
%worlds () (all-in-nat-list-trans _ _ _).
%total (D1) (all-in-nat-list-trans D1 _ _).
nat-list-permutes : nat-list -> nat-list -> type.
nat-list-permutes/nil : nat-list-permutes nat-list/nil nat-list/nil.
nat-list-permutes/cons : nat-list-permutes (nat-list/cons N1 NL)
(nat-list/cons N1 NL')
<- nat-list-permutes NL NL'.
nat-list-permutes/swap : nat-list-permutes
(nat-list/cons N1 (nat-list/cons N2 NL))
(nat-list/cons N2 (nat-list/cons N1 NL)).
nat-list-permutes/trans : nat-list-permutes N1 N3
<- nat-list-permutes N1 N2
<- nat-list-permutes N2 N3.
nat-list-permutes-all-in: nat-list-permutes N1 N2
-> all-in-nat-list N1 N2
-> type.
%mode nat-list-permutes-all-in +D1 -D2.
- : nat-list-permutes-all-in nat-list-permutes/nil
all-in-nat-list/nil.
- : nat-list-permutes-all-in (nat-list-permutes/cons D1)
(all-in-nat-list/cons D2' in-nat-list/hit)
<- nat-list-permutes-all-in D1 D2
<- all-in-nat-list-wkn _ D2 D2'.
- : nat-list-permutes-all-in nat-list-permutes/swap
(all-in-nat-list/cons
(all-in-nat-list/cons D1'' in-nat-list/hit)
(in-nat-list/miss in-nat-list/hit))
<- all-in-nat-list-refl _ D1
<- all-in-nat-list-wkn _ D1 D1'
<- all-in-nat-list-wkn _ D1' D1''.
- : nat-list-permutes-all-in (nat-list-permutes/trans D2 D1) D3'
<- nat-list-permutes-all-in D1 D1'
<- nat-list-permutes-all-in D2 D2'
<- all-in-nat-list-trans D1' D2' D3'.
%worlds () (nat-list-permutes-all-in _ _).
%total (D1) (nat-list-permutes-all-in D1 _).
nat-neq : nat -> nat -> type.
nat-neq/l : nat-neq N1 N2
<- nat-less N1 N2.
nat-neq/r : nat-neq N1 N2
<- nat-less N2 N1.
nin-nat-list : nat -> nat-list -> type.
nin-nat-list/nil : nin-nat-list N1 nat-list/nil.
nin-nat-list/cons : nin-nat-list N1 (nat-list/cons N2 NL)
<- nat-neq N1 N2
<- nin-nat-list N1 NL.
nat-list-no-dups : nat-list -> type.
nat-list-no-dups/nil : nat-list-no-dups nat-list/nil.
nat-list-no-dups/cons : nat-list-no-dups (nat-list/cons N1 NL)
<- nin-nat-list N1 NL
<- nat-list-no-dups NL.
nat-list-permutes-refl : {NL} nat-list-permutes NL NL
-> type.
%mode nat-list-permutes-refl +D1 -D2.
- : nat-list-permutes-refl nat-list/nil nat-list-permutes/nil.
- : nat-list-permutes-refl (nat-list/cons _ NL)
(nat-list-permutes/cons D1)
<- nat-list-permutes-refl NL D1.
%worlds () (nat-list-permutes-refl _ _).
%total (D1) (nat-list-permutes-refl D1 _).
nat-list-permutes-sym : nat-list-permutes N1 N2
-> nat-list-permutes N2 N1
-> type.
%mode nat-list-permutes-sym +D1 -D2.
- : nat-list-permutes-sym nat-list-permutes/nil nat-list-permutes/nil.
- : nat-list-permutes-sym (nat-list-permutes/cons D1)
(nat-list-permutes/cons D1')
<- nat-list-permutes-sym D1 D1'.
- : nat-list-permutes-sym nat-list-permutes/swap nat-list-permutes/swap.
- : nat-list-permutes-sym (nat-list-permutes/trans D2 D1)
(nat-list-permutes/trans D1' D2')
<- nat-list-permutes-sym D1 D1'
<- nat-list-permutes-sym D2 D2'.
%worlds () (nat-list-permutes-sym _ _).
%total (D1) (nat-list-permutes-sym D1 _).
nat-list-permutes-swap-head-2 : nat-list-permutes NN
(nat-list/cons N1 (nat-list/cons N2 NL))
-> nat-list-permutes
NN
(nat-list/cons N2 (nat-list/cons N1 NL))
-> type.
%mode nat-list-permutes-swap-head-2 +D1 -D4.
- : nat-list-permutes-swap-head-2 D1
(nat-list-permutes/trans nat-list-permutes/swap D1).
%worlds () (nat-list-permutes-swap-head-2 _ _).
%total {} (nat-list-permutes-swap-head-2 _ _).
in-nat-list-permutes : in-nat-list N1 NL
-> nat-list-permutes NL (nat-list/cons N1 NL')
-> type.
%mode in-nat-list-permutes +D1 -D2.
- : in-nat-list-permutes in-nat-list/hit D1
<- nat-list-permutes-refl _ D1.
- : in-nat-list-permutes
(in-nat-list/miss (D1 : in-nat-list N (nat-list/cons N2 NL)))
DP
<- in-nat-list-permutes D1
(DL : nat-list-permutes (nat-list/cons N2 NL)
(nat-list/cons N NL'))
<- nat-list-permutes-swap-head-2 (nat-list-permutes/cons DL) DP.
%worlds () (in-nat-list-permutes _ _).
%total (D1) (in-nat-list-permutes D1 _).
nin-nat-list-permutes : nin-nat-list N1 NL
-> nat-list-permutes NL NL'
-> nin-nat-list N1 NL'
-> type.
%mode nin-nat-list-permutes +D1 +D2 -D3.
- : nin-nat-list-permutes _ nat-list-permutes/nil nin-nat-list/nil.
- : nin-nat-list-permutes (nin-nat-list/cons D1 Dneq)
(nat-list-permutes/cons D2)
(nin-nat-list/cons D1' Dneq)
<- nin-nat-list-permutes D1 D2 D1'.
- : nin-nat-list-permutes
(nin-nat-list/cons (nin-nat-list/cons D1 Dneq2) Dneq1)
nat-list-permutes/swap
(nin-nat-list/cons (nin-nat-list/cons D1 Dneq1) Dneq2).
- : nin-nat-list-permutes D1 (nat-list-permutes/trans D3 D2)
D1''
<- nin-nat-list-permutes D1 D2 D1'
<- nin-nat-list-permutes D1' D3 D1''.
%worlds () (nin-nat-list-permutes _ _ _).
%total (D1) (nin-nat-list-permutes _ D1 _).
nat-neq-sym : nat-neq N1 N2
-> nat-neq N2 N1
-> type.
%mode nat-neq-sym +D1 -D2.
- : nat-neq-sym (nat-neq/l D1) (nat-neq/r D1).
- : nat-neq-sym (nat-neq/r D1) (nat-neq/l D1).
%worlds () (nat-neq-sym _ _).
%total {} (nat-neq-sym _ _).
no-dups-permutes : nat-list-no-dups N1
-> nat-list-permutes N1 N2
-> nat-list-no-dups N2
-> type.
%mode no-dups-permutes +D1 +D2 -D3.
- : no-dups-permutes _ nat-list-permutes/nil nat-list-no-dups/nil.
- : no-dups-permutes (nat-list-no-dups/cons D2 D1)
(nat-list-permutes/cons D3)
(nat-list-no-dups/cons D2' D1')
<- nin-nat-list-permutes D1 D3 D1'
<- no-dups-permutes D2 D3 D2'.
- : no-dups-permutes
(nat-list-no-dups/cons
(nat-list-no-dups/cons D3 DninB)
(nin-nat-list/cons DninA DneqA1))
nat-list-permutes/swap
(nat-list-no-dups/cons
(nat-list-no-dups/cons D3 DninA)
(nin-nat-list/cons DninB DneqA1'))
<- nat-neq-sym DneqA1 DneqA1'.
- : no-dups-permutes D1 (nat-list-permutes/trans D3 D2) D1''
<- no-dups-permutes D1 D2 D1'
<- no-dups-permutes D1' D3 D1''.
%worlds () (no-dups-permutes _ _ _).
%total (D1) (no-dups-permutes _ D1 _).
nat-list-length : nat-list -> nat -> type.
nat-list-length/z : nat-list-length nat-list/nil z.
nat-list-length/s : nat-list-length (nat-list/cons _ NL) (s N)
<- nat-list-length NL N.
permutes-length : nat-list-length NL N
-> nat-list-permutes NL NL'
-> nat-list-length NL' N
-> type.
%mode permutes-length +D1 +D2 -D3.
- : permutes-length _ nat-list-permutes/nil nat-list-length/z.
- : permutes-length (nat-list-length/s D1)
(nat-list-permutes/cons D2)
(nat-list-length/s D3)
<- permutes-length D1 D2 D3.
- : permutes-length (nat-list-length/s (nat-list-length/s D1))
nat-list-permutes/swap
(nat-list-length/s (nat-list-length/s D1)).
- : permutes-length D1 (nat-list-permutes/trans D3 D2)
D3'
<- permutes-length D1 D2 D1'
<- permutes-length D1' D3 D3'.
%worlds () (permutes-length _ _ _).
%total (D1) (permutes-length _ D1 _).
uninhabited : type.
nat-less-irrefl : nat-less N1 N1
-> uninhabited
-> type.
%mode nat-less-irrefl +D1 -D3.
- : nat-less-irrefl (nat-less/s D1) DU
<- nat-less-irrefl D1 DU.
%worlds () (nat-less-irrefl _ _).
%total (D1) (nat-less-irrefl D1 _).
nat-neq-irrefl : nat-neq N1 N1
-> uninhabited
-> type.
%mode nat-neq-irrefl +D1 -D2.
- : nat-neq-irrefl (nat-neq/l D1) DU
<- nat-less-irrefl D1 DU.
- : nat-neq-irrefl (nat-neq/r D1) DU
<- nat-less-irrefl D1 DU.
%worlds () (nat-neq-irrefl _ _).
%total {} (nat-neq-irrefl _ _).
uninhabited-in-nat-list : {N1}{NL}
uninhabited
-> in-nat-list N1 NL
-> type.
%mode uninhabited-in-nat-list +D1 +D2 +D3 -D4.
%worlds () (uninhabited-in-nat-list _ _ _ _).
%total {} (uninhabited-in-nat-list _ _ _ _).
in-nat-list-strengthen : nat-neq N1 NA
-> in-nat-list NA (nat-list/cons N1 NL')
-> in-nat-list NA NL'
-> type.
%mode in-nat-list-strengthen +D1 +D2 -D4.
- : in-nat-list-strengthen _ (in-nat-list/miss D1) D1.
- : in-nat-list-strengthen D1 in-nat-list/hit D1'
<- nat-neq-irrefl D1 DU
<- uninhabited-in-nat-list _ _ DU D1'.
%worlds () (in-nat-list-strengthen _ _ _).
%total (D1) (in-nat-list-strengthen _ D1 _).
all-in-strengthen : nin-nat-list N1 NL
-> all-in-nat-list NL (nat-list/cons N1 NL')
-> all-in-nat-list NL NL'
-> type.
%mode all-in-strengthen +D1 +D2 -D3.
- : all-in-strengthen _ all-in-nat-list/nil all-in-nat-list/nil.
- : all-in-strengthen (nin-nat-list/cons D1 Dneq)
(all-in-nat-list/cons DB DA)
(all-in-nat-list/cons DB' DA')
<- all-in-strengthen D1 DB DB'
<- in-nat-list-strengthen Dneq DA DA'.
%worlds () (all-in-strengthen _ _ _).
%total (D1) (all-in-strengthen _ D1 _).
all-in-no-dups-permutes : {N}
nat-list-no-dups NL
-> nat-list-length NL N
-> nat-list-length NL' N
-> all-in-nat-list NL NL'
-> nat-list-permutes NL NL'
-> type.
%mode all-in-no-dups-permutes +N +D1 +D2 +D3 +D4 -D5.
- : all-in-no-dups-permutes _ _ _ _ all-in-nat-list/nil
nat-list-permutes/nil.
- : all-in-no-dups-permutes
_
(nat-list-no-dups/cons D1 DNINN)
(nat-list-length/s Dl1)
DN
(all-in-nat-list/cons (DA : all-in-nat-list NL NL') DIN)
(nat-list-permutes/trans DP' (nat-list-permutes/cons DPP))
<- in-nat-list-permutes DIN
(DP : nat-list-permutes NL' (nat-list/cons N1 NL''))
<- nat-list-permutes-all-in DP
(DIN' : all-in-nat-list NL' (nat-list/cons N1 NL''))
<- permutes-length DN
DP (nat-list-length/s D3')
<- all-in-nat-list-trans DA DIN' DIN''
<- all-in-strengthen DNINN DIN'' DIN'''
<- all-in-no-dups-permutes _ D1 Dl1 D3' DIN''' DPP
<- nat-list-permutes-sym DP DP'.
%worlds () (all-in-no-dups-permutes _ _ _ _ _ _).
%total (D1) (all-in-no-dups-permutes D1 _ _ _ _ _).
%{
TODO: Finish commentary on the proof.
{{stub}}
}%