Library prosa.util.lcmseq
From mathcomp Require Export ssreflect seq div ssrbool ssrnat eqtype ssrfun.
Require Export prosa.util.tactics.
Require Export prosa.util.tactics.
A function to calculate the least common multiple
of all integers in a sequence xs, denoted by lcml xs
Lemma int_divides_lcm_in_seq:
∀ (a : nat) (xs : seq nat), a %| lcml (a :: xs).
Proof.
intros.
rewrite /lcml.
induction xs.
- rewrite /foldr.
now apply dvdn_lcml.
- rewrite -cat1s.
rewrite foldr_cat /foldr.
by apply dvdn_lcml.
Qed.
∀ (a : nat) (xs : seq nat), a %| lcml (a :: xs).
Proof.
intros.
rewrite /lcml.
induction xs.
- rewrite /foldr.
now apply dvdn_lcml.
- rewrite -cat1s.
rewrite foldr_cat /foldr.
by apply dvdn_lcml.
Qed.
Lemma lcm_seq_divides_lcm_super:
∀ (x : nat) (xs : seq nat),
lcml xs %| lcml (x :: xs).
Proof.
intros.
rewrite /lcml.
induction xs; first by auto.
rewrite -cat1s foldr_cat /foldr.
by apply dvdn_lcmr.
Qed.
∀ (x : nat) (xs : seq nat),
lcml xs %| lcml (x :: xs).
Proof.
intros.
rewrite /lcml.
induction xs; first by auto.
rewrite -cat1s foldr_cat /foldr.
by apply dvdn_lcmr.
Qed.
Lemma lcm_seq_is_mult_of_all_ints:
∀ (sq : seq nat) (a : nat), a \in sq → ∃ k, lcml sq = k × a.
Proof.
intros xs x IN.
induction xs as [ | z sq IH_DIVIDES]; first by easy.
rewrite in_cons in IN.
move : IN ⇒ /orP [/eqP EQ | IN].
+ apply /dvdnP.
rewrite EQ /lcml.
by apply int_divides_lcm_in_seq.
+ move : (IH_DIVIDES IN) ⇒ [k EQ].
∃ ((foldr lcmn 1 (z :: sq)) %/ (foldr lcmn 1 sq) × k).
rewrite -mulnA -EQ divnK /lcml //.
by apply lcm_seq_divides_lcm_super.
Qed.
∀ (sq : seq nat) (a : nat), a \in sq → ∃ k, lcml sq = k × a.
Proof.
intros xs x IN.
induction xs as [ | z sq IH_DIVIDES]; first by easy.
rewrite in_cons in IN.
move : IN ⇒ /orP [/eqP EQ | IN].
+ apply /dvdnP.
rewrite EQ /lcml.
by apply int_divides_lcm_in_seq.
+ move : (IH_DIVIDES IN) ⇒ [k EQ].
∃ ((foldr lcmn 1 (z :: sq)) %/ (foldr lcmn 1 sq) × k).
rewrite -mulnA -EQ divnK /lcml //.
by apply lcm_seq_divides_lcm_super.
Qed.
The LCM of all elements in a sequence with only positive elements is positive.
Lemma all_pos_implies_lcml_pos:
∀ (xs : seq nat),
(∀ b, b \in xs → b > 0) →
lcml xs > 0.
Proof.
intros × POS.
induction xs; first by easy.
rewrite /lcml -cat1s ⇒ //.
simpl; rewrite lcmn_gt0.
apply /andP; split ⇒ //.
+ apply POS; rewrite in_cons; apply /orP; left.
now apply /eqP.
+ feed_n 1 IHxs.
- intros b B_IN.
now apply POS; rewrite in_cons; apply /orP; right ⇒ //.
- now rewrite /lcml in IHxs.
Qed.
∀ (xs : seq nat),
(∀ b, b \in xs → b > 0) →
lcml xs > 0.
Proof.
intros × POS.
induction xs; first by easy.
rewrite /lcml -cat1s ⇒ //.
simpl; rewrite lcmn_gt0.
apply /andP; split ⇒ //.
+ apply POS; rewrite in_cons; apply /orP; left.
now apply /eqP.
+ feed_n 1 IHxs.
- intros b B_IN.
now apply POS; rewrite in_cons; apply /orP; right ⇒ //.
- now rewrite /lcml in IHxs.
Qed.