Section WeightTree.
Variable A : Type.
Variable f : A -> nat.
Fixpoint sum_leaves (t : btree A) : nat :=
match t with
| leaf n => f n
| node t1 t2 => sum_leaves t1 + sum_leaves t2
end.
Definition sum_order x y := sum_leaves x <= sum_leaves y.
Definition le_sum x y := le_bool (sum_leaves x) (sum_leaves y).
Proof using.
intros a b1; apply (le_bool_correct3 (sum_leaves a) (sum_leaves b1)).
Qed.
Proof using.
intros a b1; apply (le_bool_correct4 (sum_leaves a) (sum_leaves b1)).
Qed.
Fixpoint weight_tree (t : btree A) : nat :=
match t with
| leaf n => 0
| node t1 t2 =>
sum_leaves t1 + weight_tree t1 + (sum_leaves t2 + weight_tree t2)
end.
Definition weight_tree_list : list (btree A) -> nat :=
fold_right (fun x : btree A => plus (weight_tree x)) 0.
Proof using.
intros t1 t2 l; simpl in |- *; ring.
Qed.
Proof using.
intros l1 l2 H; elim H; auto.
simpl in |- *; auto; intros; ring.
simpl in |- *; auto; intros; ring.
intros l0 l3 l4 H0 H1 H2 H3; apply trans_equal with (1 := H1); auto.
Qed.
End WeightTree.
Arguments sum_leaves [A].
Arguments sum_order [A].
Arguments le_sum [A].
Arguments weight_tree [A].
Arguments weight_tree_list [A].

(* sum_leaves are the same for ordered list that are permutations one from the other *)
Theorem ordered_sum_leaves_eq :
forall (A : Type) (f : A -> nat) (l1 l2 : list (btree A)),
permutation l1 l2 ->
ordered (sum_order f) l1 ->
ordered (sum_order f) l2 -> map (sum_leaves f) l1 = map (sum_leaves f) l2.