diff --git a/util/all.v b/util/all.v
index 25acc36ba7e9401eb2ac8d5ac29202e57bed0faa..892aad02c146e41dbe06e142bf9ee794f431c6a4 100644
--- a/util/all.v
+++ b/util/all.v
@@ -1,6 +1,7 @@
 Require Export rt.util.tactics.
 Require Export rt.util.notation.
 Require Export rt.util.bigcat.
+Require Export rt.util.pick.
 Require Export rt.util.bigord.
 Require Export rt.util.counting.
 Require Export rt.util.div_mod.
@@ -16,4 +17,4 @@ Require Export rt.util.sum.
 Require Export rt.util.minmax.
 Require Export rt.util.seqset.
 Require Export rt.util.step_function.
-Require Export rt.util.pick.
\ No newline at end of file
+Require Export rt.util.epsilon.
diff --git a/util/list.v b/util/list.v
index 4f82d0aad92628075e64278fcfe0bb2aef2ef316..e822d2314b2c06a72a305aa57cdec916249ec24b 100644
--- a/util/list.v
+++ b/util/list.v
@@ -109,6 +109,52 @@ Section UniqList.
   
 End UniqList.
 
+(* Additional lemmas about rem for lists. *)
+Section RemList.
+  
+  (* We prove that if x lies in xs excluding y, then x also lies in xs. *)
+  Lemma rem_in:
+    forall (T: eqType) (x y: T) (xs: seq T),
+      x \in rem y xs -> x \in xs.
+  Proof.
+    clear; intros.
+    induction xs; simpl in H.
+    { by rewrite in_nil in H. }
+    { rewrite in_cons; apply/orP.
+      destruct (a == y) eqn:EQ. 
+      { by move: EQ => /eqP EQ; subst a; right. }
+      { move: H; rewrite in_cons; move => /orP [/eqP H | H].
+        - by subst a; left.
+        - by right; apply IHxs.
+      }
+    }
+  Qed.
+
+  (* We prove that if we remove an element x for which P x from 
+     a filter, then the size of the filter decreases by 1. *)
+  Lemma filter_size_rem: 
+    forall (T: eqType) (x:T) (xs: seq T) (P: T -> bool), 
+      (x \in xs) ->
+      P x ->
+      size [seq y <- xs | P y] = size [seq y <- rem x xs | P y] + 1.
+  Proof.
+    clear; intros.
+    induction xs; first by inversion H.
+    move: H; rewrite in_cons; move => /orP [/eqP H | H]; subst.
+    { by simpl; rewrite H0 -[X in X = _]addn1 eq_refl. }
+    { specialize (IHxs H); simpl in *. 
+      case EQab: (a == x); simpl.
+      { move: EQab => /eqP EQab; subst.
+          by rewrite H0 addn1. }
+      { case Pa: (P a); simpl.
+        - by rewrite IHxs !addn1.
+        - by rewrite IHxs.
+      }
+    }
+  Qed.
+
+End RemList.
+
 (* Additional lemmas about list zip. *)
 Section Zip.
   
@@ -697,4 +743,89 @@ Section Order.
       rel x2 x1 ->
       x1 = x2.
 
-End Order.
\ No newline at end of file
+End Order.
+
+(* In this section we prove some additional lemmas about sequences. *)
+Section AdditionalLemmas.
+
+  (* We define a local function max over lists using foldl and maxn. *)
+  Let max := foldl maxn 0.
+  
+  (* We prove that max {x, xs} is equal to max {x, max xs}. *)
+  Lemma seq_max_cons: forall x xs, max (x :: xs) = maxn x (max xs).
+  Proof.
+    have L: forall s x xs, foldl maxn s (x::xs) = maxn x (foldl maxn s xs).
+    { clear; intros. 
+      generalize dependent s; generalize dependent x.
+      induction xs.
+      { by intros; rewrite maxnC. }
+      { intros; simpl in *.
+          by rewrite maxnC IHxs [maxn s a]maxnC IHxs maxnA [maxn s x]maxnC.
+      }
+    }
+      by intros; unfold max; apply L.
+  Qed.
+
+  (* We prove that for any two sequences xs and ys the fact that xs is a subsequence 
+     of ys implies that the size of xs is at most the size of ys. *)
+  Lemma subseq_leq_size:
+    forall {T: eqType} (xs ys: seq T),
+      uniq xs ->
+      (forall x, x \in xs -> x \in ys) ->
+      size xs <= size ys.
+  Proof.
+    clear; intros ? ? ? UNIQ SUB.
+    have Lem:
+      forall a ys,
+        (a \in ys) -> 
+        exists ysl ysr, ys = ysl ++ [::a] ++ ysr.
+    { clear; intros ? ? ? SUB.
+      induction ys; first by done.
+      move: SUB; rewrite in_cons; move => /orP [/eqP EQ|IN].
+      - by subst; exists [::], ys.
+      - feed IHys; first by done.
+        clear IN; move: IHys => [ysl [ysr EQ]].
+          by subst; exists(a0::ysl), ysr.
+    }
+    have EXm: exists m, size ys <= m.
+    { by exists (size ys). }
+    move: EXm => [m SIZEm].
+    move: SIZEm UNIQ SUB; move: xs ys.
+    induction m.
+    { intros.
+      move: SIZEm; rewrite leqn0 size_eq0; move => /eqP SIZEm; subst ys.
+      destruct xs; first by done.
+      specialize (SUB s).
+      feed SUB; first by rewrite in_cons; apply/orP; left.
+        by done.
+    }
+    { intros.
+      destruct xs as [ | x xs]; first by done.
+      specialize (@Lem _ x ys).
+      feed Lem.
+      { by apply SUB; rewrite in_cons; apply/orP; left. }
+      move: Lem => [ysl [ysr EQ]]; subst ys.
+      rewrite !size_cat; simpl; rewrite -addnC add1n addSn ltnS -size_cat.
+      eapply IHm.
+      - move: SIZEm; rewrite !size_cat; simpl; move => SIZE.
+          by rewrite add1n addnS ltnS addnC in SIZE.
+      - by move: UNIQ; rewrite cons_uniq; move => /andP [_ UNIQ].
+      - intros a IN.
+        destruct (a == x) eqn: EQ.
+        { exfalso.
+          move: EQ UNIQ; rewrite cons_uniq; move => /eqP EQ /andP [NIN UNIQ].
+            by subst; move: NIN => /negP NIN; apply: NIN.
+        }
+        { specialize (SUB a).
+          feed SUB.
+          { by rewrite in_cons; apply/orP; right. }
+          clear IN; move: SUB; rewrite !mem_cat; move => /orP [IN| /orP [IN|IN]].
+          - by apply/orP; right.
+          - exfalso.
+              by  move: IN; rewrite in_cons; move => /orP [IN|IN]; [rewrite IN in EQ | ].
+          - by apply/orP; left.
+        }
+    }
+  Qed.
+
+End AdditionalLemmas.
\ No newline at end of file
diff --git a/util/minmax.v b/util/minmax.v
index ea69b93b3841ada7e6cfd4403d812a8e42ce09b2..5d8e673eead69db683195e482c4d06ccf26d50a8 100644
--- a/util/minmax.v
+++ b/util/minmax.v
@@ -514,14 +514,55 @@ End MinMaxSeq.
 
 (* Additional lemmas about max. *)
 Section ExtraLemmas.
-  
-  Lemma leq_big_max I r (P : pred I) (E1 E2 : I -> nat) :
-    (forall i, P i -> E1 i <= E2 i) ->
-      \max_(i <- r | P i) E1 i <= \max_(i <- r | P i) E2 i.
+
+  Lemma leq_bigmax_cond_seq (T : eqType) (P : pred T) (r : seq T) F i0 :
+    i0 \in r -> P i0 -> F i0 <= \max_(i <- r | P i) F i.
+  Proof.
+    intros IN0 Pi0; by rewrite (big_rem i0) //= Pi0 leq_maxl.
+  Qed.
+
+  Lemma bigmax_sup_seq:
+    forall (T: eqType) (i: T) r (P: pred T) m F,
+      i \in r -> P i -> m <= F i -> m <= \max_(i <- r| P i) F i.
+  Proof.
+    intros.
+    induction r.
+    - by rewrite in_nil  in H.
+      move: H; rewrite in_cons; move => /orP [/eqP EQA | IN].
+      {
+        clear IHr; subst a.
+        rewrite (big_rem i) //=; last by rewrite in_cons; apply/orP; left.
+        apply leq_trans with (F i); first by done.
+          by rewrite H0 leq_maxl.
+      }
+      {
+        apply leq_trans with (\max_(i0 <- r | P i0) F i0); first by apply IHr.
+        rewrite [in X in _ <= X](big_rem a) //=; last by rewrite in_cons; apply/orP; left.
+
+        have Ob: a == a; first by done.
+          by rewrite Ob leq_maxr.
+      }
+  Qed.
+
+  Lemma bigmax_leq_seqP (T : eqType) (P : pred T) (r : seq T) F m :
+    reflect (forall i, i \in r -> P i -> F i <= m)
+            (\max_(i <- r | P i) F i <= m).
+  Proof.
+    apply: (iffP idP) => leFm => [i IINR Pi|];
+      first by apply: leq_trans leFm; apply leq_bigmax_cond_seq.
+    rewrite big_seq_cond; elim/big_ind: _ => // m1 m2.
+      by intros; rewrite geq_max; apply/andP; split. 
+      by move: m2 => /andP [M1IN Pm1]; apply: leFm.
+  Qed.
+
+  Lemma leq_big_max (T : eqType) (P : pred T) (r : seq T) F1 F2 :
+    (forall i, i \in r -> P i -> F1 i <= F2 i) ->
+    \max_(i <- r | P i) F1 i <= \max_(i <- r | P i) F2 i.
   Proof.
-    move => leE12; elim/big_ind2 : _ => // m1 m2 n1 n2.
-    intros LE1 LE2; rewrite leq_max; unfold maxn.
-    by destruct (m2 < n2) eqn:LT; [by apply/orP; right | by apply/orP; left].
+    intros; apply /bigmax_leq_seqP; intros.
+    specialize (H i); feed_n 2 H; try(done).
+    rewrite (big_rem i) //=; rewrite H1.
+      by apply leq_trans with (F2 i); [ | rewrite leq_maxl].
   Qed.
 
   Lemma bigmax_ord_ltn_identity n :
diff --git a/util/nat.v b/util/nat.v
index 8cb1de9b36c62cb77ede8e206205e88e6b43d772..e661c533d427033d3a7e66320e7ffe6a1013bfd1 100644
--- a/util/nat.v
+++ b/util/nat.v
@@ -22,7 +22,7 @@ Section NatLemmas.
       n1 >= n2 ->
       (m1 + n1) - (m2 + n2) = m1 - m2 + (n1 - n2).
   Proof. by ins; ssromega. Qed.
-
+  
   Lemma subh3 :
     forall m n p,
       m + p <= n ->
@@ -33,6 +33,21 @@ Section NatLemmas.
     by rewrite subh1 // -addnBA // subnn addn0.
   Qed.
 
+  (* subh3: forall m n p : nat, m + p <= n -> p <= n -> m <= n - p *)
+  (*                 unnecessary condition -- ^^^^^^^^^ *)
+  (* TODO: del subh3 *)
+  Lemma subh3_ext:
+    forall m n p,
+      m + p <= n ->
+      m <= n - p.
+  Proof.
+    clear.
+    intros.
+    apply subh3; first by done.
+    apply leq_trans with (m+p); last by done.
+      by rewrite leq_addl.
+  Qed.
+
   Lemma subh4:
     forall m n p,
       m <= n ->
diff --git a/util/step_function.v b/util/step_function.v
index a1e3fcd4497bb36ab2a33d48f7c10cf49cfa6ab9..c999715f6417b7e1760892424284d0b23d341f42 100644
--- a/util/step_function.v
+++ b/util/step_function.v
@@ -85,5 +85,50 @@ Section StepFunction.
     End ExistsIntermediateValue.
 
   End Lemmas.
+  
+  (* In this section, we prove an analogue of the intermediate
+     value theorem, but for predicates of natural numbers. *) 
+  Section ExistsIntermediateValuePredicates. 
+
+    (* Let P be any predicate on natural numbers. *)
+    Variable P: nat -> bool.
+
+    (* Consider a time interval [t1,t2] such that ... *)
+    Variables t1 t2: nat.
+    Hypothesis H_t1_le_t2: t1 <= t2.
+
+    (* ... P doesn't hold for t1 ... *)
+    Hypothesis H_not_P_at_t1: ~~ P t1.
+
+    (* ... but holds for t2. *)
+    Hypothesis H_P_at_t2: P t2.
+    
+    (* Then we prove that within time interval [t1,t2] there exists time 
+       instant t such that t is the first time instant when P holds. *)
+    Lemma exists_first_intermediate_point:
+      exists t, (t1 < t <= t2) /\ (forall x, t1 <= x < t -> ~~ P x) /\ P t.
+    Proof.
+      have EX: exists x, P x && (t1 < x <= t2).
+      { exists t2.
+        apply/andP; split; first by done.
+        apply/andP; split; last by done.
+        move: H_t1_le_t2; rewrite leq_eqVlt; move => /orP [/eqP EQ | NEQ1]; last by done.
+          by exfalso; subst t2; move: H_not_P_at_t1 => /negP NPt1. 
+      }
+      have MIN := ex_minnP EX.
+      move: MIN => [x /andP [Px /andP [LT1 LT2]] MIN]; clear EX.
+      exists x; repeat split; [ apply/andP; split | | ]; try done.
+      move => y /andP [NEQ1 NEQ2]; apply/negPn; intros Py.
+      feed (MIN y). 
+      { apply/andP; split; first by done.
+        apply/andP; split.
+        - move: NEQ1. rewrite leq_eqVlt; move => /orP [/eqP EQ | NEQ1]; last by done.
+            by exfalso; subst y; move: H_not_P_at_t1 => /negP NPt1. 
+        - by apply ltnW, leq_trans with x.
+      }
+        by move: NEQ2; rewrite ltnNge; move => /negP NEQ2.
+    Qed.
+    
+  End ExistsIntermediateValuePredicates.  
 
 End StepFunction.
\ No newline at end of file
diff --git a/util/sum.v b/util/sum.v
index 7980bd4c2b6fa3153400e05727efd856dc56c38f..6266d3da93ecf455aa5b10ca758477cb5e6f14fd 100644
--- a/util/sum.v
+++ b/util/sum.v
@@ -1,88 +1,7 @@
 Require Import rt.util.tactics rt.util.notation rt.util.sorting rt.util.nat.
 From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq fintype bigop path.
 
-(* Lemmas about arithmetic with sums. *)
-Section SumArithmetic.
-
-  (* Inequality with sums is monotonic with their functions. *)
-  Lemma sum_diff_monotonic :
-    forall n G F,
-      (forall i : nat, i < n -> G i <= F i) ->
-      (\sum_(0 <= i < n) (G i)) <= (\sum_(0 <= i < n) (F i)).
-  Proof.
-    intros n G F ALL.
-    rewrite big_nat_cond [\sum_(0 <= i < n) F i]big_nat_cond.
-    apply leq_sum; intros i LT; rewrite andbT in LT.
-    move: LT => /andP LT; des.
-    by apply ALL, leq_trans with (n := n); ins.
-  Qed.
-
-  Lemma sum_diff :
-    forall n F G,
-      (forall i (LT: i < n), F i >= G i) ->
-      \sum_(0 <= i < n) (F i - G i) =
-        (\sum_(0 <= i < n) (F i)) - (\sum_(0 <= i < n) (G i)).       
-  Proof.
-    intros n F G ALL.
-    induction n; ins; first by rewrite 3?big_geq.
-    assert (ALL': forall i, i < n -> G i <= F i).
-      by ins; apply ALL, leq_trans with (n := n); ins.
-    rewrite 3?big_nat_recr // IHn //; simpl.
-    rewrite subh1; last by apply sum_diff_monotonic.
-    rewrite subh2 //; try apply sum_diff_monotonic; ins.
-    rewrite subh1; ins; apply sum_diff_monotonic; ins.
-    by apply ALL; rewrite ltnS leqnn. 
-  Qed.
-
-  Lemma telescoping_sum :
-    forall (T: Type) (F: T->nat) r (x0: T),
-    (forall i, i < (size r).-1 -> F (nth x0 r i) <= F (nth x0 r i.+1)) ->
-      F (nth x0 r (size r).-1) - F (nth x0 r 0) =
-        \sum_(0 <= i < (size r).-1) (F (nth x0 r (i.+1)) - F (nth x0 r i)).
-  Proof.
-    intros T F r x0 ALL.
-    have ADD1 := big_add1.
-    have RECL := big_nat_recl.
-    specialize (ADD1 nat 0 addn 0 (size r) (fun x => true) (fun i => F (nth x0 r i))).
-    specialize (RECL nat 0 addn (size r).-1 0 (fun i => F (nth x0 r i))).
-    rewrite sum_diff; last by ins.
-    rewrite addmovr; last by rewrite -[_.-1]add0n; apply prev_le_next; try rewrite add0n leqnn.
-    rewrite subh1; last by apply sum_diff_monotonic.
-    rewrite addnC -RECL //.
-    rewrite addmovl; last by rewrite big_nat_recr // -{1}[\sum_(_ <= _ < _) _]addn0; apply leq_add.
-    by rewrite addnC -big_nat_recr.
-  Qed.
-
-  Lemma leq_sum_sub_uniq :
-    forall (T: eqType) (r1 r2: seq T) F,
-      uniq r1 ->
-      {subset r1 <= r2} ->
-      \sum_(i <- r1) F i <= \sum_(i <- r2) F i.
-  Proof.
-    intros T r1 r2 F UNIQ SUB; generalize dependent r2.
-    induction r1 as [| x r1' IH]; first by ins; rewrite big_nil.
-    {
-      intros r2 SUB.
-      assert (IN: x \in r2).
-        by apply SUB; rewrite in_cons eq_refl orTb.
-      simpl in UNIQ; move: UNIQ => /andP [NOTIN UNIQ]; specialize (IH UNIQ).
-      destruct (splitPr IN).
-      rewrite big_cat 2!big_cons /= addnA [_ + F x]addnC -addnA leq_add2l.
-      rewrite mem_cat in_cons eq_refl in IN.
-      rewrite -big_cat /=.
-      apply IH; red; intros x0 IN0.
-      rewrite mem_cat.
-      feed (SUB x0); first by rewrite in_cons IN0 orbT.
-      rewrite mem_cat in_cons in SUB.
-      move: SUB => /orP [SUB1 | /orP [/eqP EQx | SUB2]];
-        [by rewrite SUB1 | | by rewrite SUB2 orbT].
-      by rewrite -EQx IN0 in NOTIN.
-    }
-  Qed.
-    
-End SumArithmetic.
-
-(* Additional lemmas about sum. *)
+(* Lemmas about sum. *)
 Section ExtraLemmas.
   
   Lemma extend_sum :
@@ -97,7 +16,7 @@ Section ExtraLemmas.
     rewrite -> big_cat_nat with (m := t1') (n := t1); try (by done); simpl;
       last by apply leq_trans with (n := t2).
     rewrite -> big_cat_nat with (p := t2') (n := t2); try (by done); simpl.
-    by rewrite addnC -addnA; apply leq_addr.
+      by rewrite addnC -addnA; apply leq_addr.
   Qed.
 
   Lemma leq_sum_nat m n (P : pred nat) (E1 E2 : nat -> nat) :
@@ -106,7 +25,7 @@ Section ExtraLemmas.
   Proof.
     intros LE.
     rewrite big_nat_cond [\sum_(_ <= _ < _| P _)_]big_nat_cond.
-    by apply leq_sum; move => j /andP [IN H]; apply LE.
+      by apply leq_sum; move => j /andP [IN H]; apply LE.
   Qed.
 
   Lemma leq_sum_seq (I: eqType) (r: seq I) (P : pred I) (E1 E2 : I -> nat) :
@@ -115,7 +34,7 @@ Section ExtraLemmas.
   Proof.
     intros LE.
     rewrite big_seq_cond [\sum_(_ <- _| P _)_]big_seq_cond.
-    by apply leq_sum; move => j /andP [IN H]; apply LE.
+      by apply leq_sum; move => j /andP [IN H]; apply LE.
   Qed.
 
   Lemma sum_nat_eq0_nat (T : eqType) (F : T -> nat) (r: seq T) :
@@ -128,7 +47,7 @@ Section ExtraLemmas.
         first by rewrite big_const_seq iter_addn mul0n addn0 leqnn.
       intro i; rewrite andbT; intros IN.
       specialize (ZERO i); rewrite IN in ZERO.
-      by move: ZERO => /implyP ZERO; apply/eqP; apply ZERO.
+        by move: ZERO => /implyP ZERO; apply/eqP; apply ZERO.
     }
     {
       apply negbT in ZERO; rewrite -has_predC in ZERO.
@@ -136,7 +55,7 @@ Section ExtraLemmas.
       rewrite (big_rem x) /=; last by done.
       symmetry; apply negbTE; rewrite neq_ltn; apply/orP; right.
       apply leq_trans with (n := F x); last by apply leq_addr.
-      by rewrite lt0n.
+        by rewrite lt0n.
     }
   Qed.
   
@@ -153,7 +72,7 @@ Section ExtraLemmas.
       case TRUE: (P i); last by done.
       move: (REDUCE i (conj LE TRUE)) => [LE' TRUE'].
       rewrite (big_rem i); last by rewrite mem_index_iota.
-      by rewrite TRUE' eq_refl.
+        by rewrite TRUE' eq_refl.
     }
     {
       apply leq_sum_nat; intros i LE TRUE.
@@ -162,12 +81,242 @@ Section ExtraLemmas.
       {
         rewrite big_nat_cond big1; first by done.
         move => i' /andP [LE'' _]; case EQ: (_ == _); last by done.
-        by move: EQ => /eqP EQ; subst; rewrite LE'' in LE'.
+          by move: EQ => /eqP EQ; subst; rewrite LE'' in LE'.
       }
       rewrite (bigD1_seq i) /=; [ | by rewrite mem_index_iota | by rewrite iota_uniq ].
       rewrite eq_refl big1; first by done.
-      by move => i' /negbTE NEQ; rewrite NEQ.
+        by move => i' /negbTE NEQ; rewrite NEQ.
+    }
+  Qed.
+
+  Lemma sum_seq_gt0P:
+    forall (T:eqType) (r: seq T) (F: T -> nat),
+      reflect (exists i, i \in r /\ 0 < F i) (0 < \sum_(i <- r) F i).
+  Proof.
+    intros; apply: (iffP idP); intros.
+    {
+      induction r; first by rewrite big_nil in H.
+      destruct (F a > 0) eqn:POS.
+      exists a; split; [by rewrite in_cons; apply/orP; left | by done].
+      apply negbT in POS; rewrite -leqNgt leqn0 in POS; move: POS => /eqP POS.
+      rewrite big_cons POS add0n in H. clear POS.
+      feed IHr; first by done. move: IHr => [i [IN POS]].
+      exists i; split; [by rewrite in_cons; apply/orP;right | by done].
+    }
+    {
+      move: H => [i [IN POS]].
+      rewrite (big_rem i) //=.
+      apply leq_trans with (F i); [by done | by rewrite leq_addr].
+    }
+  Qed.
+
+  Lemma leq_pred_sum:
+    forall (T:eqType) (r: seq T) (P1 P2: pred T) F, 
+      (forall i, P1 i -> P2 i) ->
+      \sum_(i <- r | P1 i) F i <=
+      \sum_(i <- r | P2 i) F i.
+  Proof.
+    intros.
+    rewrite big_mkcond [in X in _ <= X]big_mkcond//= leq_sum //.
+    intros i _. 
+    destruct P1 eqn:P1a; destruct P2 eqn:P2a; [by done | | by done | by done].
+    exfalso.
+    move: P1a P2a => /eqP P1a /eqP P2a.
+    rewrite eqb_id in P1a; rewrite eqbF_neg in P2a.
+    move: P2a => /negP P2a.
+      by apply P2a; apply H.
+  Qed.
+
+  Lemma sum_notin_rem_eqn:
+    forall (T:eqType) (a: T) xs P F,
+      a \notin xs ->
+      \sum_(x <- xs | P x && (x != a)) F x = \sum_(x <- xs | P x) F x.
+  Proof.
+    intros ? ? ? ? ? NOTIN.
+    induction xs; first by rewrite !big_nil.
+    rewrite !big_cons.
+    rewrite IHxs; clear IHxs; last first.
+    { apply/memPn; intros y IN.
+      move: NOTIN => /memPn NOTIN.
+        by apply NOTIN; rewrite in_cons; apply/orP; right.
     }
+    move: NOTIN => /memPn NOTIN. 
+    move: (NOTIN a0) => NEQ.
+    feed NEQ; first by (rewrite in_cons; apply/orP; left).
+      by rewrite NEQ Bool.andb_true_r.
   Qed.
 
-End ExtraLemmas.
\ No newline at end of file
+  (* We prove that if any element of a set r is bounded by constant const, 
+     then the sum of the whole set is bounded by [const * size r]. *)
+  Lemma sum_majorant_constant:
+    forall (T: eqType) (r: seq T) (P: pred T) F const,
+      (forall a,  a \in r -> P a -> F a <= const) -> 
+      \sum_(j <- r | P j) F j <= const * (size [seq j <- r | P j]).
+  Proof.
+    clear; intros.
+    induction r; first by rewrite big_nil.
+    feed IHr.
+    { intros; apply H.
+      - by rewrite in_cons; apply/orP; right.
+      - by done. } 
+    rewrite big_cons.
+    destruct (P a) eqn:EQ.
+    { rewrite -cat1s filter_cat size_cat.
+      rewrite mulnDr.
+      apply leq_add; last by done.
+      rewrite size_filter.
+      simpl; rewrite addn0.
+      rewrite EQ muln1.
+      apply H; last by done. 
+        by rewrite in_cons; apply/orP; left. 
+    }
+    { apply leq_trans with (const * size [seq j <- r | P j]); first by done.
+      rewrite leq_mul2l; apply/orP; right.
+      rewrite -cat1s filter_cat size_cat.
+        by rewrite leq_addl.
+    }
+  Qed.
+
+  (* We prove that if for any element x of a set xs the following two statements hold 
+     (1) [F1 x] is less than or equal to [F2 x] and (2) the sum [F1 x_1, ..., F1 x_n] 
+     is equal to the sum of [F2 x_1, ..., F2 x_n], then [F1 x] is equal to [F2 x] for 
+     any element x of xs. *)
+  Lemma sum_majorant_eqn:
+    forall (T: eqType) xs F1 F2 (P: pred T),
+      (forall x, x \in xs -> P x -> F1 x <= F2 x) -> 
+      \sum_(x <- xs | P x) F1 x = \sum_(x <- xs | P x) F2 x ->
+      (forall x, x \in xs -> P x -> F1 x = F2 x).
+  Proof.
+    clear.      
+    intros T xs F1 F2 P H1 H2 x IN PX.
+    induction xs; first by done.
+    have Fact: \sum_(j <- xs | P j) F1 j <= \sum_(j <- xs | P j) F2 j.
+    { rewrite [in X in X <= _]big_seq_cond [in X in _ <= X]big_seq_cond leq_sum //.
+      move => y /andP [INy PY].
+      apply: H1; last by done. 
+        by rewrite in_cons; apply/orP; right. }
+    feed IHxs.
+    { intros x' IN' PX'.
+      apply H1; last by done.
+        by rewrite in_cons; apply/orP; right. }
+    rewrite big_cons [RHS]big_cons in H2.
+    have EqLeq: forall a b c d, a + b = c + d -> a <= c -> b >= d.
+    { clear; intros.
+      rewrite leqNgt; apply/negP; intros H1.
+      move: H => /eqP; rewrite eqn_leq; move => /andP [LE GE].
+      move: GE; rewrite leqNgt; move => /negP GE; apply: GE.
+        by apply leq_trans with (a + d); [rewrite ltn_add2l | rewrite leq_add2r]. }
+    move: IN; rewrite in_cons; move => /orP [/eqP EQ | IN]. 
+    { subst a.
+      rewrite PX in H2.
+      specialize (H1 x).
+      feed_n 2 H1; [ by rewrite in_cons; apply/orP; left | by done | ].
+      move: (EqLeq
+               (F1 x) (\sum_(j <- xs | P j) F1 j)
+               (F2 x) (\sum_(j <- xs | P j) F2 j) H2 H1) => Q.
+      have EQ: \sum_(j <- xs | P j) F1 j = \sum_(j <- xs | P j) F2 j. 
+      { by apply/eqP; rewrite eqn_leq; apply/andP; split. }
+        by move: H2 => /eqP; rewrite EQ eqn_add2r; move => /eqP EQ'.
+    }
+    { destruct (P a) eqn:PA; last by apply IHxs.
+      apply: IHxs; last by done.
+      specialize (H1 a).
+      feed_n 2 (H1); [ by rewrite in_cons; apply/orP; left | by done | ].
+      move: (EqLeq
+               (F1 a) (\sum_(j <- xs | P j) F1 j)
+               (F2 a) (\sum_(j <- xs | P j) F2 j) H2 H1) => Q.
+        by apply/eqP; rewrite eqn_leq; apply/andP; split.
+    }
+  Qed.
+
+  (* We prove that the sum of Δ ones is equal to Δ. *)
+  Lemma sum_of_ones:
+    forall t Δ,
+      \sum_(t <= x < t + Δ) 1 = Δ. 
+  Proof.
+    intros.
+    simpl_sum_const.
+    rewrite addnC -addnBA; last by done.
+      by rewrite subnn addn0.  
+  Qed.
+  
+End ExtraLemmas.
+
+(* Lemmas about arithmetic with sums. *)
+Section SumArithmetic.
+
+  Lemma sum_seq_diff:
+    forall (T:eqType) (r: seq T) (F G : T -> nat),
+      (forall i : T, i \in r -> G i <= F i) ->
+      \sum_(i <- r) (F i - G i) = \sum_(i <- r) F i - \sum_(i <- r) G i.
+  Proof.
+    intros.
+    induction r; first by rewrite !big_nil subn0. 
+    rewrite !big_cons subh2.
+    - apply/eqP; rewrite eqn_add2l; apply/eqP; apply IHr.
+        by intros; apply H; rewrite in_cons; apply/orP; right.
+    - by apply H; rewrite in_cons; apply/orP; left.
+    - rewrite big_seq_cond [in X in _ <= X]big_seq_cond.
+      rewrite leq_sum //; move => i /andP [IN _].
+        by apply H; rewrite in_cons; apply/orP; right.
+  Qed.
+  
+  Lemma sum_diff:
+    forall n F G,
+      (forall i (LT: i < n), F i >= G i) ->
+      \sum_(0 <= i < n) (F i - G i) =
+      (\sum_(0 <= i < n) (F i)) - (\sum_(0 <= i < n) (G i)).       
+  Proof.
+    intros n F G ALL.
+    rewrite sum_seq_diff; first by done.
+    move => i; rewrite mem_index_iota; move => /andP [_ LT].
+      by apply ALL.
+  Qed.
+  
+  Lemma telescoping_sum :
+    forall (T: Type) (F: T->nat) r (x0: T),
+      (forall i, i < (size r).-1 -> F (nth x0 r i) <= F (nth x0 r i.+1)) ->
+      F (nth x0 r (size r).-1) - F (nth x0 r 0) =
+      \sum_(0 <= i < (size r).-1) (F (nth x0 r (i.+1)) - F (nth x0 r i)).
+  Proof.
+    intros T F r x0 ALL.
+    have ADD1 := big_add1.
+    have RECL := big_nat_recl.
+    specialize (ADD1 nat 0 addn 0 (size r) (fun x => true) (fun i => F (nth x0 r i))).
+    specialize (RECL nat 0 addn (size r).-1 0 (fun i => F (nth x0 r i))).
+    rewrite sum_diff; last by ins.
+    rewrite addmovr; last by rewrite -[_.-1]add0n; apply prev_le_next; try rewrite add0n leqnn.
+    rewrite subh1; last by apply leq_sum_nat; move => i /andP [_ LT] _; apply ALL.
+    rewrite addnC -RECL //.
+    rewrite addmovl; last by rewrite big_nat_recr // -{1}[\sum_(_ <= _ < _) _]addn0; apply leq_add.
+      by rewrite addnC -big_nat_recr.
+  Qed.
+
+  Lemma leq_sum_sub_uniq :
+    forall (T: eqType) (r1 r2: seq T) F,
+      uniq r1 ->
+      {subset r1 <= r2} ->
+      \sum_(i <- r1) F i <= \sum_(i <- r2) F i.
+  Proof.
+    intros T r1 r2 F UNIQ SUB; generalize dependent r2.
+    induction r1 as [| x r1' IH]; first by ins; rewrite big_nil.
+    {
+      intros r2 SUB.
+      assert (IN: x \in r2).
+        by apply SUB; rewrite in_cons eq_refl orTb.
+        simpl in UNIQ; move: UNIQ => /andP [NOTIN UNIQ]; specialize (IH UNIQ).
+        destruct (splitPr IN).
+        rewrite big_cat 2!big_cons /= addnA [_ + F x]addnC -addnA leq_add2l.
+        rewrite mem_cat in_cons eq_refl in IN.
+        rewrite -big_cat /=.
+        apply IH; red; intros x0 IN0.
+        rewrite mem_cat.
+        feed (SUB x0); first by rewrite in_cons IN0 orbT.
+        rewrite mem_cat in_cons in SUB.
+        move: SUB => /orP [SUB1 | /orP [/eqP EQx | SUB2]];
+                       [by rewrite SUB1 | | by rewrite SUB2 orbT].
+          by rewrite -EQx IN0 in NOTIN.
+    }
+  Qed.
+  
+End SumArithmetic.
\ No newline at end of file