intros.
assert (exists i : Nat, n =' S i + m in _).
clear H H0.
induction  H1 as [| m0 H1 HrecH1].
exists 0; simpl in |- *; auto.
inversion_clear HrecH1.
exists (S x).
simpl in |- *.
apply f_equal with (f := S).
auto.
inversion_clear H2.
rename x into d.
generalize B C n H H0 H1 d H3.
clear H3 d H1 H0 H n C B.
induction m.
intros.
destruct n.
inversion_clear H1.
generalize (n_element_subset_sequence H); intro p; inversion_clear p.
exists (x (Build_finiteT H1)).
inversion_clear H2.
split.
apply in_part_comp_r with (seq_set x); auto with algebra.
simpl in |- *.
exists (Build_finiteT H1); auto with algebra.
generalize (n_element_subset_sequence H0); intro p; inversion_clear p.
inversion_clear H2.
intro.
assert (in_part (x (Build_finiteT H1)) (empty A)).
apply in_part_comp_r with (seq_set x0); auto with algebra.
apply in_part_comp_r with C; auto with algebra.
simpl in H8.
auto.
intros.
generalize (n_element_subset_sequence H0); intro p; inversion_clear p.
inversion_clear H2.
case (classic (in_part (head x) B)).
destruct n.
inversion_clear H1.
generalize (n_element_subset_sequence H); intro p; inversion_clear p.
inversion_clear H2.
intro.
assert (in_part (head x) (seq_set x0)).
apply in_part_comp_r with B; auto with algebra.
simpl in H8.
inversion_clear H8.
rename x1 into i.
rename x0 into Bseq.
set (B' := seq_set (omit Bseq i)) in *.
set (C' := seq_set (Seqtl x)) in *.
generalize (IHm B' C' n).
assert (has_n_elements n B').
apply seq_set_n_element_subset; auto with algebra.
exists (omit Bseq i).
split; auto with algebra.
apply omit_preserves_distinct with (i := i); auto with algebra.
intro q; generalize (q H8); clear H8 q; intro.
assert (has_n_elements m C').
apply seq_set_n_element_subset; auto with algebra.
exists (Seqtl x); split; auto with algebra.
apply Seqtl_preserves_distinct with (v := x); auto with algebra.
assert (m < n); auto with arith.
assert (n = S d + m).
apply eq_add_S; auto with algebra.
transitivity (S d + S m).
auto.
symmetry  in |- *.
transitivity (S (S d) + m); auto.
apply plus_Snm_nSm.
generalize (H8 H10 H11 d H12); clear H12 H11 H10 H8; intro.
inversion_clear H8.
rename x0 into a; exists a.
inversion_clear H10.
split.
unfold B' in H8.
change (exists j : fin _, a =' omit Bseq i j in _) in H8.
inversion_clear H8.
rename x0 into j.
apply in_part_comp_l with (omit Bseq i j); auto with algebra.
apply in_part_comp_r with (seq_set Bseq); auto with algebra.
apply omit_seq_in_seq_set; auto with algebra.
apply not_inpart_comp_r with (seq_set x); auto with algebra.
simpl in |- *.
intro.
inversion_clear H10.
destruct x0.
rename index into xi.
destruct xi as [| n0].
assert (a =' head x in _).
apply Trans with (x (Build_finiteT in_range_prf)); auto with algebra;
unfold head in |- *; simpl in |- *.
generalize distinct_omit_removes_all; intro q; red in q.
unfold B' in H8.
change (exists j : fin _, a =' omit Bseq i j in _) in H8.
inversion_clear H8.
rename x0 into j.
apply (q _ _ _ H7 i j).
apply Trans with a; auto with algebra.
apply Trans with (head x); auto with algebra.
assert (in_part a C').
simpl in |- *.
exists (Build_finiteT (lt_S_n _ _ in_range_prf)).
apply Trans with (x (Build_finiteT in_range_prf)); auto with algebra.
apply H11; auto with algebra.
(***********)
intro.
set (C' := seq_set (Seqtl x)) in *.
generalize (IHm B C' n H).
assert (has_n_elements m C').
apply seq_set_n_element_subset; auto with algebra.
exists (Seqtl x); split; auto with algebra.
apply Seqtl_preserves_distinct with (v := x); auto with algebra.
assert (m < n); auto with arith.
intro.
generalize (H8 H6 H7); clear H8; intro.
simpl in n; assert (n = S (S d) + m).
simpl in |- *; transitivity (S d + S m); auto.
symmetry  in |- *.
replace (S (S (d + m))) with (S (S d) + m); auto with arith.
apply plus_Snm_nSm.
generalize (H8 _ H9); clear H9 H8 H7; intro.
inversion_clear H7.
rename x0 into a.
inversion_clear H8.
exists a; split; auto.
apply not_inpart_comp_r with (seq_set x); auto with algebra.
simpl in |- *.
intro.
inversion_clear H8.
destruct x0.
rename index into xi.
destruct xi as [| n0].
assert (a =' head x in _).
apply Trans with (x (Build_finiteT in_range_prf)); auto with algebra;
unfold head in |- *; simpl in |- *.
apply H2; auto with algebra.
apply in_part_comp_l with a; auto with algebra.
apply H9; auto with algebra.
simpl in |- *.
exists (Build_finiteT (lt_S_n _ _ in_range_prf)).
apply Trans with (x (Build_finiteT in_range_prf)); auto with algebra.
Qed.

(* Specifications: *)
Lemma inject_subsets_preserves_has_n_elements :
forall (A : Setoid) (B : part_set A) (C : part_set B) (n : Nat),
has_n_elements n C -> has_n_elements n (inject_subsets C).