Definition strat (n:nat) (p:predicate) : sinv n :=
    proj1_sig (stratify (proj1_sig p) (proj2_sig p) n).Definition unstrat (n:nat) (p:sinv n) : predicate :=
    exist hered (unstratify n p) (unstratify_hered n p).Definition squash (x:nat * F predicate) : knot :=
    match x with (n,f) => existT (F_sinv) n (fmap F (strat n) (unstrat n) f) end.Definition unsquash (k:knot) : nat * F predicate :=
    match k with existT _ n f => (n, fmap F (unstrat n) (strat n) f) end.Definition knot_level_def (k:knot) : nat :=
    fst (unsquash k).Definition knot_age1_def (k:knot) : option knot :=
    match unsquash k with
    | (O,_) => None
    | (S n,x) => Some (squash (n,x))
    end.Definition knot_unage_def (k:knot) :=
    let (n,k) := unsquash k in squash (S n,k).Program Definition approx (n:nat) (p:predicate) : predicate :=
    fun w => if (le_gt_dec n (knot_level_def (fst w))) then T_bot else proj1_sig p w.

(* Specifications: *)
Lemma strat_unstrat : forall n, strat n oo unstrat n = id (sinv n).
Lemma predicate_eq : forall (p1 p2:predicate), proj1_sig p1 = proj1_sig p2 -> p1 = p2.
Lemma unstrat_strat : forall n, unstrat n oo strat n = approx n.
Lemma squash_unsquash : forall k, squash (unsquash k) = k.
Lemma unsquash_squash : forall n f, unsquash (squash (n,f)) = (n, fmap F (approx n) (approx n) f).
Lemma strat_Sx_unstrat : forall x, sinv_unage x = strat (S x) oo unstrat x.
Lemma strat_unstrat_Sx : forall x, sinv_age x = strat x oo unstrat (S x).
Lemma age1_eq : forall k, age1_def k = knot_age1_def k.
Lemma unsquash_inj : forall k1 k2, unsquash k1 = unsquash k2 -> k1 = k2.
Lemma pred_ext : forall (p1 p2:predicate), (forall x, proj1_sig p1 x = proj1_sig p2 x) -> p1 = p2.
Lemma approx_spec : forall n p ko, proj1_sig (approx n p) ko = if (le_gt_dec n (knot_level_def (fst ko))) then T_bot else proj1_sig p ko.
Lemma ag_knot_facts : ageable_facts knot knot_level_def knot_age1_def.