Revision 7ae3d64f7211fdb2ca0cfa738fddad52399571fb authored by François Dupressoir on 26 June 2015, 09:46:35 UTC, committed by Pierre-Yves Strub on 26 June 2015, 14:11:43 UTC
Some remain in newth/NewIntCore.ec and newth/NewRealCore.ec.
smt full and smt all currently fail for different reasons.
1 parent 966282e
Raw File
NewBigop.eca
(* --------------------------------------------------------------------
 * Copyright (c) - 2012-2015 - IMDEA Software Institute and INRIA
 * Distributed under the terms of the CeCILL-C license
 * -------------------------------------------------------------------- *)

(* This API has been mostly inspired from the [bigop] library of the
 * ssreflect Coq extension. *)

pragma +implicits.

(* -------------------------------------------------------------------- *)
require import Fun Pred Pair Int IntExtra NewList Ring.
require (*--*) NewMonoid.

import Ring.IntID.

(* -------------------------------------------------------------------- *)
type t.

clone export NewMonoid as Support with type t <- t.

(* -------------------------------------------------------------------- *)
op big (P : 'a -> bool) (F : 'a -> t) (r : 'a list) =
  foldr Support.(+) idm (map F (filter P r)).

(* -------------------------------------------------------------------- *)
op bigi (P : int -> bool) (F : int -> t) i j =
  big P F (range i j).

(* -------------------------------------------------------------------- *)
lemma big_nil (P : 'a -> bool) (F : 'a -> t): big P F [] = idm.
proof. by []. qed.

(* -------------------------------------------------------------------- *)
lemma big_cons (P : 'a -> bool) (F : 'a -> t) x s:
  big P F (x :: s) = if P x then F x + big P F s else big P F s.
proof. by rewrite {1}/big /= @(fun_if (map F)); case (P x). qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_rec (K : t -> bool) r P (F : 'a -> t):
  K idm => (forall i x, P i => K x => K (F i + x)) => K (big P F r).
proof.
  move=> K0 Kop; elim: r => //= i r; rewrite big_cons.
  by case (P i) => //=; apply/Kop.
qed.

lemma nosmt big_ind (K : t -> bool) r P (F : 'a -> t):
     (forall x y, K x => K y => K (x + y))
  => K idm => (forall i, P i => K (F i))
  => K (big P F r).
proof.
  move=> Kop Kidx K_F; apply/big_rec => //.
  by move=> i x Pi Kx; apply/Kop => //; apply/K_F.
qed.

lemma nosmt big_rec2:
  forall (K : t -> t -> bool) r P (F1 F2 : 'a -> t),
       K idm idm
    => (forall i y1 y2, P i => K y1 y2 => K (F1 i + y1) (F2 i + y2))
    => K (big P F1 r) (big P F2 r).
proof.
  move=> K r P F1 F2 KI KF; elim: r => //= i r IHr.
  by rewrite !big_cons; case (P i) => _ //=; apply/KF.
qed.

lemma nosmt big_ind2:
  forall (K : t -> t -> bool) r P (F1 F2 : 'a -> t),
       (forall x1 x2 y1 y2, K x1 x2 => K y1 y2 => K (x1 + y1) (x2 + y2))
    => K idm idm
    => (forall i, P i => K (F1 i) (F2 i))
    => K (big P F1 r) (big P F2 r).
proof.
  move=> K r P F1 F2 Kop KI KF; apply/big_rec2 => //.
  by move=> i x1 x2 Pi Kx1x2; apply/Kop => //; apply/KF.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_endo (f : t -> t):
     f idm = idm
  => (forall (x y : t), f (x + y) = f x + f y)
  => forall r P (F : 'a -> t),
       f (big P F r) = big P (f \o F) r.
proof.
  (* FIXME: should be a consequence of big_morph *)
  move=> fI fM; elim=> //= i r IHr P F; rewrite !big_cons.
  by case (P i) => //=; rewrite 1?fM IHr.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_map ['a 'b] (h : 'b -> 'a) (P : 'a -> bool) F s:
  big P F (map h s) = big (P \o h) (F \o h) s.
proof. by elim: s => // x s; rewrite map_cons !big_cons=> ->. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_comp ['a] (h : t -> t) (P : 'a -> bool) F s:
  h idm = idm => morphism_2 h Support.(+) Support.(+) =>
  h (big P F s) = big P (h \o F) s.
proof. 
  move=> Hidm Hh;elim: s => // x s; rewrite !big_cons => <-.
  by rewrite /(\o) -Hh;case (P x) => //.
qed.

lemma nosmt big_Dl ['a] (h : t -> t -> t) (P : 'a -> bool) F s t:
   left_zero idm h => 
   left_distributive h Support.(+) =>
   h (big P F s) t = big P (fun a => h (F a) t) s.
proof.
  move=> Hlz HDl.
  cut /= -> := big_comp (fun t1 => h t1 t) P F s _ _=> //=.
  + by apply Hlz.
  move=> t1 t2; apply (HDl t1 t2 t).
qed.

lemma nosmt big_Dr ['a] (h:t -> t -> t) (P:'a -> bool) F s t:
   right_zero idm h => 
   right_distributive h Support.(+) =>
   h t (big P F s) = big P (fun a => h t (F a)) s.
proof.
  move=> Hrz HDr.
  by cut /= -> := big_comp (h t) P F s _ _=> //=;[apply Hrz|apply (HDr t)]. 
qed.

lemma nosmt big_D ['a 'b] (h : t -> t -> t) (P1 : 'a -> bool) F1 s1
                                             (P2 : 'b -> bool) F2 s2:
   commutative h =>
   left_zero idm h => 
   left_distributive h Support.(+) =>
   h (big P1 F1 s1) (big P2 F2 s2) =
     big P1 (fun a1 => big P2 (fun a2 => h (F1 a1) (F2 a2)) s2) s1.
proof.
  move=> Hc Hlz HDl.
  rewrite big_Dl => //; congr;apply fun_ext=> a1.
  rewrite big_Dr //;smt.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_nth x0 (P : 'a -> bool) (F : 'a -> t) s:
  big P F s = big (P \o (nth x0 s)) (F \o (nth x0 s)) (iota_ 0 (size s)).
proof. by rewrite -{1}@(mkseq_nth x0 s) /mkseq big_map. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_const (P : 'a -> bool) x s:
  big P (fun i => x) s = iter (count P s) ((+) x) idm.
proof.
  elim: s=> [|y s ih]; [by rewrite iter0 | rewrite big_cons /=].
  by rewrite ih; case (P y) => //; rewrite addzC iterS // count_ge0.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_seq1 (F : 'a -> t) x: big predT F [x] = F x.
proof. by rewrite big_cons big_nil addm0. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_mkcond (P : 'a -> bool) (F : 'a -> t) s:
  big P F s = big predT (fun i => if P i then F i else idm) s.
proof.
  elim: s=> // x s ih; rewrite !big_cons -ih /predT /=.
  by case (P x)=> //; rewrite add0m.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_filter (P : 'a -> bool) F s:
  big predT F (filter P s) = big P F s.
proof. by elim: s => //= x s; case (P x)=> //; rewrite !big_cons=> -> ->. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt eq_bigl (P1 P2 : 'a -> bool) (F : 'a -> t) s:
     (forall i, P1 i <=> P2 i)
  => big P1 F s = big P2 F s.
proof. by move=> h; rewrite /big (eq_filter h). qed.

(* -------------------------------------------------------------------- *)
lemma nosmt eq_bigr (P : 'a -> bool) (F1 F2 : 'a -> t) s:
     (forall i, P i => F1 i = F2 i)
  => big P F1 s = big P F2 s.
proof.                          (* FIXME: big_rec2 *)
  move=> eqF; elim: s=> // x s; rewrite !big_cons=> <-.
  by case (P x)=> // /eqF <-.
qed.

(* -------------------------------------------------------------------- *)
lemma big_andbC (P Q : 'a -> bool) F s:
  big (fun x => P x /\ Q x) F s = big (fun x => Q x /\ P x) F s.
proof. by apply/eq_bigl=> i. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt eq_big (P1 P2 : 'a -> bool) (F1 F2 : 'a -> t) s:
     (forall i, P1 i <=> P2 i)
  => (forall i, P1 i => F1 i = F2 i)
  => big P1 F1 s = big P2 F2 s.
proof. by move=> /eq_bigl <- /eq_bigr <-. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt congr_big r1 r2 P1 P2 (F1 F2 : 'a -> t):
     r1 = r2
  => (forall x, P1 x <=> P2 x)
  => (forall i, P1 i => F1 i = F2 i)
  => big P1 F1 r1 = big P2 F2 r2.
proof. by move=> <-; apply/eq_big. qed.

(* -------------------------------------------------------------------- *)
lemma big0_eq (P : 'a -> bool) s: big P (fun i => idm) s = idm.
proof.
  rewrite big_const; elim/Induction.natind: (count _ _) => n.
    by move/iter0<:t> => ->.
    by move/iterS<:t> => -> ->; rewrite addm0.
qed.

(* -------------------------------------------------------------------- *)
lemma big0 (P : 'a -> bool) F s: (forall i, P i => F i = idm) =>
  big P F s = idm.
proof. by move=> h; rewrite -@(big0_eq P s); apply/eq_bigr. qed.

(* -------------------------------------------------------------------- *)
lemma big_hasC (P : 'a -> bool) (F : 'a -> t) s: !has P s =>
  big P F s = idm.
proof.
  rewrite -big_filter has_count -size_filter.
  by rewrite ltz_def size_ge0 /= => /size_eq0 ->.
qed.

(* -------------------------------------------------------------------- *)
lemma big_pred0_eq (F : 'a -> t) s: big pred0 F s = idm.
proof. by rewrite big_hasC // has_pred0. qed.

(* -------------------------------------------------------------------- *)
lemma big_pred0 (P : 'a -> bool) (F : 'a -> t) s:
  (forall i, P i <=> false) => big P F s = idm.
proof. by move=> h; rewrite -@(big_pred0_eq F s); apply/eq_bigl. qed.

(* -------------------------------------------------------------------- *)
lemma big_cat (P : 'a -> bool) (F : 'a -> t) s1 s2:
  big P F (s1 ++ s2) = big P F s1 + big P F s2.
proof.
  rewrite !@(big_mkcond P); elim: s1 => /= [|i s1 ih].
    by rewrite @(big_nil P F) add0m.
  by rewrite !big_cons /(predT i) /= ih addmA.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_catl (P : 'a -> bool) (F : 'a -> t) s1 s2: !has P s2 =>
  big P F (s1 ++ s2) = big P F s1.
proof. by rewrite big_cat => /big_hasC ->; rewrite addm0. qed.
  
(* -------------------------------------------------------------------- *)
lemma nosmt big_catr (P : 'a -> bool) (F : 'a -> t) s1 s2: !has P s1 =>
  big P F (s1 ++ s2) = big P F s2.
proof. by rewrite big_cat => /big_hasC ->; rewrite add0m. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_rcons (P : 'a -> bool) (F : 'a -> t) s x:
  big P F (rcons s x) = if P x then big P F s + F x else big P F s.
proof.
  by rewrite -cats1 big_cat big_cons big_nil; case: (P x); rewrite !addm0.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt eq_big_perm (P : 'a -> bool) (F : 'a -> t) s1 s2:
  perm_eq s1 s2 => big P F s1 = big P F s2.
proof.
  move=> /perm_eqP; rewrite !@(big_mkcond P).
  elim s1 s2 => [|i s1 ih1] s2 eq_s12.
    by case s2 eq_s12 => // i s2 h; cut := h (pred1 i); smt.
  cut r2i: mem s2 i by rewrite -has_pred1 has_count -eq_s12 smt.
  have/splitPr [s3 s4] ->> := r2i.
  rewrite big_cat !big_cons /(predT i) /=.
  rewrite addmCA; congr; rewrite -big_cat; apply/ih1=> a.
  by have := eq_s12 a; rewrite !count_cat /= addzCA => /addzI.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_rem (P : 'a -> bool) (F : 'a -> t) s x: mem s x =>
  big P F s = (if P x then F x else idm) + big P F (rem x s).
proof.
  by move/perm_to_rem/eq_big_perm=> ->; rewrite !@(big_mkcond P) big_cons.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt bigD1 (F : 'a -> t) s x: mem s x => uniq s =>
  big predT F s = F x + big (predC1 x) F s.
proof. by move=> /big_rem-> /rem_filter->; rewrite big_filter. qed.

(* -------------------------------------------------------------------- *)
lemma big_split (P : 'a -> bool) (F1 F2 : 'a -> t) s:
  big P (fun i => F1 i + F2 i) s = big P F1 s + big P F2 s.
proof.
  elim: s=> /= [|x s ih]; 1: by rewrite !big_nil addm0.
  rewrite !big_cons ih; case: (P x) => // _.
  by rewrite addmCA -!addmA addmCA.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt bigID (P : 'a -> bool) (F : 'a -> t) (a : 'a -> bool) s:
  big P F s = big (predI P a) F s + big (predI P (predC a)) F s.
proof.
  rewrite !@(big_mkcond _ F) -big_split /(/\) /[!].
  apply/eq_bigr => i _ /=.
  by rewrite /predI /predC; case: (a i); rewrite ?addm0 ?add0m.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_reindex (P : 'a -> bool) (F : 'a -> t) (f f' : 'a -> 'a) s:
  cancel f' f => big P F s = big (P \o f) (F \o f) (map f' s).
proof. by move=> bij_ff'; rewrite -big_map -map_comp id_map. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_seq_cond (P : 'a -> bool) (F : 'a -> t) s:
  big P F s = big (fun i => mem s i /\ P i) F s.
proof. by rewrite -!@(big_filter _ _ s); congr; apply/eq_in_filter. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_seq (F : 'a -> t) s:
  big predT F s = big (fun i => mem s i) F s.
proof. by rewrite big_seq_cond; apply/eq_bigl. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt eq_big_seq (F1 F2 : 'a -> t) s:
     (forall x, mem s x => F1 x = F2 x)
  => big predT F1 s = big predT F2 s.
proof. by move=> eqF; rewrite !big_seq; apply/eq_bigr. qed.

(* -------------------------------------------------------------------- *)
lemma big1_eq (P : 'a -> bool) s: big P (fun x => idm) s = idm.
proof.
  rewrite big_const; elim/Induction.natind: (count _ _)=> n.
    by move/iter0<:t> => ->.
  by move/iterS<:t> => -> ->; rewrite addm0.
qed.

(* -------------------------------------------------------------------- *)
lemma big1 (P : 'a -> bool) F s:
  (forall i, P i => F i = idm) => big P F s = idm.
proof. by move/eq_bigr=> ->; apply/big1_eq. qed.

(* -------------------------------------------------------------------- *)
lemma big1_seq (P : 'a -> bool) F s:
  (forall i, P i /\ (mem s i) => F i = idm) => big P F s = idm.
proof. by move=> eqF1; rewrite big_seq_cond big_andbC big1. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_int_cond m n P F:
  bigi P F m n = bigi (fun i => m <= i < n /\ P i) F m n.
proof. by rewrite /bigi big_seq_cond; apply/eq_bigl=> i /=; smt. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_int m n F:
  bigi predT F m n = bigi (fun i => m <= i < n) F m n.
proof. by rewrite big_int_cond. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt congr_big_int (m1 n1 m2 n2 : int) P1 P2 F1 F2:
       m1 = m2 => n1 = n2
    => (forall i, m1 <= i < n2 => P1 i = P2 i)
    => (forall i, P1 i /\ (m1 <= i < n2) => F1 i = F2 i)
    => bigi P1 F1 m1 n1 = bigi P2 F2 m2 n2.
proof.
  move=> <- <- eqP12 eqF12; rewrite /bigi big_seq_cond @(big_seq_cond P2).
  by apply/eq_big=> i /=; rewrite mem_range smt.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt eq_big_int (m n : int) F1 F2:
     (forall i, m <= i < n => F1 i = F2 i)
  => bigi predT F1 m n = bigi predT F2 m n.
proof. by move=> eqF; apply/congr_big_int. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_ltn_cond (m n : int) P F: m < n =>
  let x = bigi P F (m+1) n in
  bigi P F m n = if P m then F m + x else x.
proof. by rewrite /bigi => /range_ltn ->; rewrite big_cons. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_ltn (m n : int) F: m < n =>
  bigi predT F m n = F m + bigi predT F (m+1) n.
proof. by move/big_ltn_cond=> /= ->. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_geq (m n : int) P F: n <= m =>
  bigi P F m n = idm.
proof. by move/range_geq; rewrite /bigi=> ->; rewrite big_nil. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_addn (m n a : int) P F:
    bigi P F (m+a) n
  = bigi (fun i => P (i+a)) (fun i => F (i+a)) m (n-a).
proof.
rewrite /bigi range_addl big_map; apply/eq_big.
  by move=> i /=; rewrite /(\o) addzC.
by move=> i /= _; rewrite /(\o) addzC.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_int1 n F: bigi predT F n (n+1) = F n.
proof. by rewrite big_ltn 1:smt big_geq // addm0. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_cat_int (n m p : int) P F: m <= n => n <= p =>
  bigi P F m p = (bigi P F m n) + (bigi P F n p).
proof. by move=> lemn lenp; rewrite {-1}/bigi -big_cat -range_cat. qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_int_recl (n m : int) F: m <= n =>
  bigi predT F m (n+1) = F m + bigi predT (fun i => F (i+1)) m n.
proof.
  move=> lemn; rewrite big_ltn 1?big_addn /= 1:smt.
  by rewrite subrE addrK.
qed.

(* -------------------------------------------------------------------- *)
lemma nosmt big_int_recr (n m : int) F: m <= n =>
  bigi predT F m (n+1) = bigi predT F m n + F n.
proof. by move=> lemn; rewrite @(big_cat_int n) ?big_int1 // smt. qed.
back to top