Skip to content

Commit af62356

Browse files
mituharuTragicusybertot
committed
Add solve_Qint_span to intdiv.v.
Co-authored-by: Quentin Vermande <quentin.vermande@orange.fr> Co-authored-by: Yves Bertot <yves.bertot@inria.fr>
1 parent e7e8e07 commit af62356

2 files changed

Lines changed: 99 additions & 53 deletions

File tree

algebra/intdiv.v

Lines changed: 95 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,79 +1049,121 @@ Qed.
10491049
Definition inIntSpan (V : zmodType) m (s : m.-tuple V) v :=
10501050
exists a : int ^ m, v = \sum_(i < m) s`_i *~ a i.
10511051

1052-
Lemma dec_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :
1053-
decidable (inIntSpan s v).
1052+
Lemma solve_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :
1053+
{b : int ^ m &
1054+
{p : seq (int ^ m) &
1055+
forall a : int ^ m,
1056+
v = \sum_(i < m) s`_i *~ a i <->
1057+
exists c : seq int, a = b + \sum_(i < size p) p`_i *~ c`_i}} +
1058+
(~ inIntSpan s v).
10541059
Proof.
10551060
have s_s (i : 'I_m): s`_i \in <<s>>%VS by rewrite memv_span ?memt_nth.
10561061
have s_Zs a: \sum_(i < m) s`_i *~ a i \in <<s>>%VS.
10571062
by apply/rpred_sum => i _; apply/rpredMz.
10581063
case s_v: (v \in <<s>>%VS); last by right=> [[a Dv]]; rewrite Dv s_Zs in s_v.
1059-
pose S := \matrix_(i < m, j < _) coord (vbasis <<s>>) j s`_i.
1060-
pose r := \rank S; pose k := (m - r)%N; pose Em := erefl m; pose Ek := erefl k.
1061-
have Dm: (m = k + r)%N by rewrite subnK ?rank_leq_row.
1064+
move SE : (\matrix_(i < m, j < _) coord (vbasis <<s>>) j s`_i) => S.
1065+
move rE : (\rank S) => r; move kE : (m - r)%N => k.
1066+
have Dm: (m = k + r)%N by rewrite -kE -rE subnK ?rank_leq_row.
1067+
rewrite Dm in s s_s s_Zs s_v S SE rE kE *.
1068+
move=> {Dm m}; pose m := (k + r)%N.
10621069
have [K kerK]: {K : 'M_(k, m) | map_mx intr K == kermx S}%MS.
1070+
move: (mxrank_ker S); rewrite rE kE => krk.
10631071
pose B := row_base (kermx S); pose d := \prod_ij denq (B ij.1 ij.2).
1064-
exists (castmx (mxrank_ker S, Em) (map_mx numq (intr d *: B))).
1065-
rewrite /k; case: _ / (mxrank_ker S); set B1 := map_mx _ _.
1066-
have ->: B1 = (intr d *: B).
1067-
apply/matrixP=> i j; rewrite 3!mxE mulrC [d](bigD1 (i, j)) // rmorphM mulrA.
1072+
exists (castmx (krk, erefl m) (map_mx numq (intr d *: B))).
1073+
rewrite map_castmx !eqmx_cast -map_mx_comp map_mx_id_in => [|i j]; last first.
1074+
rewrite mxE mulrC [d](bigD1 (i, j)) //= rmorphM mulrA.
10681075
by rewrite -numqE -rmorphM numq_int.
1069-
suffices nz_d: d%:Q != 0 by rewrite !eqmx_scale // !eq_row_base andbb.
1076+
suff nz_d: d%:Q != 0 by rewrite !eqmx_scale // !eq_row_base andbb.
10701077
by rewrite intr_eq0; apply/prodf_neq0 => i _; apply: denq_neq0.
10711078
have [L _ [G uG [D _ defK]]] := int_Smith_normal_form K.
1072-
pose Gud := castmx (Dm, Em) G; pose G'lr := castmx (Em, Dm) (invmx G).
1073-
have{K L D defK kerK} kerGu: map_mx intr (usubmx Gud) *m S = 0.
1074-
pose Kl : 'M[rat]_k:= map_mx intr (lsubmx (castmx (Ek, Dm) (K *m invmx G))).
1075-
have{} defK: map_mx intr K = row_mx Kl 0 *m map_mx intr Gud.
1076-
rewrite -[K](mulmxKV uG) -{2}[G](castmxK Dm Em) -/Gud.
1077-
rewrite -[K *m _](castmxK Ek Dm) map_mxM map_castmx.
1078-
rewrite -(hsubmxK (castmx _ _)) map_row_mx -/Kl map_castmx /Em.
1079-
set Kr := map_mx _ _; case: _ / (esym Dm) (map_mx _ _) => /= GudQ.
1080-
congr (row_mx _ _ *m _); apply/matrixP=> i j; rewrite !mxE defK mulmxK //=.
1081-
rewrite castmxE mxE big1 //= => j1 _; rewrite mxE /= eqn_leq andbC.
1079+
have {K L D defK kerK} [kerGu kerS_sub_Gu]: map_mx intr (usubmx G) *m S = 0 /\
1080+
(kermx S <= map_mx intr (usubmx G))%MS.
1081+
pose Kl : 'M[rat]_k := map_mx intr (lsubmx (K *m invmx G)).
1082+
have {}defK: map_mx intr K = Kl *m map_mx intr (usubmx G).
1083+
rewrite /Kl -map_mxM; congr map_mx.
1084+
rewrite -[LHS](mulmxKV uG) -{2}[G]vsubmxK -{1}[K *m _]hsubmxK.
1085+
rewrite mul_row_col -[RHS]addr0; congr (_ + _).
1086+
rewrite defK mulmxK //= -[RHS](mul0mx _ (dsubmx G)); congr (_ *m _).
1087+
apply/matrixP => i j; rewrite !mxE big1 //= => j1 _.
1088+
rewrite mxE /= eqn_leq andbC.
10821089
by rewrite leqNgt (leq_trans (valP j1)) ?mulr0 ?leq_addr.
1083-
have /row_full_inj: row_full Kl; last apply.
1084-
rewrite /row_full eqn_leq rank_leq_row /= -{1}[k](mxrank_ker S).
1085-
rewrite -(eqmxP kerK) defK map_castmx mxrankMfree; last first.
1086-
case: _ / (Dm); apply/row_freeP; exists (map_mx intr (invmx G)).
1087-
by rewrite -map_mxM mulmxV ?map_mx1.
1088-
by rewrite -mxrank_tr tr_row_mx trmx0 -addsmxE addsmx0 mxrank_tr.
1089-
rewrite mulmx0 mulmxA (sub_kermxP _) // -(eqmxP kerK) defK.
1090-
by rewrite -{2}[Gud]vsubmxK map_col_mx mul_row_col mul0mx addr0.
1091-
pose T := map_mx intr (dsubmx Gud) *m S.
1092-
have{kerGu} defS: map_mx intr (rsubmx G'lr) *m T = S.
1093-
have: G'lr *m Gud = 1%:M by rewrite /G'lr /Gud; case: _ / (Dm); apply: mulVmx.
1094-
rewrite -{1}[G'lr]hsubmxK -[Gud]vsubmxK mulmxA mul_row_col -map_mxM.
1095-
move/(canRL (addKr _))->; rewrite -mulNmx raddfD /= map_mx1 map_mxM /=.
1090+
split; last by rewrite -(eqmxP kerK); apply/submxP; exists Kl.
1091+
suff /row_full_inj: row_full Kl.
1092+
by apply; rewrite mulmx0 mulmxA (sub_kermxP _) // -(eqmxP kerK) defK.
1093+
rewrite /row_full eqn_leq rank_leq_row /= -{1}kE -{2}rE -(mxrank_ker S).
1094+
by rewrite -(eqmxP kerK) defK mxrankM_maxl.
1095+
pose T := map_mx intr (dsubmx G) *m S.
1096+
have defS: map_mx intr (rsubmx (invmx G)) *m T = S.
1097+
rewrite mulmxA -map_mxM /=; move: (mulVmx uG).
1098+
rewrite -{2}[G]vsubmxK -{1}[invmx G]hsubmxK mul_row_col.
1099+
move/(canRL (addKr _)) ->; rewrite -mulNmx raddfD /= map_mx1 map_mxM /=.
10961100
by rewrite mulmxDl -mulmxA kerGu mulmx0 add0r mul1mx.
10971101
pose vv := \row_j coord (vbasis <<s>>) j v.
10981102
have uS: row_full S.
10991103
apply/row_fullP; exists (\matrix_(i, j) coord s j (vbasis <<s>>)`_i).
1100-
apply/matrixP=> j1 j2; rewrite !mxE.
1104+
apply/matrixP => j1 j2; rewrite !mxE.
11011105
rewrite -(coord_free _ _ (basis_free (vbasisP _))).
11021106
rewrite -!tnth_nth (coord_span (vbasis_mem (mem_tnth j1 _))) linear_sum.
1103-
by apply: eq_bigr => i _; rewrite !mxE (tnth_nth 0) !linearZ.
1107+
by apply: eq_bigr => /= i _; rewrite -SE !mxE (tnth_nth 0) !linearZ.
11041108
have eqST: (S :=: T)%MS by apply/eqmxP; rewrite -{1}defS !submxMl.
1105-
case Zv: (map_mx denq (vv *m pinvmx T) == const_mx 1).
1106-
pose a := map_mx numq (vv *m pinvmx T) *m dsubmx Gud.
1107-
left; exists [ffun j => a 0 j].
1108-
transitivity (\sum_j (map_mx intr a *m S) 0 j *: (vbasis <<s>>)`_j).
1109+
case Zv: (map_mx denq (vv *m pinvmx T) == const_mx 1); last first.
1110+
right=> [[a Dv]]; case/eqP: Zv; apply/rowP.
1111+
have ->: vv = map_mx intr (\row_i a i) *m S.
1112+
apply/rowP => j; rewrite !mxE Dv linear_sum.
1113+
by apply: eq_bigr => i _; rewrite -SE -scaler_int linearZ !mxE.
1114+
rewrite -defS -2!mulmxA; have ->: T *m pinvmx T = 1%:M.
1115+
have uT: row_free T by rewrite /row_free -eqST rE.
1116+
by apply: (row_free_inj uT); rewrite mul1mx mulmxKpV.
1117+
by move=> i; rewrite mulmx1 -map_mxM 2!mxE denq_int mxE.
1118+
pose b := map_mx numq (vv *m pinvmx T) *m dsubmx G.
1119+
left; exists [ffun j => b 0 j], [seq [ffun j => (usubmx G) i j] | i : 'I_k].
1120+
rewrite size_image card_ord => a; rewrite -[a](addNKr [ffun j => b 0 j]).
1121+
move: (_ + a) => h; under eq_bigr => i _ do rewrite !ffunE mulrzDr.
1122+
rewrite big_split /=.
1123+
have <-: v = \sum_(i < m) s`_i *~ b 0 i.
1124+
transitivity (\sum_j (map_mx intr b *m S) 0 j *: (vbasis <<s>>)`_j).
11091125
rewrite {1}(coord_vbasis s_v); apply: eq_bigr => j _; congr (_ *: _).
1110-
have ->: map_mx intr a = vv *m pinvmx T *m map_mx intr (dsubmx Gud).
1111-
rewrite map_mxM /=; congr (_ *m _); apply/rowP=> i; rewrite 2!mxE numqE.
1112-
by have /eqP/rowP/(_ i)/[!mxE]-> := Zv; rewrite mulr1.
1113-
by rewrite -(mulmxA _ _ S) mulmxKpV ?mxE // -eqST submx_full.
1126+
suff ->: map_mx intr b = vv *m pinvmx T *m map_mx intr (dsubmx G).
1127+
by rewrite -(mulmxA _ _ S) mulmxKpV ?mxE // -eqST submx_full.
1128+
rewrite map_mxM /=; congr (_ *m _); apply/rowP => i; rewrite 2!mxE numqE.
1129+
by have /eqP/rowP/(_ i)/[!mxE] -> := Zv; rewrite mulr1.
11141130
rewrite (coord_vbasis (s_Zs _)); apply: eq_bigr => j _; congr (_ *: _).
1115-
rewrite linear_sum mxE; apply: eq_bigr => /= i _.
1116-
by rewrite mxE mulrzl mxE ffunE raddfMz.
1117-
right=> [[a Dv]]; case/eqP: Zv; apply/rowP.
1118-
have ->: vv = map_mx intr (\row_i a i) *m S.
1119-
apply/rowP=> j; rewrite !mxE Dv linear_sum.
1120-
by apply: eq_bigr => i _; rewrite !mxE raddfMz mulrzl.
1121-
rewrite -defS -2!mulmxA; have ->: T *m pinvmx T = 1%:M.
1122-
have uT: row_free T by rewrite /row_free -eqST.
1123-
by apply: (row_free_inj uT); rewrite mul1mx mulmxKpV.
1124-
by move=> i; rewrite mulmx1 -map_mxM 2!mxE denq_int mxE.
1131+
rewrite linear_sum mxE; apply: eq_bigr => i _.
1132+
by rewrite -SE -scaler_int linearZ [b]lock !mxE.
1133+
split.
1134+
rewrite -[LHS]addr0 => /addrI hP; pose c := \row_i h i *m lsubmx (invmx G).
1135+
exists [seq c 0 i | i : 'I_k]; congr (_ + _).
1136+
have/sub_kermxP: map_mx intr (\row_i h i) *m S = 0.
1137+
transitivity (\row_j coord (vbasis <<s>>) j (\sum_(i < m) s`_i *~ h i)).
1138+
apply/rowP => j; rewrite !mxE linear_sum; apply: eq_bigr => i _.
1139+
by rewrite -SE !mxE -scaler_int linearZ.
1140+
by apply/rowP => j; rewrite !mxE -hP linear0.
1141+
case/submx_trans/(_ kerS_sub_Gu)/submxP => c' /[dup].
1142+
move/(congr1 (mulmx^~ (map_mx intr (lsubmx (invmx G))))).
1143+
rewrite -mulmxA -!map_mxM [in RHS]mulmx_lsub mul_usub_mx -/c mulmxV //=.
1144+
rewrite scalar_mx_block -/(ulsubmx _) block_mxKul map_scalar_mx mulmx1.
1145+
move=> <- {c'}; rewrite -map_mxM /= => defh; apply/ffunP => j.
1146+
move/rowP/(_ j): defh; rewrite sum_ffunE !mxE => /intr_inj ->.
1147+
apply: eq_bigr => i _; rewrite ffunMzE mulrzz mulrC.
1148+
rewrite (nth_map i) ?size_enum_ord // nth_ord_enum ffunE.
1149+
by rewrite (nth_map i) ?size_enum_ord // nth_ord_enum.
1150+
case=> c /addrI -> {h}; rewrite -[LHS]addr0; congr (_ + _).
1151+
pose h := \row_(j < k) c`_j *m usubmx G.
1152+
transitivity (\sum_j (map_mx intr h *m S) 0 j *: (vbasis <<s>>)`_j).
1153+
by rewrite map_mxM -mulmxA kerGu mulmx0 big1 // => j _; rewrite mxE scale0r.
1154+
rewrite (coord_vbasis (s_Zs _)); apply: eq_bigr => i _; congr (_ *: _).
1155+
rewrite linear_sum -SE mxE; apply: eq_bigr => j _.
1156+
rewrite -scaler_int linearZ !mxE sum_ffunE; congr (_%:~R * _).
1157+
apply: {i} eq_bigr => i _; rewrite mxE ffunMzE mulrzz mulrC.
1158+
by rewrite (nth_map i) ?size_enum_ord // ffunE nth_ord_enum.
1159+
Qed.
1160+
1161+
Lemma dec_Qint_span (vT : vectType rat) m (s : m.-tuple vT) v :
1162+
decidable (inIntSpan s v).
1163+
Proof.
1164+
have [[b [p aP]]|] := solve_Qint_span s v; last by right.
1165+
left; exists b; apply/(aP b); exists [::]; rewrite big1 ?addr0 // => i _.
1166+
by rewrite nth_nil mulr0z.
11251167
Qed.
11261168

11271169
Lemma eisenstein_crit (p : nat) (q : {poly int}) : prime p -> (size q != 1)%N ->
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- in `intdiv.v`
2+
+ lemma `solve_Qint_span`
3+
([#1191](https://github.com/math-comp/math-comp/pull/1191),
4+
by mituharu).

0 commit comments

Comments
 (0)