diff options
| author | Enrico Tassi | 2015-03-09 11:07:53 +0100 |
|---|---|---|
| committer | Enrico Tassi | 2015-03-09 11:24:38 +0100 |
| commit | fc84c27eac260dffd8f2fb1cb56d599f1e3486d9 (patch) | |
| tree | c16205f1637c80833a4c4598993c29fa0fd8c373 /mathcomp/attic | |
Initial commit
Diffstat (limited to 'mathcomp/attic')
| -rw-r--r-- | mathcomp/attic/algnum_basic.v | 535 | ||||
| -rw-r--r-- | mathcomp/attic/all.v | 9 | ||||
| -rw-r--r-- | mathcomp/attic/amodule.v | 417 | ||||
| -rw-r--r-- | mathcomp/attic/fib.v | 340 | ||||
| -rw-r--r-- | mathcomp/attic/forms.v | 193 | ||||
| -rw-r--r-- | mathcomp/attic/galgebra.v | 227 | ||||
| -rw-r--r-- | mathcomp/attic/multinom.v | 438 | ||||
| -rw-r--r-- | mathcomp/attic/mxtens.v | 312 | ||||
| -rw-r--r-- | mathcomp/attic/quote.v | 365 | ||||
| -rw-r--r-- | mathcomp/attic/tutorial.v | 296 |
10 files changed, 3132 insertions, 0 deletions
diff --git a/mathcomp/attic/algnum_basic.v b/mathcomp/attic/algnum_basic.v new file mode 100644 index 0000000..a302e7a --- /dev/null +++ b/mathcomp/attic/algnum_basic.v @@ -0,0 +1,535 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype tuple div. +Require Import bigop prime finset fingroup ssralg finalg zmodp abelian. +Require Import matrix vector falgebra finfield action poly ssrint cyclotomic. +Require Import fieldext mxalgebra mxpoly. + +(************************************************************************************************) +(* Basic algebraic number theory concepts from Milne, J.S.: Algebraic Number Theory. *) +(* We work in the setting of an extension field L0 : fieldextType F. At this point, *) +(* an integral domain is represented as a collective predicate on L0 closed under *) +(* subring operations. A module over the integral domain A is represented as a *) +(* Prop-valued predicate closed under the operations (0, x + y, x - y, x * y). It *) +(* is not a-priori made a collective predicate since we first need to establish the *) +(* Basis Lemma in order to show decidability. *) +(* *) +(* integral A l <-> l is integral over the domain A, i.e., it satisfies a polynomial *) +(* over A. This is currently a Prop-valued predicate since we *) +(* quantify over all polynomials over A. An alternative definition *) +(* would be to say that the minimal polynomial of l over the field *) +(* of fractions of A is itself a polynomial over A. The latter is *) +(* a decidable property and the equivalence of the two definitions *) +(* is provided by Prop. 2.11 in Milne. *) +(* int_closed A <-> A is integrally closed. *) +(* int_closure A L == The integral closure of A in L. This is currently a Prop-valued *) +(* predicate. *) +(* is_frac_field A K <-> K is the field of fractions of A. The condition of every k \in K *) +(* arising as a quotient a / b for a,b \in K is skolemized. This is *) +(* not strictly necessary since L0 has a canonical choiceType *) +(* structure but it facilitates some of the later proofs. *) +(* frac_field_alg_int A == Every element l arises as a quotient b / a, where a is in A and b *) +(* is integral over A. The statement of the theorem is skolemized, *) +(* which is not strictly necessary. *) +(* int_clos_incl A == Every element of A is integral over A. *) +(* int_subring_closed A == The integral closure of A is closed under the subring operations *) +(* (a - b, a * b). The proof of this lemma uses an equivalent *) +(* characterization of integrality, cf. Prop. 2.4 in Milne, which is *) +(* captured by the Lemmas intPl and intPr. The former states that *) +(* if there exists a nonzero finitely-generated A-module closed under *) +(* multiplication by l, then l is integral over A. The latter states *) +(* that if l is integral over A, then the A-algebra generated by l is *) +(* closed under multiplication by l. Note: These lemmas probably need *) +(* better names. *) +(* int_zmod_closed A == The integral closure of A is closed under subtraction. *) +(* int_mulr_closed A == The integral closure of A is closed under multiplication. *) +(* tr L l k == The trace of l * k on L; the result is in the field of scalars F. *) +(* The function tr is scalar in its first argument. *) +(* tr_sym == The trace function is commutative. *) +(* ndeg Q V <-> The binary function Q : vT -> vT -> rT is nondegenerate on the *) +(* subspace V. *) +(* dual_basis U X == The dual basis of U for X, with respect to the trace bilinear form. *) +(* trK K L == The trace function on L viewed as a subfield over K. *) +(* trK_int A K L == If k and l are integral over A then their trace is in A, provided *) +(* A is an integrally closed domain, K is its field of fractions, and *) +(* L extends K. *) +(* module A M <-> M is an A-module. *) +(* span_mod A X == The A-module generated by X. *) +(* submod A M N <-> M is a submodule of N over A. *) +(* basis_of_mod A M X <-> X is the basis of the A-module M. *) +(* ideal A N <-> N is an A-ideal. *) +(* PID A <-> Every ideal in A is principal. *) +(* int_mod_closed A L == The integral closure of A in L is an A-module. *) +(* basis_lemma I Ifr K == The integral closure of I in K is a free module, provided I is an *) +(* integrally-closed principal ideal domain contained in K, Ifr is the *) +(* field of fractions of I, and the trace function trK Ifr K is *) +(* nondegenerate on K. *) +(************************************************************************************************) + +Import GRing.Theory. +Import DefaultKeying GRing.DefaultPred. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Local Open Scope ring_scope. + +Section Integral. + +Variable (F : fieldType) (L0 : fieldExtType F) (A : pred L0) (K L : {subfield L0}). + +Hypothesis Asubr : subring_closed A. + +Definition integral l := exists p, [/\ p \is monic, p \is a polyOver A & root p l]. +Definition int_closed := {in A, forall a b, integral (a / b) -> (a / b) \in A}. +Definition int_closure l := l \in L /\ integral l. +Definition is_frac_field := {subset A <= K} /\ exists f, forall k, f k != 0 /\ + (k \in K -> f k \in A /\ f k * k \in A). + +Hypothesis AfracK : is_frac_field. + +Lemma frac_field_alg_int : exists f, forall l, [/\ f l != 0, f l \in A & integral (f l * l)]. +Proof. +have [Aid _ Amcl] := Asubr; have Amulr : mulr_closed A := Asubr. +have [AsubK [f /all_and2-[fH0 /(_ _)/all_and2-/all_and2-[fHa fHk]]]] := AfracK. +pose g := fun l => let p := minPoly K l in \prod_(i < size p) f p`_i; exists g => l. +pose p := minPoly K l; pose n := (size p).-1. +pose s := mkseq (fun i => p`_i * (g l) ^+ (n - i)%N) (size p). +have kI (i : 'I_(size p)) : p`_i \in K by apply/all_nthP => //; apply/minPolyOver. +have glA : g l \in A by rewrite/g; elim/big_ind: _ => // i _; apply/fHa. +have pmon: p`_n = 1 by have /monicP := monic_minPoly K l. +have an1: nth 0 s n = 1 by rewrite /n nth_mkseq ?pmon ?mul1r ?subnn ?size_minPoly. +have eqPs: (Poly s) = s :> seq L0. + by rewrite (PolyK (c := 0)) // -nth_last size_mkseq an1 oner_neq0. +have ilen i : i < size p -> i <= n by move => iB; rewrite /n -ltnS prednK // size_minPoly. +split => //; first by apply/prodf_neq0 => i _. +exists (Poly s); split; last first; last by rewrite monicE lead_coefE eqPs // size_mkseq an1. + rewrite /root -(mulr0 ((g l) ^+ n)); have <- := minPolyxx K l. + rewrite !horner_coef eqPs size_mkseq big_distrr; apply/eqP/eq_bigr => i _. + rewrite nth_mkseq // exprMn //=; rewrite !mulrA; congr (_ * _); rewrite -mulrA mulrC. + by congr (_ * _); rewrite -exprD subnK ?ilen. +apply/(all_nthP 0) => i; rewrite eqPs size_mkseq => iB; rewrite nth_mkseq //. + have := ilen _ iB; rewrite leq_eqVlt => /orP. + case; first by move /eqP ->; rewrite subnn pmon mulr1. + rewrite -subn_gt0 => {pmon ilen eqPs an1} /prednK <-; rewrite exprS mulrA /= Amcl ?rpredX //. + rewrite /g (bigD1 (Ordinal iB)) //= mulrA; apply/Amcl. + by rewrite mulrC; apply/fHk/(kI (Ordinal iB)). + by rewrite rpred_prod => // j _; apply/fHa. +Qed. + +Lemma int_clos_incl a : a \in A -> integral a. +Proof. +move=> ainA; exists ('X - a%:P); rewrite monicXsubC root_XsubC. +rewrite polyOverXsubC => //; by exact Asubr. +Qed. + +Lemma intPl (I : eqType) G (r : seq I) l : has (fun x => G x != 0) r -> + (forall e, e \in r -> {f | \sum_(e' <- r) f e' * G e' = l * G e & forall e', f e' \in A}) -> + integral l. +Proof. +have Aaddr : addr_closed A := Asubr; have Amulr : mulr_closed A := Asubr. +have Aoppr : oppr_closed A := Asubr; have [Aid _ _] := Asubr. +move => rn gen; pose s := in_tuple r; pose g j := gen (tnth s j) (mem_tnth j s). +pose f j := sval (g j); pose fH j := svalP (g j). +pose M := \matrix_(i, j < size r) f j (tnth s i). +exists (char_poly M); rewrite char_poly_monic; split => //. + apply/rpred_sum => p _; apply/rpredM; first by apply/rpredX; rewrite rpredN polyOverC. + apply/rpred_prod => i _; rewrite !mxE /= rpredB ?rpredMn ?polyOverX ?polyOverC ?/f //. + by have [_ fH2] := fH (perm.PermDef.fun_of_perm p i). +rewrite -eigenvalue_root_char; apply/eigenvalueP; move: rn => /hasP[x] /(nthP x)[k kB <- xn]. +exists (\row_(i < size r) G (tnth s i)); last first. + move: xn; apply/contra => /eqP/matrixP-v0; have := v0 0 (Ordinal kB). + by rewrite !mxE (tnth_nth x) => <-. +rewrite -rowP => j; rewrite !mxE; have [fH1 _] := fH j; rewrite -fH1 (big_nth x) big_mkord. +by apply/eq_bigr => /= i _; rewrite /M !mxE (tnth_nth x) mulrC. +Qed. + +Lemma intPr l : integral l -> exists r : seq L0, + [/\ r != nil, all A r & \sum_(i < size r) r`_i * l ^+ i = l ^+ (size r)]. +Proof. +move => [p [pm pA pr]]; pose n := size p; pose r := take n.-1 (- p). +have ps : n > 1. + rewrite ltnNge; apply/negP => /size1_polyC pc; rewrite pc in pr pm => {pc}. + move: pr => /rootP; rewrite hornerC => pc0. + by move: pm; rewrite monicE lead_coefC pc0 eq_sym oner_eq0. +have rs : size r = n.-1 by rewrite /r size_takel // size_opp leq_pred. +exists r; split. + apply/eqP => /nilP; rewrite /nilp /r size_takel; last by rewrite size_opp leq_pred. + by rewrite -subn1 subn_eq0 leqNgt ps. + have : - p \is a polyOver A by rewrite rpredN //; exact Asubr. + by move => /allP-popA; apply/allP => x /mem_take /popA. +move: pr => /rootP; rewrite horner_coef -(prednK (n := size p)); last by rewrite ltnW. +rewrite big_ord_recr /= rs; have := monicP pm; rewrite /lead_coef => ->; rewrite mul1r => /eqP. +rewrite addrC addr_eq0 -sumrN => /eqP => ->; apply/eq_bigr => i _; rewrite /r nth_take //. +by rewrite coefN mulNr. +Qed. + +Lemma int_subring_closed a b : integral a -> integral b -> + integral (a - b) /\ integral (a * b). +Proof. +have [A0 _ ] := (Asubr : zmod_closed A); have [A1 Asubr2 Amulr2] := Asubr. +move => /intPr[ra [/negbTE-ran raA raS]] /intPr[rb [/negbTE-rbn rbA rbS]]. +pose n := size ra; pose m := size rb; pose r := Finite.enum [finType of 'I_n * 'I_m]. +pose G (z : 'I_n * 'I_m) := let (k, l) := z in a ^ k * b ^l. +have [nz mz] : 0 < n /\ 0 < m. + by rewrite !lt0n; split; apply/negP; move => /nilP/eqP; rewrite ?ran ?rbn. +have rnn : has (fun x => G x != 0) r. + apply/hasP; exists (Ordinal nz, Ordinal mz); first by rewrite /r -enumT mem_enum. + by rewrite /G mulr1 oner_neq0. +pose h s i : 'I_(size s) -> L0 := fun k => if (i != size s) then (i == k)%:R else s`_k. +pose f i j (z : 'I_n * 'I_m) : L0 := let (k, l) := z in h ra i k * h rb j l. +have fA i j : forall z, f i j z \in A. + have hA s k l : all A s -> h s k l \in A. + move => /allP-sa; rewrite /h; case (eqVneq k (size s)) => [/eqP ->|->]. + by apply/sa/mem_nth. + by case (eqVneq k l) => [/eqP ->|/negbTE ->]. + by move => [k l]; rewrite /f; apply/Amulr2; apply/hA. +have fS i j : (i <= n) -> (j <= m) -> \sum_(z <- r) f i j z * G z = a ^ i * b ^ j. + have hS s k c : (k <= size s) -> \sum_(l < size s) s`_l * c ^ l = c ^ (size s) -> + \sum_(l < size s) h s k l * c ^ l = c ^ k. + move => kB sS; rewrite /h; case (eqVneq k (size s)) => [->|kn {sS}]; first by rewrite eqxx. + rewrite kn; rewrite leq_eqVlt (negbTE kn) /= in kB => {kn}. + rewrite (bigD1 (Ordinal kB)) //= eqxx mul1r /= -[RHS]addr0; congr (_ + _). + by apply/big1 => l; rewrite eq_sym => kl; have : k != l := kl => /negbTE ->; rewrite mul0r. + move => iB jB; rewrite -(hS ra i a) // -(hS rb j b) // mulr_suml. + rewrite (eq_bigr (fun k => \sum_(l < m) (h ra i k * a ^ k) * (h rb j l * b ^ l))). + rewrite pair_bigA; apply eq_bigr => [[k l] _]; rewrite !mulrA; congr (_ * _). + by rewrite -!mulrA [in h rb j l * a ^ k] mulrC. + by move => k _; rewrite mulr_sumr. +pose fB i j z := f i.+1 j z - f i j.+1 z; pose fM i j z := f i.+1 j.+1 z. +have fBA i j z : fB i j z \in A by rewrite /fB Asubr2. +have fBM i j z : fM i j z \in A by rewrite /fM. +split; apply/(@intPl _ G r) => //= [[i j] _]; [exists (fB i j) | exists (fM i j)] => //. + rewrite /fB [in RHS]/G mulrBl mulrA -exprS [in b * (a ^ i * b ^ j)] mulrC -mulrA -exprSr. + rewrite -(fS _ _ (ltnW (ltn_ord i))) // -(fS _ _ _ (ltnW (ltn_ord j))) //. + by rewrite -sumrB; apply/eq_bigr => [[k l] _]; apply/mulrBl. +by rewrite /fM [in RHS]/G mulrA [in (a * b) * a ^ i] mulrC mulrA -exprSr -mulrA -exprS -!fS. +Qed. + +Lemma int_zmod_closed a b : integral a -> integral b -> integral (a - b). +Proof. by move => aI bI; have [Azmod] := int_subring_closed aI bI. Qed. + +Lemma int_mulr_closed a b : integral a -> integral b -> integral (a * b). +Proof. by move => aI bI; have [_] := int_subring_closed aI bI. Qed. + +End Integral. + +Section Trace. + +Variable (F : fieldType) (L0 : fieldExtType F) (A : pred L0) (L : {subfield L0}). + +Implicit Types k l : L0. + +Definition tr : L0 -> L0 -> F := fun l k => + let X := vbasis L in + let M := \matrix_(i, j) coord X i (l * k * X`_j) + in \tr M. + +Fact tr_is_scalar l : scalar (tr l). +Proof. +move => c a b; rewrite /tr -!linearP /=; congr (\tr _); apply/matrixP => i j; rewrite !mxE. +by rewrite mulrDr mulrDl linearD /= -scalerAr -scalerAl linearZ. +Qed. + +Canonical tr_additive l := Additive (@tr_is_scalar l). +Canonical tr_linear l := AddLinear (@tr_is_scalar l). + +Lemma tr_sym : commutative tr. +Proof. by move => a b; rewrite /tr mulrC. Qed. + +Hypothesis Asubr : subring_closed A. +Hypothesis Aint : int_closed A. +Hypothesis Afrac : is_frac_field A 1%AS. + +Lemma tr_int k l : integral A k -> integral A l -> (tr k l)%:A \in A. +Proof. admit. Qed. + +Section NDeg. + +Variable (vT : vectType F) (rT : ringType) (Q : vT -> vT -> rT) (V : {vspace vT}). + +Definition ndeg := forall (l : vT), l != 0 -> l \in V -> exists (k : vT), k \in V /\ Q l k != 0. + +End NDeg. + +Variable (U : {vspace L0}). +Let m := \dim U. +Variable (X : m.-tuple L0). + +Lemma dual_basis_def : + {Y : m.-tuple L0 | ndeg tr U -> basis_of U X -> basis_of U Y /\ + forall (i : 'I_m), tr X`_i Y`_i = 1 /\ + forall (j : 'I_m), j != i -> tr X`_i Y`_j = 0}. +Proof. +pose Uv := subvs_vectType U; pose Fv := subvs_FalgType (1%AS : {aspace L0}); +pose HomV := [vectType _ of 'Hom(Uv, Fv)]. +pose tr_sub : Uv -> Uv -> Fv := fun u v => (tr (vsval u) (vsval v))%:A. +have HomVdim : \dim {:HomV} = m by rewrite dimvf /Vector.dim /= /Vector.dim /= dimv1 muln1. +have [f fH] : {f : 'Hom(Uv, HomV) | forall u, f u =1 tr_sub u}. + have lf1 u : linear (tr_sub u) by move => c x y; rewrite /tr_sub linearP scalerDl scalerA. + have lf2 : linear (fun u => linfun (Linear (lf1 u))). + move => c x y; rewrite -lfunP => v; rewrite add_lfunE scale_lfunE !lfunE /= /tr_sub. + by rewrite tr_sym linearP scalerDl scalerA /=; congr (_ + _); rewrite tr_sym. + by exists (linfun (Linear lf2)) => u v; rewrite !lfunE. +have [Xdual XdualH] : {Xdual : m.-tuple HomV | + forall (i : 'I_m) u, Xdual`_i u = (coord X i (vsval u))%:A}. + have lg (i : 'I_m) : linear (fun u : Uv => (coord X i (vsval u))%:A : Fv). + by move => c x y; rewrite linearP /= scalerDl scalerA. + exists (mktuple (fun i => linfun (Linear (lg i)))) => i u. + by rewrite -tnth_nth tnth_mktuple !lfunE. +have [finv finvH] : {finv : 'Hom(HomV, L0) | finv =1 vsval \o (f^-1)%VF}. + by exists (linfun vsval \o f^-1)%VF => u; rewrite comp_lfunE lfunE. +pose Y := map_tuple finv Xdual; exists Y => Und Xb. +have Ydef (i : 'I_m) : Y`_i = finv Xdual`_i by rewrite -!tnth_nth tnth_map. +have XiU (i : 'I_m) : X`_i \in U by apply/(basis_mem Xb)/mem_nth; rewrite size_tuple. +have Xii (i : 'I_m) : coord X i X`_i = 1%:R. + by rewrite coord_free ?eqxx //; exact (basis_free Xb). +have Xij (i j : 'I_m) : j != i -> coord X i X`_j = 0%:R. + by rewrite coord_free; [move => /negbTE -> | exact (basis_free Xb)]. +have Xdualb : basis_of fullv Xdual. + suffices Xdualf : free Xdual. + rewrite /basis_of Xdualf andbC /= -dimv_leqif_eq ?subvf // eq_sym HomVdim. + by move: Xdualf; rewrite /free => /eqP => ->; rewrite size_tuple. + apply/freeP => k sX i. + suffices: (\sum_(i < m) k i *: Xdual`_i) (vsproj U X`_i) = (k i)%:A. + by rewrite sX zero_lfunE => /esym /eqP; rewrite scaler_eq0 oner_eq0 orbF => /eqP. + rewrite sum_lfunE (bigD1 i) //= scale_lfunE XdualH vsprojK // Xii. + rewrite scaler_nat -[RHS]addr0; congr (_ + _); apply/big1 => j; rewrite eq_sym => ineqj. + by rewrite scale_lfunE XdualH vsprojK ?Xij // scaler_nat scaler0. +have finj : (lker f = 0)%VS. + apply/eqP; rewrite -subv0; apply/subvP=> u; rewrite memv_ker memv0 => /eqP-f0. + apply/contraT => un0; have {un0} [k [kiU /negP[]]] := Und (vsval u) un0 (subvsP u). + have /eqP := fH u (vsproj U k). + by rewrite /tr_sub vsprojK // f0 zero_lfunE eq_sym scaler_eq0 oner_eq0 orbF. +have flimg : limg f = fullv. + apply/eqP; rewrite -dimv_leqif_eq ?subvf // limg_dim_eq; last by rewrite finj capv0. + by rewrite HomVdim dimvf /Vector.dim. +have finvK : cancel finv (f \o vsproj U). + by move => u; rewrite finvH /= vsvalK; apply/limg_lfunVK; rewrite flimg memvf. +have finv_inj : (lker finv = 0)%VS by apply/eqP/lker0P/(can_inj finvK). +have finv_limg : limg finv = U. + apply/eqP; rewrite -dimv_leqif_eq; first by rewrite limg_dim_eq ?HomVdim ?finv_inj ?capv0. + by apply/subvP => u /memv_imgP [h _] ->; rewrite finvH subvsP. +have Xt (i j : 'I_m) : (f \o vsproj U) Y`_j (vsproj U X`_i) = (tr Y`_j X`_i)%:A. + by rewrite fH /tr_sub !vsprojK // Ydef finvH subvsP. +have Xd (i j : 'I_m) : (f \o vsproj U) Y`_j (vsproj U X`_i) = Xdual`_j (vsproj U X`_i). + by rewrite Ydef finvK. +have Ainj := fmorph_inj [rmorphism of in_alg Fv]. +split => [| i]; first by rewrite -{1}finv_limg limg_basis_of // capfv finv_inj. +split => [| j]; first by have := Xt i i; rewrite tr_sym Xd XdualH vsprojK // Xii => /Ainj. +by rewrite eq_sym => inj; have := Xt i j; rewrite tr_sym Xd XdualH vsprojK // Xij // => /Ainj. +Qed. + +Definition dual_basis : m.-tuple L0 := sval dual_basis_def. + +Hypothesis Und : ndeg tr U. +Hypothesis Xb : basis_of U X. + +Lemma dualb_basis : basis_of U dual_basis. +Proof. have [Yb _] := svalP dual_basis_def Und Xb; exact Yb. Qed. + +Lemma dualb_orth : + forall (i : 'I_m), tr X`_i dual_basis`_i = 1 /\ + forall (j : 'I_m), j != i -> tr X`_i dual_basis`_j = 0. +Proof. by have [_] := svalP dual_basis_def Und Xb. Qed. + +End Trace. + +Section TraceFieldOver. + +Variable (F : fieldType) (L0 : fieldExtType F) (A : pred L0) (K L : {subfield L0}). + +Implicit Types k l : L0. + +Let K' := subvs_fieldType K. +Let L0' := fieldOver_fieldExtType K. + +Definition trK : L0 -> L0 -> K' := tr (aspaceOver K L). + +Lemma trK_ndeg (U : {aspace L0}) : (K <= U)%VS -> + (ndeg trK U <-> ndeg (tr (aspaceOver K L)) (aspaceOver K U)). +Proof. +move => UsubL; have UU' : aspaceOver K U =i U := mem_aspaceOver UsubL. +split => [ndK l lnz | nd l lnz]. + by rewrite UU' => liU; have [k] := ndK l lnz liU; exists k; rewrite UU'. +by rewrite -UU' => liU'; have [k] := nd l lnz liU'; exists k; rewrite -UU'. +Qed. + +Hypothesis Asubr : subring_closed A. +Hypothesis Aint : int_closed A. +Hypothesis Afrac : is_frac_field A K. +Hypothesis AsubL : {subset A <= L}. + +Lemma trK_int k l : integral A k -> integral A l -> ((trK k l)%:A : L0') \in A. +Proof. admit. Qed. + +End TraceFieldOver. + +Section BasisLemma. + +Section Modules. + +Variable (F : fieldType) (L0 : fieldExtType F) (A : pred L0). + +Implicit Types M N : L0 -> Prop. + +Definition module M := M 0 /\ forall a k l, a \in A -> M k -> M l -> M (a * k - l). +Definition span_mod X m := exists2 r : (size X).-tuple L0, + all A r & m = \sum_(i < size X) r`_i * X`_i. +Definition submod M N := forall m, M m -> N m. +Definition basis_of_mod M X := free X /\ submod M (span_mod X) /\ forall m, m \in X -> M m. +Definition ideal N := submod N A /\ module N. +Definition PID := forall (N : L0 -> Prop), ideal N -> + exists2 a, N a & forall v, N v -> exists2 d, d \in A & d * a = v. + +Variable L : {subfield L0}. + +Hypothesis Asubr : subring_closed A. +Hypothesis AsubL : {subset A <= L}. + +Lemma int_mod_closed : module (int_closure A L). +Proof. +have [A0 _] : zmod_closed A := Asubr; split. + by rewrite /int_closure mem0v; split => //; apply/int_clos_incl. +move => a k l aA [kI kL] [lI lL]; split; first by rewrite rpredB ?rpredM //; apply/AsubL. +by apply/int_zmod_closed => //; apply/int_mulr_closed => //; apply/int_clos_incl. +Qed. + +End Modules. + +Variable (F0 : fieldType) (E : fieldExtType F0) (I : pred E) (Ifr K : {subfield E}). + +Hypothesis Isubr : subring_closed I. +Hypothesis Iint : int_closed I. +Hypothesis Ipid : PID I. +Hypothesis Ifrac : is_frac_field I Ifr. +Hypothesis IsubK : {subset I <= K}. +Hypothesis Knd : ndeg (trK Ifr K) K. + +Lemma basis_lemma : exists X : (\dim_Ifr K).-tuple E, basis_of_mod I (int_closure I K) X. +Proof. +suffices FisK (F : fieldType) (L0 : fieldExtType F) (A : pred L0) (L : {subfield L0}) : + subring_closed A -> int_closed A -> PID A -> is_frac_field A 1 -> ndeg (tr L) L -> + exists2 X, size X == \dim L & basis_of_mod A (int_closure A L) X. + have [Isub [f /all_and2[fH0 fHk]]] := Ifrac; pose F := subvs_fieldType Ifr; + pose L0 := fieldOver_fieldExtType Ifr; pose L := aspaceOver Ifr K. + have Ifrsub : (Ifr <= K)%VS. + apply/subvP=> x /fHk-[fHx fHxx]; rewrite -(mulKf (fH0 x) x). + by apply/memvM; rewrite ?memvV; apply/IsubK. + have LK : L =i K := mem_aspaceOver Ifrsub; have Lnd : ndeg (tr L) L by rewrite -trK_ndeg. + have Ifrac1 : is_frac_field (I : pred L0) 1. + split; first by move => a; rewrite /= trivial_fieldOver; apply/Isub. + by exists f => k; split => //; rewrite trivial_fieldOver => /fHk. + have [X Xsize [Xf [Xs Xi]]] := FisK _ L0 _ _ Isubr Iint Ipid Ifrac1 Lnd. + rewrite -dim_aspaceOver => //; have /eqP <- := Xsize; exists (in_tuple X); split; last first. + split => m; last by move => /Xi; rewrite /int_closure LK. + by rewrite /int_closure -LK; move => /Xs. + move: Xf; rewrite -{1}(in_tupleE X); move => /freeP-XfL0; apply/freeP => k. + have [k' kk'] : exists k' : 'I_(size X) -> F, forall i, (k i)%:A = vsval (k' i). + by exists (fun i => vsproj Ifr (k i)%:A) => i; rewrite vsprojK ?rpredZ ?mem1v. + pose Ainj := fmorph_inj [rmorphism of in_alg E]. + move => kS i; apply/Ainj => {Ainj} /=; rewrite scale0r kk'; apply/eqP. + rewrite raddf_eq0; last by apply/subvs_inj. + by apply/eqP/XfL0; rewrite -{3}kS => {i}; apply/eq_bigr => i _; rewrite -[RHS]mulr_algl kk'. +move => Asubr Aint Apid Afrac1 Lnd; pose n := \dim L; have Amulr : mulr_closed A := Asubr. +have [A0 _] : zmod_closed A := Asubr; have [Asub1 _] := Afrac1. +have AsubL : {subset A <= L} by move => a /Asub1; exact (subvP (sub1v L) a). +have [b1 [b1B b1H]] : exists (b1 : n.-tuple L0), [/\ basis_of L b1 & + forall i : 'I_n, integral A b1`_i]. + pose b0 := vbasis L; have [f /all_and3-[fH0 fHa fHi]] := frac_field_alg_int Asubr Afrac1. + pose d := \prod_(i < n) f b0`_i; pose b1 := map_tuple (amulr d) b0. + exists b1; split; last first => [i|]. + rewrite (nth_map 0) /d; last by rewrite size_tuple. + rewrite lfunE /= (bigD1 i) //= mulrA; apply/int_mulr_closed => //; first by rewrite mulrC. + by apply/int_clos_incl => //; rewrite rpred_prod. + have dun : d \is a GRing.unit by rewrite unitfE /d; apply/prodf_neq0 => i _. + have lim : (amulr d @: L = L)%VS. + have dinA : d \in A by rewrite rpred_prod. + rewrite limg_amulr; apply/eqP; rewrite -dimv_leqif_eq; first by rewrite dim_cosetv_unit. + by apply/prodv_sub => //; apply/AsubL. + rewrite -lim limg_basis_of //; last by apply/vbasisP. + by have /eqP -> := lker0_amulr dun; rewrite capv0. +have [b2 [/andP[/eqP-b2s b2f] b2H]] : exists (b2 : n.-tuple L0), [/\ basis_of L b2 & + forall b, b \in L -> integral A b -> forall i, (coord b2 i b)%:A \in A]. + pose b2 := dual_basis L b1; have b2B := dualb_basis Lnd b1B; exists b2; rewrite b2B. + split => // b biL bint i; suffices <-: tr L b1`_i b = coord b2 i b by rewrite tr_int. + have -> : tr L b1`_i b = \sum_(j < n) coord b2 j b * tr L b1`_i b2`_j. + by rewrite {1}(coord_basis b2B biL) linear_sum; apply/eq_bigr => j _; rewrite linearZ. + rewrite (bigD1 i); have [oi oj //] := dualb_orth Lnd b1B i; rewrite /= oi mulr1 -[RHS]addr0. + by congr (_ + _); apply/big1 => j jneqi; rewrite (oj j jneqi) mulr0. +have Mbasis k (X : k.-tuple L0) M : free X -> module A M -> submod M (span_mod A X) -> + exists B, basis_of_mod A M B. + move: k X M; elim => [X M _ _ Ms | k IH X M Xf [M0 Mm] Ms]. + by exists [::]; rewrite /basis_of_mod nil_free; move: Ms; rewrite tuple0. + pose X1 := [tuple of behead X]; pose v := thead X. + pose M1 := fun m => M m /\ coord X ord0 m = 0. + pose M2 := fun (a : L0) => exists2 m, M m & (coord X ord0 m)%:A = a. + have scr r m : r \in A -> exists c, r * m = c *: m. + by move => /Asub1/vlineP[c ->]; exists c; rewrite mulr_algl. + have span_coord m : M m -> exists r : (k.+1).-tuple L0, + [/\ all A r, m = \sum_(i < k.+1) r`_i * X`_i & forall i, (coord X i m)%:A = r`_i]. + have seqF (s : seq L0) : all A s -> exists s', s = [seq c%:A | c <- s']. + elim: s => [_| a l IHl /= /andP[/Asub1/vlineP[c ->]]]; first by exists [::]. + by move => /IHl[s' ->]; exists (c :: s'). + move => mM; have := Ms m mM; rewrite /span_mod !size_tuple; move => [r rA rS]. + exists r; split => //; have [rF rFr] := seqF r rA => {seqF}; rewrite rFr in rA. + have rFs : size rF = k.+1 by rewrite -(size_tuple r) rFr size_map. + have -> : m = \sum_(i < k.+1) rF`_i *: X`_i. + by rewrite rS; apply/eq_bigr => i _; rewrite rFr (nth_map 0) ?rFs // mulr_algl. + by move => i; rewrite coord_sum_free // rFr (nth_map 0) ?rFs. + have [B1 [B1f [B1s B1A]]] : exists B1, basis_of_mod A M1 B1. + have X1f : free X1 by move: Xf; rewrite (tuple_eta X) free_cons => /andP[_]. + apply/(IH X1) => //. + rewrite /module /M1 linear0; split => // a x y aA [xM xfc0] [yM yfc0]. + have := Mm a x y aA xM yM; move: aA => /Asub1/vlineP[r] ->; rewrite mulr_algl => msc. + by rewrite /M1 linearB linearZ /= xfc0 yfc0 subr0 mulr0. + move => m [mM mfc0]; have := span_coord m mM; move => [r [rA rS rC]]. + move: mfc0 (rC 0) ->; rewrite scale0r; move => r0; rewrite /span_mod size_tuple. + exists [tuple of behead r]; first by apply/allP => a /mem_behead/(allP rA). + by rewrite rS big_ord_recl -r0 mul0r add0r; apply/eq_bigr => i _; rewrite !nth_behead. + have [a [w wM wC] aG] : exists2 a, M2 a & forall v, M2 v -> exists2 d, d \in A & d * a = v. + apply/Apid; split. + move => c [m mM <-]; have := span_coord m mM; move => [r [/all_nthP-rA _ rC]]. + by move: rC ->; apply/rA; rewrite size_tuple. + split; first by exists 0 => //; rewrite linear0 scale0r. + move => c x y cA [mx mxM mxC] [my myM myC]; have := Mm c mx my cA mxM myM. + move: cA => /Asub1/vlineP[r] ->; rewrite !mulr_algl => mC. + by exists (r *: mx - my) => //; rewrite linearB linearZ /= scalerBl -scalerA mxC myC. + pose Ainj := fmorph_inj [rmorphism of in_alg L0]. + have mcM1 m : M m -> exists2 d, d \in A & d * a = (coord X 0 m)%:A. + by move => mM; apply/aG; exists m. + case: (eqVneq a 0) => [| an0]. + exists B1; split => //; split => [m mM |]; last by move => m /B1A[mM]. + apply/B1s; split => //; apply/Ainj => /=; have [d _ <-] := mcM1 m mM. + by rewrite a0 mulr0 scale0r. + exists (w :: B1); split. + rewrite free_cons B1f andbT; move: an0; apply/contra; move: wC <-. + rewrite -(in_tupleE B1); move => /coord_span ->; apply/eqP. + rewrite linear_sum big1 ?scale0r => //= i _; rewrite linearZ /=. + by have [_] := B1A B1`_i (mem_nth 0 (ltn_ord _)) => ->; rewrite mulr0. + split => [m mM | m]; last by rewrite in_cons; move => /orP; case => [/eqP ->|/B1A[mM]]. + have [d dA dam] := mcM1 m mM; have mdwM1 : M1 (m - d * w). + split; [have Mdwm := Mm d w m dA wM mM; have := Mm _ _ _ A0 Mdwm Mdwm |]. + by rewrite mul0r sub0r opprB. + move: dA dam => /Asub1/vlineP[r] -> {d}; rewrite !mulr_algl linearB linearZ /= => rac. + by apply/Ainj => /=; rewrite scalerBl -scalerA wC rac subrr scale0r. + have [r rA rS] := B1s _ mdwM1; exists [tuple of d :: r]; first by rewrite /= rA andbT. + by move: rS => /eqP; rewrite subr_eq addrC => /eqP ->; rewrite /= big_ord_recl. +have [X Xb] : exists X, basis_of_mod A (int_closure A L) X. + apply/(Mbasis _ b2 _ b2f) => [| m [mL mI]]; first by apply/int_mod_closed. + pose r : n.-tuple L0 := [tuple (coord b2 i m)%:A | i < n]; rewrite /span_mod size_tuple. + exists r; have rci (i : 'I_n) : r`_i = (coord b2 i m)%:A by rewrite -tnth_nth tnth_mktuple. + apply/(all_nthP 0) => i; rewrite size_tuple; move => iB. + by have -> := rci (Ordinal iB); apply/b2H. + move: mL; rewrite -b2s; move => /coord_span ->; apply/eq_bigr => i _. + by rewrite rci mulr_algl. +exists X => //; move: Xb => [/eqP-Xf [Xs Xg]]; rewrite -Xf eqn_leq; apply/andP; split. + by apply/dimvS/span_subvP => m /Xg[mL _]. +have /andP[/eqP-b1s _] := b1B; rewrite -b1s; apply/dimvS/span_subvP => b /tnthP-[i ->] {b}. +rewrite (tnth_nth 0); have [r /all_tnthP-rA ->] : span_mod A X b1`_i. + by apply/Xs; rewrite /int_closure (basis_mem b1B) ?mem_nth ?size_tuple => //. +apply/rpred_sum => j _; have := rA j; rewrite (tnth_nth 0); move => /Asub1/vlineP[c ->]. +by rewrite mulr_algl; apply/rpredZ/memv_span/mem_nth. +Qed. + +End BasisLemma.
\ No newline at end of file diff --git a/mathcomp/attic/all.v b/mathcomp/attic/all.v new file mode 100644 index 0000000..41badbb --- /dev/null +++ b/mathcomp/attic/all.v @@ -0,0 +1,9 @@ +Require Export algnum_basic. +Require Export amodule. +Require Export fib. +Require Export forms. +Require Export galgebra. +Require Export multinom. +Require Export mxtens. +Require Export quote. +Require Export tutorial. diff --git a/mathcomp/attic/amodule.v b/mathcomp/attic/amodule.v new file mode 100644 index 0000000..f23ed60 --- /dev/null +++ b/mathcomp/attic/amodule.v @@ -0,0 +1,417 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrbool ssrfun eqtype fintype finfun finset ssralg. +Require Import bigop seq tuple choice ssrnat prime ssralg fingroup pgroup. +Require Import zmodp matrix vector falgebra galgebra. + +(*****************************************************************************) +(* * Module over an algebra *) +(* amoduleType A == type for finite dimension module structure. *) +(* *) +(* v :* x == right product of the module *) +(* (M :* A)%VS == the smallest vector space that contains *) +(* {v :* x | v \in M & x \in A} *) +(* (modv M A) == M is a module for A *) +(* (modf f M A) == f is a module homomorphism on M for A *) +(*****************************************************************************) +(*****************************************************************************) + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Open Local Scope ring_scope. + +Delimit Scope amodule_scope with aMS. + +Import GRing.Theory. + +Module AModuleType. +Section ClassDef. + +Variable R : ringType. +Variable V: vectType R. +Variable A: FalgType R. + +Structure mixin_of (V : vectType R) : Type := Mixin { + action: A -> 'End(V); + action_morph: forall x a b, action (a * b) x = action b (action a x); + action_linear: forall x , linear (action^~ x); + action1: forall x , action 1 x = x +}. + +Structure class_of (V : Type) : Type := Class { + base : Vector.class_of R V; + mixin : mixin_of (Vector.Pack _ base V) +}. +Local Coercion base : class_of >-> Vector.class_of. + +Implicit Type phA : phant A. + +Structure type phA : Type := Pack {sort : Type; _ : class_of sort; _ : Type}. +Local Coercion sort : type >-> Sortclass. + +Definition class phA (cT : type phA):= + let: Pack _ c _ := cT return class_of cT in c. +Definition clone phA T cT c of phant_id (@class phA cT) c := @Pack phA T c T. + +Definition pack phA V V0 (m0 : mixin_of (@Vector.Pack R _ V V0 V)) := + fun bT b & phant_id (@Vector.class _ (Phant R) bT) b => + fun m & phant_id m0 m => Pack phA (@Class V b m) V. + +Definition eqType phA cT := Equality.Pack (@class phA cT) cT. +Definition choiceType phA cT := choice.Choice.Pack (@class phA cT) cT. +Definition zmodType phA cT := GRing.Zmodule.Pack (@class phA cT) cT. +Definition lmodType phA cT := GRing.Lmodule.Pack (Phant R) (@class phA cT) cT. +Definition vectType phA cT := Vector.Pack (Phant R) (@class phA cT) cT. + +End ClassDef. + +Module Exports. +Coercion base : class_of >-> Vector.class_of. +Coercion mixin : class_of >-> mixin_of. +Coercion sort : type >-> Sortclass. + +Coercion eqType : type >-> Equality.type. +Canonical Structure eqType. +Coercion choiceType : type >-> Choice.type. +Canonical Structure choiceType. +Coercion zmodType : type >-> GRing.Zmodule.type. +Canonical Structure zmodType. +Coercion lmodType : type>-> GRing.Lmodule.type. +Canonical Structure lmodType. +Coercion vectType : type >-> Vector.type. +Canonical Structure vectType. + +Notation amoduleType A := (@type _ _ (Phant A)). +Notation AModuleType A m := (@pack _ _ (Phant A) _ _ m _ _ id _ id). +Notation AModuleMixin := Mixin. + +Bind Scope ring_scope with sort. +End Exports. + +End AModuleType. +Import AModuleType.Exports. + +Section AModuleDef. +Variables (F : fieldType) (A: FalgType F) (M: amoduleType A). + +Definition rmorph (a: A) := AModuleType.action (AModuleType.class M) a. +Definition rmul (a: M) (b: A) : M := rmorph b a. +Notation "a :* b" := (rmul a b): ring_scope. + +Implicit Types x y: A. +Implicit Types v w: M. +Implicit Types c: F. + +Lemma rmulD x: {morph (rmul^~ x): v1 v2 / v1 + v2}. +Proof. move=> *; exact: linearD. Qed. + +Lemma rmul_linear_proof : forall v, linear (rmul v). +Proof. by rewrite /rmul /rmorph; case: M => s [] b []. Qed. +Canonical Structure rmul_linear v := GRing.Linear (rmul_linear_proof v). + +Lemma rmulA v x y: v :* (x * y) = (v :* x) :* y. +Proof. exact: AModuleType.action_morph. Qed. + +Lemma rmulZ : forall c v x, (c *: v) :* x = c *: (v :* x). +Proof. move=> c v x; exact: linearZZ. Qed. + +Lemma rmul0 : left_zero 0 rmul. +Proof. move=> x; exact: linear0. Qed. + +Lemma rmul1 : forall v , v :* 1 = v. +Proof. by rewrite /rmul /rmorph; case: M => s [] b []. Qed. + +Lemma rmul_sum : forall I r P (f : I -> M) x, + \sum_(i <- r | P i) f i :* x = (\sum_(i <- r | P i) f i) :* x. +Proof. +by move=> I r P f x; rewrite -linear_sum. +Qed. + +Implicit Types vs: {vspace M}. +Implicit Types ws: {vspace A}. + +Lemma size_eprodv : forall vs ws, + size (allpairs rmul (vbasis vs) (vbasis ws)) == (\dim vs * \dim ws)%N. +Proof. by move=> *; rewrite size_allpairs !size_tuple. Qed. + +Definition eprodv vs ws := span (Tuple (size_eprodv vs ws)). +Local Notation "A :* B" := (eprodv A B) : vspace_scope. + +Lemma memv_eprod vs ws a b : a \in vs -> b \in ws -> a :* b \in (vs :* ws)%VS. +Proof. +move=> Ha Hb. +rewrite (coord_vbasis Ha) (coord_vbasis Hb). +rewrite linear_sum /=; apply: memv_suml => j _. +rewrite -rmul_sum; apply: memv_suml => i _ /=. +rewrite linearZ memvZ //= rmulZ memvZ //=. +apply: memv_span; apply/allpairsP; exists ((vbasis vs)`_i, (vbasis ws)`_j)=> //. +by rewrite !mem_nth //= size_tuple. +Qed. + +Lemma eprodvP : forall vs1 ws vs2, + reflect (forall a b, a \in vs1 -> b \in ws -> a :* b \in vs2) + (vs1 :* ws <= vs2)%VS. +Proof. +move=> vs1 ws vs2; apply: (iffP idP). + move=> Hs a b Ha Hb. + by apply: subv_trans Hs; exact: memv_eprod. +move=> Ha; apply/subvP=> v. +move/coord_span->; apply: memv_suml=> i _ /=. +apply: memvZ. +set u := allpairs _ _ _. +have: i < size u by rewrite (eqP (size_eprodv _ _)). +move/(mem_nth 0); case/allpairsP=> [[x1 x2] [I1 I2 ->]]. +by apply Ha; apply: vbasis_mem. +Qed. + +Lemma eprod0v: left_zero 0%VS eprodv. +Proof. +move=> vs; apply subv_anti; rewrite sub0v andbT. +apply/eprodvP=> a b; case/vlineP=> k1 -> Hb. +by rewrite scaler0 rmul0 mem0v. +Qed. + +Lemma eprodv0 : forall vs, (vs :* 0 = 0)%VS. +Proof. +move=> vs; apply subv_anti; rewrite sub0v andbT. +apply/eprodvP=> a b Ha; case/vlineP=> k1 ->. +by rewrite scaler0 linear0 mem0v. +Qed. + +Lemma eprodv1 : forall vs, (vs :* 1 = vs)%VS. +Proof. +case: (vbasis1 A) => k Hk He /=. +move=> vs; apply subv_anti; apply/andP; split. + apply/eprodvP=> a b Ha; case/vlineP=> k1 ->. + by rewrite linearZ /= rmul1 memvZ. +apply/subvP=> v Hv. +rewrite (coord_vbasis Hv); apply: memv_suml=> [] [i Hi] _ /=. +apply: memvZ. +rewrite -[_`_i]rmul1; apply: memv_eprod; last by apply: memv_line. +by apply: vbasis_mem; apply: mem_nth; rewrite size_tuple. +Qed. + +Lemma eprodvSl ws vs1 vs2 : (vs1 <= vs2 -> vs1 :* ws <= vs2 :* ws)%VS. +Proof. +move=> Hvs; apply/eprodvP=> a b Ha Hb; apply: memv_eprod=> //. +by apply: subv_trans Hvs. +Qed. + +Lemma eprodvSr vs ws1 ws2 : (ws1 <= ws2 -> vs :* ws1 <= vs :* ws2)%VS. +Proof. +move=> Hvs; apply/eprodvP=> a b Ha Hb; apply: memv_eprod=> //. +by apply: subv_trans Hvs. +Qed. + +Lemma eprodv_addl: left_distributive eprodv addv. +Proof. +move=> vs1 vs2 ws; apply subv_anti; apply/andP; split. + apply/eprodvP=> a b;case/memv_addP=> v1 Hv1 [v2 Hv2 ->] Hb. + by rewrite rmulD; apply: memv_add; apply: memv_eprod. +apply/subvP=> v; case/memv_addP=> v1 Hv1 [v2 Hv2 ->]. +apply: memvD. + move: v1 Hv1; apply/subvP; apply: eprodvSl; exact: addvSl. +move: v2 Hv2; apply/subvP; apply: eprodvSl; exact: addvSr. +Qed. + +Lemma eprodv_sumr vs ws1 ws2 : (vs :* (ws1 + ws2) = vs :* ws1 + vs :* ws2)%VS. +Proof. +apply subv_anti; apply/andP; split. + apply/eprodvP=> a b Ha;case/memv_addP=> v1 Hv1 [v2 Hv2 ->]. + by rewrite linearD; apply: memv_add; apply: memv_eprod. +apply/subvP=> v; case/memv_addP=> v1 Hv1 [v2 Hv2 ->]. +apply: memvD. + move: v1 Hv1; apply/subvP; apply: eprodvSr; exact: addvSl. +move: v2 Hv2; apply/subvP; apply: eprodvSr; exact: addvSr. +Qed. + +Definition modv (vs: {vspace M}) (al: {aspace A}) := + (vs :* al <= vs)%VS. + +Lemma mod0v : forall al, modv 0 al. +Proof. by move=> al; rewrite /modv eprod0v subvv. Qed. + +Lemma modv1 : forall vs, modv vs (aspace1 A). +Proof. by move=> vs; rewrite /modv eprodv1 subvv. Qed. + +Lemma modfv : forall al, modv fullv al. +Proof. by move=> al; exact: subvf. Qed. + +Lemma memv_mod_mul : forall ms al m a, + modv ms al -> m \in ms -> a \in al -> m :* a \in ms. +Proof. +move=> ms al m a Hmo Hm Ha; apply: subv_trans Hmo. +by apply: memv_eprod. +Qed. + +Lemma modvD : forall ms1 ms2 al , + modv ms1 al -> modv ms2 al -> modv (ms1 + ms2) al. +Proof. +move=> ms1 ms2 al Hm1 Hm2; rewrite /modv eprodv_addl. +apply: (subv_trans (addvS Hm1 (subvv _))). +exact: (addvS (subvv _) Hm2). +Qed. + +Lemma modv_cap : forall ms1 ms2 al , + modv ms1 al -> modv ms2 al -> modv (ms1:&: ms2) al. +Proof. +move=> ms1 ms2 al Hm1 Hm2. +by rewrite /modv subv_cap; apply/andP; split; + [apply: subv_trans Hm1 | apply: subv_trans Hm2]; + apply: eprodvSl; rewrite (capvSr,capvSl). +Qed. + +Definition irreducible ms al := + [/\ modv ms al, ms != 0%VS & + forall ms1, modv ms1 al -> (ms1 <= ms)%VS -> ms != 0%VS -> ms1 = ms]. + +Definition completely_reducible ms al := + forall ms1, modv ms1 al -> (ms1 <= ms)%VS -> + exists ms2, + [/\ modv ms2 al, (ms1 :&: ms2 = 0)%VS & (ms1 + ms2)%VS = ms]. + +Lemma completely_reducible0 : forall al, completely_reducible 0 al. +Proof. +move=> al ms1 Hms1; rewrite subv0; move/eqP->. +by exists 0%VS; split; [exact: mod0v | exact: cap0v | exact: add0v]. +Qed. + +End AModuleDef. + +Notation "a :* b" := (rmul a b): ring_scope. +Notation "A :* B" := (eprodv A B) : vspace_scope. + +Section HomMorphism. + +Variable (K: fieldType) (A: FalgType K) (M1 M2: amoduleType A). + +Implicit Types ms : {vspace M1}. +Implicit Types f : 'Hom(M1, M2). +Implicit Types al : {aspace A}. + +Definition modf f ms al := + all (fun p => f (p.1 :* p.2) == f p.1 :* p.2) + (allpairs (fun x y => (x,y)) (vbasis ms) (vbasis al)). + +Lemma modfP : forall f ms al, + reflect (forall x v, v \in ms -> x \in al -> f (v :* x) = f v :* x) + (modf f ms al). +Proof. +move=> f ms al; apply: (iffP idP)=> H; last first. + apply/allP=> [] [v x]; case/allpairsP=> [[x1 x2] [I1 I2 ->]]. + by apply/eqP; apply: H; apply: vbasis_mem. +move=> x v Hv Hx; rewrite (coord_vbasis Hv) (coord_vbasis Hx). +rewrite !linear_sum; apply: eq_big=> //= i _. +rewrite !linearZ /=; congr (_ *: _). +rewrite -!rmul_sum linear_sum; apply: eq_big=> //= j _. +rewrite rmulZ !linearZ /= rmulZ; congr (_ *: _). +set x1 := _`_ _; set y1 := _ `_ _. +case: f H => f /=; move/allP; move/(_ (x1,y1))=> HH. +apply/eqP; apply: HH; apply/allpairsP; exists (x1, y1). +by rewrite !mem_nth //= size_tuple. +Qed. + +Lemma modf_zero : forall ms al, modf 0 ms al. +Proof. by move=> ms al; apply/allP=> i _; rewrite !lfunE rmul0. Qed. + +Lemma modf_add : forall f1 f2 ms al, + modf f1 ms al -> modf f2 ms al -> modf (f1 + f2) ms al. +Proof. +move=> f1 f2 ms al Hm1 Hm2; apply/allP=> [] [v x]. +case/allpairsP=> [[x1 x2] [I1 I2 ->]]; rewrite !lfunE rmulD /=. +move/modfP: Hm1->; try apply: vbasis_mem=>//. +by move/modfP: Hm2->; try apply: vbasis_mem. +Qed. + +Lemma modf_scale : forall k f ms al, modf f ms al -> modf (k *: f) ms al. +Proof. +move=> k f ms al Hm; apply/allP=> [] [v x]. +case/allpairsP=> [[x1 x2] [I1 I2 ->]]; rewrite !lfunE rmulZ /=. +by move/modfP: Hm->; try apply: vbasis_mem. +Qed. + +Lemma modv_ker : forall f ms al, + modv ms al -> modf f ms al -> modv (ms :&: lker f) al. +Proof. +move=> f ms al Hmd Hmf; apply/eprodvP=> x v. +rewrite memv_cap !memv_ker. +case/andP=> Hx Hf Hv. +rewrite memv_cap (memv_mod_mul Hmd) // memv_ker. +by move/modfP: Hmf=> ->; rewrite // (eqP Hf) rmul0 eqxx. +Qed. + +Lemma modv_img : forall f ms al, + modv ms al -> modf f ms al -> modv (f @: ms) al. +Proof. +move=> f ms al Hmv Hmf; apply/eprodvP=> v x. +case/memv_imgP=> u Hu -> Hx. +move/modfP: Hmf<-=> //. +apply: memv_img. +by apply: (memv_mod_mul Hmv). +Qed. + +End HomMorphism. + +Section ModuleRepresentation. + +Variable (F: fieldType) (gT: finGroupType) + (G: {group gT}) (M: amoduleType (galg F gT)). +Hypothesis CG: ([char F]^'.-group G)%g. +Implicit Types ms : {vspace M}. + +Let FG := gaspace F G. +Local Notation " g %:FG " := (injG _ g). + +Lemma Maschke : forall ms, modv ms FG -> completely_reducible ms FG. +Proof. +move=> ms Hmv ms1 Hms1 Hsub; rewrite /completely_reducible. +pose act g : 'End(M) := rmorph M (g%:FG). +have actE: forall g v, act g v = v :* g%:FG by done. +pose f: 'End(M) := #|G|%:R^-1 *: + \sum_(i in G) (act (i^-1)%g \o projv ms1 \o act i)%VF. +have Cf: forall v x, x \in FG -> f (v :* x) = f v :* x. + move=> v x; case/memv_sumP=> g_ Hg_ ->. + rewrite !linear_sum; apply: eq_big => //= i Hi. + move: (Hg_ _ Hi); case/vlineP=> k ->. + rewrite !linearZ /=; congr (_ *: _). + rewrite /f /= !lfunE /= !sum_lfunE rmulZ /=; congr (_ *: _). + rewrite -rmul_sum (reindex (fun g => (i^-1 * g)%g)); last first. + by exists (fun g => (i * g)%g)=> h; rewrite mulgA (mulVg, mulgV) mul1g. + apply: eq_big=> g; first by rewrite groupMl // groupV. + rewrite !lfunE /= !lfunE /= !actE -rmulA=> Hig. + have Hg: g \in G by rewrite -[g]mul1g -[1%g](mulgV i) -mulgA groupM. + by rewrite -injGM // mulgA mulgV mul1g invMg invgK !injGM + ?groupV // rmulA. +have Himf: forall v, v \in ms1 -> f v = v. + move=> v Hv. + rewrite /f !lfunE /= sum_lfunE (eq_bigr (fun x => v)); last move=> i Hi. + by rewrite sumr_const -scaler_nat scalerA mulVf // ?scale1r // -?charf'_nat. + rewrite !lfunE /= !lfunE /= projv_id !actE; last first. + by rewrite (memv_mod_mul Hms1) //= /gvspace (bigD1 i) // memvE addvSl. + by rewrite -rmulA -injGM // ?groupV // mulgV rmul1. +have If: limg f = ms1. + apply: subv_anti; apply/andP; split; last first. + by apply/subvP=> v Hv; rewrite -(Himf _ Hv) memv_img // memvf. + apply/subvP=> i; case/memv_imgP=> x _ ->. + rewrite !lfunE memvZ //= sum_lfunE memv_suml=> // j Hj. + rewrite lfunE /= lfunE (memv_mod_mul Hms1) //; first by exact: memv_proj. + by rewrite memvE /= /gvspace (bigD1 (j^-1)%g) ?addvSl // groupV. +exists (ms :&: lker f)%VS; split. + - apply: modv_ker=> //; apply/modfP=> *; exact: Cf. + apply/eqP; rewrite -subv0; apply/subvP=> v; rewrite memv0. + rewrite !memv_cap; case/andP=> Hv1; case/andP=> Hv2 Hv3. + by move: Hv3; rewrite memv_ker Himf. +apply: subv_anti; rewrite subv_add Hsub capvSl. +apply/subvP=> v Hv. +have->: v = f v + (v - f v) by rewrite addrC -addrA addNr addr0. +apply: memv_add; first by rewrite -If memv_img // memvf. +rewrite memv_cap; apply/andP; split. + apply: memvB=> //; apply: subv_trans Hsub. + by rewrite -If; apply: memv_img; exact: memvf. +rewrite memv_ker linearB /= (Himf (f v)) ?subrr // /in_mem /= -If. +by apply: memv_img; exact: memvf. +Qed. + +End ModuleRepresentation. + +Export AModuleType.Exports. diff --git a/mathcomp/attic/fib.v b/mathcomp/attic/fib.v new file mode 100644 index 0000000..e002a72 --- /dev/null +++ b/mathcomp/attic/fib.v @@ -0,0 +1,340 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype. +Require Import bigop div prime finfun tuple ssralg zmodp matrix binomial. + +(*****************************************************************************) +(* This files contains the definitions of: *) +(* fib n == n.+1 th fibonacci number *) +(* *) +(* lucas n == n.+1 lucas number *) +(* *) +(* and some of their standard properties *) +(*****************************************************************************) + +Fixpoint fib_rec (n : nat) {struct n} : nat := + if n is n1.+1 then + if n1 is n2.+1 then fib_rec n1 + fib_rec n2 + else 1 + else 0. + +Definition fib := nosimpl fib_rec. + +Lemma fibE : fib = fib_rec. +Proof. by []. Qed. + +Lemma fib0 : fib 0 = 0. +Proof. by []. Qed. + +Lemma fib1 : fib 1 = 1. +Proof. by []. Qed. + +Lemma fibSS : forall n, fib n.+2 = fib n.+1 + fib n. +Proof. by []. Qed. + +Fixpoint lin_fib_rec (a b n : nat) {struct n} : nat := + if n is n1.+1 then + if n1 is n2.+1 + then lin_fib_rec b (b + a) n1 + else b + else a. + +Definition lin_fib := nosimpl lin_fib_rec. + +Lemma lin_fibE : lin_fib = lin_fib_rec. +Proof. by []. Qed. + +Lemma lin_fib0 : forall a b, lin_fib a b 0 = a. +Proof. by []. Qed. + +Lemma lin_fib1 : forall a b, lin_fib a b 1 = b. +Proof. by []. Qed. + +Lemma lin_fibSS : forall a b n, lin_fib a b n.+2 = lin_fib b (b + a) n.+1. +Proof. by []. Qed. + +Lemma lin_fib_alt : forall n a b, + lin_fib a b n.+2 = lin_fib a b n.+1 + lin_fib a b n. +Proof. +case=>//; elim => [//|n IHn] a b. +by rewrite lin_fibSS (IHn b (b + a)) lin_fibE. +Qed. + +Lemma fib_is_linear : fib =1 lin_fib 0 1. +Proof. +move=>n; elim: n {-2}n (leqnn n)=> [n|n IHn]. + by rewrite leqn0; move/eqP=>->. +case=>//; case=>// n0; rewrite ltnS=> ltn0n; rewrite fibSS lin_fib_alt. +by rewrite (IHn _ ltn0n) (IHn _ (ltnW ltn0n)). +Qed. + +Lemma fib_add : forall m n, + m != 0 -> fib (m + n) = fib m.-1 * fib n + fib m * fib n.+1. +Proof. +move=> m; elim: m {-2}m (leqnn m)=> [[] // _ |m IH]. +move=> m1; rewrite leq_eqVlt; case/orP=> [|Hm]; last first. + by apply: IH; rewrite -ltnS. +move/eqP->; case: m IH=> [|[|m]] IH n _. +- by case: n=> [|n] //; rewrite fibSS mul1n. +- by rewrite add2n fibSS addnC !mul1n. +rewrite 2!addSn fibSS -addSn !IH // addnA [fib _ * _ + _ + _]addnAC. +by rewrite -addnA -!mulnDl -!fibSS. +Qed. + +Theorem dvdn_fib: forall m n, m %| n -> fib m %| fib n. +Proof. +move=> m n; case/dvdnP=> n1 ->. +elim: {n}n1 m=> [|m IH] // [|n]; first by rewrite muln0. +by rewrite mulSn fib_add // dvdn_add //; [apply dvdn_mull | apply dvdn_mulr]. +Qed. + +Lemma fib_gt0 : forall m, 0 < m -> 0 < fib m. +Proof. +by elim=> [|[|m] IH _] //; rewrite fibSS addn_gt0 IH. +Qed. + +Lemma fib_smonotone : forall m n, 1 < m < n -> fib m < fib n. +Proof. +move=> m n; elim: n=> [|[|n] IH]; first by rewrite andbF. + by rewrite ltnNge leq_eqVlt orbC andbC; case: leq. +rewrite fibSS andbC; case/andP; rewrite leq_eqVlt; case/orP. + by rewrite eqSS; move/eqP=> -> H1m; rewrite -addn1 leq_add // fib_gt0. +by move=> H1m H2m; apply: ltn_addr; apply: IH; rewrite // H2m. +Qed. + +Lemma fib_monotone : forall m n, m <= n -> fib m <= fib n. +Proof. +move=> m n; elim: n=> [|[|n] IH]; first by case: m. + by case: m{IH}=> [|[]]. +rewrite fibSS leq_eqVlt; case/orP=>[|Hm]; first by move/eqP->. +by apply: (leq_trans (IH _)) => //; exact: leq_addr. +Qed. + +Lemma fib_eq1 : forall n, (fib n == 1) = ((n == 1) || (n == 2)). +Proof. +case=> [|[|[|n]]] //; case: eqP=> // Hm; have: 1 < 2 < n.+3 by []. +by move/fib_smonotone; rewrite Hm. +Qed. + +Lemma fib_eq : forall m n, + (fib m == fib n) = [|| m == n, (m == 1) && (n == 2) | (m == 2) && (n == 1)]. +Proof. +move=> m n; wlog: m n/ m <= n=> [HH|]. + case/orP: (leq_total m n)=> Hm; first by exact: HH. + by rewrite eq_sym HH // eq_sym ![(_ == 1) && _]andbC [(_ && _) || _] orbC. +rewrite leq_eqVlt; case/orP=>[|]; first by move/eqP->; rewrite !eqxx. +case: m=> [|[|m]] Hm. +- by move: (fib_gt0 _ Hm); rewrite orbF [0 == _]eq_sym !eqn0Ngt Hm; + case: (fib n). +- by rewrite eq_sym fib_eq1 orbF [1==_]eq_sym; case: eqP. +have: 1 < m.+2 < n by []. +move/fib_smonotone; rewrite ltn_neqAle; case/andP; move/negPf=> -> _. +case: n Hm=> [|[|n]] //;rewrite ltn_neqAle; case/andP; move/negPf=> ->. +by rewrite andbF. +Qed. + +Lemma fib_prime : forall p, p != 4 -> prime (fib p) -> prime p. +Proof. +move=> p Dp4 Pp. +apply/primeP; split; first by case: (p) Pp => [|[]]. +move=> d; case/dvdnP=> k Hp. +have F: forall u, (fib u == 1) = ((u == 1) || (u == 2)). + case=> [|[|[|n]]] //; case: eqP=> // Hm; have: 1 < 2 < n.+3 by []. + by move/fib_smonotone; rewrite Hm. +case/primeP: (Pp); rewrite Hp => _ Hf. +case/orP: (Hf _ (dvdn_fib _ _ (dvdn_mulr d (dvdnn k)))). + rewrite fib_eq1; case/orP; first by move/eqP->; rewrite mul1n eqxx orbT. + move/eqP=> Hk. + case/orP: (Hf _ (dvdn_fib _ _ (dvdn_mull k (dvdnn d)))). + rewrite fib_eq1; case/orP; first by move->. + by move/eqP=>Hd; case/negP: Dp4; rewrite Hp Hd Hk. + rewrite fib_eq; case/or3P; first by move/eqP<-; rewrite eqxx orbT. + by case/andP=>->. + by rewrite Hk; case: (d)=> [|[|[|]]]. +rewrite fib_eq; case/or3P; last by case/andP;move/eqP->; case: (d)=> [|[|]]. + rewrite -{1}[k]muln1; rewrite eqn_mul2l; case/orP; move/eqP=> HH. + by move: Pp; rewrite Hp HH. + by rewrite -HH eqxx. +by case/andP; move/eqP->; rewrite mul1n eqxx orbT. +Qed. + +Lemma fib_sub : forall m n, n <= m -> + fib (m - n) = if odd n then fib m.+1 * fib n - fib m * fib n.+1 + else fib m * fib n.+1 - fib m.+1 * fib n. +Proof. +elim=> [|m IH]; first by case=> /=. +case=> [|n Hn]; first by rewrite muln0 muln1 !subn0. +by rewrite -{2}[n.+1]add1n odd_add (addTb (odd n)) subSS IH //; case: odd; + rewrite !fibSS !mulnDr !mulnDl !subnDA !addKn. +Qed. + +Lemma gcdn_fib: forall m n, gcdn (fib m) (fib n) = fib (gcdn m n). +Proof. +move=> m n; apply: gcdn_def. +- by apply: dvdn_fib; exact: dvdn_gcdl. +- by apply: dvdn_fib; exact: dvdn_gcdr. +move=> d' Hdm Hdn. +case: m Hdm=> [|m Hdm]; first by rewrite gcdnE eqxx. +have F: 0 < m.+1 by []. +case: (egcdnP n F)=> km kn Hg Hl. +have->: gcdn m.+1 n = km * m.+1 - kn * n by rewrite Hg addKn. +rewrite fib_sub; last by rewrite Hg leq_addr. +by case: odd; apply: dvdn_sub; + try (by apply: (dvdn_trans Hdn); apply: dvdn_mull; + apply: dvdn_fib; apply: dvdn_mull); + apply: (dvdn_trans Hdm); apply: dvdn_mulr; + apply: dvdn_fib; apply: dvdn_mull. +Qed. + +Lemma coprimeSn_fib: forall n, coprime (fib n.+1) (fib n). +Proof. +by move=> n; move: (coprimeSn n); rewrite /coprime gcdn_fib; move/eqP->. +Qed. + +Fixpoint lucas_rec (n : nat) {struct n} : nat := + if n is n1.+1 then + if n1 is n2.+1 then lucas_rec n1 + lucas_rec n2 + else 1 + else 2. + +Definition lucas := nosimpl lucas_rec. + +Lemma lucasE : lucas = lucas_rec. +Proof. by []. Qed. + +Lemma lucas0 : lucas 0 = 2. +Proof. by []. Qed. + +Lemma lucas1 : lucas 1 = 1. +Proof. by []. Qed. + +Lemma lucasSS : forall n, lucas n.+2 = lucas n.+1 + lucas n. +Proof. by []. Qed. + +Lemma lucas_is_linear : lucas =1 lin_fib 2 1. +Proof. +move=>n; elim: n {-2}n (leqnn n)=> [n|n IHn]. + by rewrite leqn0; move/eqP=>->. +case=>//; case=>// n0; rewrite ltnS=> ltn0n; rewrite lucasSS lin_fib_alt. +by rewrite (IHn _ ltn0n) (IHn _ (ltnW ltn0n)). +Qed. + +Lemma lucas_fib: forall n, n != 0 -> lucas n = fib n.+1 + fib n.-1. +Proof. +move=> n; elim: n {-2}n (leqnn n)=> [[] // _ |n IH]. +move=> n1; rewrite leq_eqVlt; case/orP=> [|Hn1]; last first. + by apply: IH; rewrite -ltnS. +move/eqP->; case: n IH=> [|[|n] IH _] //. +by rewrite lucasSS !IH // addnCA -addnA -fibSS addnC. +Qed. + +Lemma lucas_gt0 : forall m, 0 < lucas m. +Proof. +by elim=> [|[|m] IH] //; rewrite lucasSS addn_gt0 IH. +Qed. + +Lemma double_lucas: forall n, 3 <= n -> (lucas n).*2 = fib (n.+3) + fib (n-3). +Proof. +case=> [|[|[|n]]] // _; rewrite !subSS subn0. +apply/eqP; rewrite -(eqn_add2l (lucas n.+4)) {2}lucasSS addnC -addnn. +rewrite -2![lucas _ + _ + _]addnA eqn_add2l addnC -lucasSS. +rewrite !lucas_fib // [_ + (_ + _)]addnC -[fib _ + _ + _]addnA eqn_add2l. +by rewrite [_ + (_ + _)]addnC -addnA -fibSS. +Qed. + +Lemma fib_double_lucas : forall n, fib (n.*2) = fib n * lucas n. +Proof. +case=> [|n]; rewrite // -addnn fib_add // lucas_fib // mulnDr addnC. +by apply/eqP; rewrite eqn_add2l mulnC. +Qed. + +Lemma fib_doubleS: forall n, fib (n.*2.+1) = fib n.+1 ^ 2 + fib n ^ 2. +Proof. +by move=> n; rewrite -addnn -addSn fib_add // addnC. +Qed. + +Lemma fib_square: forall n, (fib n)^2 = if odd n then (fib n.+1 * fib n.-1).+1 + else (fib n.+1 * fib n.-1).-1. +Proof. +case=> [|n] //; move: (fib_sub (n.+1) n (leqnSn _)). +rewrite subSn // subnn fib1 -{8}[n.+1]add1n odd_add addTb. +case: odd=> H1; last first. + by rewrite -[(_ * _).+1]addn1 {2}H1 addnC subnK // ltnW // -subn_gt0 -H1. +by apply/eqP; rewrite -subn1 {2}H1 subKn // ltnW // -subn_gt0 -H1. +Qed. + +Lemma fib_sum : forall n, \sum_(i < n) fib i = (fib n.+1).-1. +Proof. +elim=> [|n IH]; first by rewrite big_ord0. +by rewrite big_ord_recr /= IH fibSS; case: fib (fib_gt0 _ (ltn0Sn n)). +Qed. + +Lemma fib_sum_even : forall n, \sum_(i < n) fib i.*2 = (fib n.*2.-1).-1. +Proof. +elim=> [|n IH]; first by rewrite big_ord0. +rewrite big_ord_recr IH; case: (n)=> [|n1] //. +rewrite (fibSS (n1.*2.+1)) addnC -[(n1.+1).*2.-1]/n1.*2.+1. +by case: fib (fib_gt0 _ (ltn0Sn ((n1.*2)))). +Qed. + +Lemma fib_sum_odd: forall n, \sum_(i < n) fib i.*2.+1 = fib n.*2. +Proof. +elim=> [|n IH]; first by rewrite big_ord0. +by rewrite big_ord_recr IH /= addnC -fibSS. +Qed. + +Lemma fib_sum_square: forall n, \sum_(i < n) (fib i)^2 = fib n * fib n.-1. +Proof. +elim=> [|n IH]; first by rewrite big_ord0. +rewrite big_ord_recr /= IH. +by rewrite -mulnDr addnC; case: (n)=> // n1; rewrite -fibSS mulnC. +Qed. + +Lemma bin_sum_diag: forall n, \sum_(i < n) 'C(n.-1-i,i) = fib n. +Proof. +move=> n; elim: n {-2}n (leqnn n)=> [[] // _ |n IH]; first by rewrite big_ord0. +move=> n1; rewrite leq_eqVlt; case/orP=> [|Hn]; last first. + by apply: IH; rewrite -ltnS. +move/eqP->; case: n IH=> [|[|n]] IH. +- by rewrite big_ord_recr big_ord0. +- by rewrite !big_ord_recr big_ord0. +rewrite fibSS -!IH // big_ord_recl bin0 big_ord_recr /= subnn bin0n addn0. +set ss := \sum_(i < _) _. +rewrite big_ord_recl bin0 -addnA -big_split; congr (_ + _). +by apply eq_bigr=> i _ /=; rewrite -binS subSn //; case: i. +Qed. + + +(* The matrix *) + +Section Matrix. + +Open Local Scope ring_scope. +Import GRing.Theory. + +Variable R: ringType. + +(* Equivalence ^ n.+1 *) +(* fib n.+2 fib n.+1 1 1 *) +(* = *) +(* fib n.+1 fib n 1 0 *) + +Definition seq2matrix m n (l: seq (seq R)) := + \matrix_(i<m,j<n) nth 1 (nth [::] l i) j. + +Local Notation "''M{' l } " := (seq2matrix _ _ l). + +Lemma matrix_fib : forall n, + 'M{[:: [::(fib n.+2)%:R; (fib n.+1)%:R]; + [::(fib n.+1)%:R; (fib n)%:R]]} = + ('M{[:: [:: 1; 1]; + [:: 1; 0]]})^+n.+1 :> 'M[R]_(2,2). +Proof. +elim=> [|n IH]. + by apply/matrixP=> [[[|[|]] // _] [[|[|]] // _]]; rewrite !mxE. +rewrite exprS -IH; apply/matrixP=> i j. +by rewrite !mxE !big_ord_recl big_ord0 !mxE; + case: i=> [[|[|]]] //= _; case: j=> [[|[|]]] //= _; + rewrite !mul1r ?mul0r !addr0 // fibSS natrD. +Qed. + +End Matrix. diff --git a/mathcomp/attic/forms.v b/mathcomp/attic/forms.v new file mode 100644 index 0000000..1c88af5 --- /dev/null +++ b/mathcomp/attic/forms.v @@ -0,0 +1,193 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype bigop. +Require Import finfun tuple ssralg matrix zmodp vector. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. +Open Local Scope ring_scope. + +Import GRing.Theory. + +Section RingLmodule. + +Variable (R : fieldType). + +Definition r2rv x: 'rV[R^o]_1 := \row_(i < 1) x . + +Lemma r2rv_morph_p : linear r2rv. +Proof. by move=> k x y; apply/matrixP=> [] [[|i] Hi] j;rewrite !mxE. Qed. + +Canonical Structure r2rv_morph := Linear r2rv_morph_p. + +Definition rv2r (A: 'rV[R]_1): R^o := A 0 0. + +Lemma r2rv_bij : bijective r2rv. +Proof. +exists rv2r; first by move => x; rewrite /r2rv /rv2r /= mxE. +by move => x; apply/matrixP=> i j; rewrite [i]ord1 [j]ord1 /r2rv /rv2r !mxE /=. +Qed. + +Canonical Structure RVMixin := Eval hnf in VectMixin r2rv_morph_p r2rv_bij. +Canonical Structure RVVectType := VectType R RVMixin. + +Lemma dimR : vdim RVVectType = 1%nat. +Proof. by rewrite /vdim /=. Qed. + +End RingLmodule. + +(* BiLinear & Sesquilinear & Quadratic Forms over a vectType *) +Section LinearForm. + +Variable (F : fieldType) (V : vectType F). + +Section SesquiLinearFormDef. + +Structure fautomorphism:= FautoMorph {fval :> F -> F; + _ : rmorphism fval; + _ : bijective fval}. +Variable theta: fautomorphism. + +Lemma fval_rmorph : rmorphism theta. +Proof. by case: theta. Qed. + +Canonical Structure fautomorh_additive := Additive fval_rmorph. +Canonical Structure fautomorph_rmorphism := RMorphism fval_rmorph. + +Local Notation vvf:= (V -> V -> F). + +Structure sesquilinear_form := + SesqlinearForm {formv :> vvf; + _ : forall x, {morph formv x : y z / y + z}; + _ : forall x, {morph formv ^~ x : y z / y + z}; + _ : forall a x y, formv (a *: x) y = a * formv x y; + _ : forall a x y , formv x (a *: y) = (theta a) * (formv x y)}. + +Variable f : sesquilinear_form. + +Lemma bilin1 : forall x, {morph f x : y z / y + z}. Proof. by case f. Qed. +Lemma bilin2 : forall x, {morph f ^~ x : y z / y + z}. Proof. by case f. Qed. +Lemma bilina1 : forall a x y, f (a *: x) y = a * f x y. Proof. by case f. Qed. +Lemma bilina2 : forall a x y, f x (a *: y) = (theta a) * (f x y). +Proof. by case f. Qed. + +End SesquiLinearFormDef. + +Section SesquiLinearFormTheory. + +Variable theta: fautomorphism. +Local Notation sqlf := (sesquilinear_form theta). + +Definition symmetric (f : sqlf):= (forall a, (theta a = a)) /\ + forall x y, (f x y = f y x). +Definition skewsymmetric (f : sqlf) := (forall a , theta a = a) /\ + forall x y, f x y = -(f y x). + +Definition hermitian_sym (f : sqlf) := (forall x y, f x y = (theta (f y x))). + +Inductive symmetricf (f : sqlf): Prop := + Symmetric : symmetric f -> symmetricf f +| Skewsymmetric: skewsymmetric f -> symmetricf f +| Hermitian_sym : hermitian_sym f -> symmetricf f . + +Lemma fsym_f0: forall (f: sqlf) x y, (symmetricf f) -> + (f x y = 0 <-> f y x = 0). +Proof. +move => f x y ;case; first by move=> [Htheta Hf];split; rewrite Hf. + by move=> [Htheta Hf];split; rewrite Hf; move/eqP;rewrite oppr_eq0; move/eqP->. +move=> Htheta;split; first by rewrite (Htheta y x) => ->; rewrite rmorph0. +by rewrite (Htheta x y) => ->; rewrite rmorph0. +Qed. + +End SesquiLinearFormTheory. + +Variable theta: fautomorphism. +Variable f: (sesquilinear_form theta). +Hypothesis fsym: symmetricf f. + +Section orthogonal. + +Definition orthogonal x y := f x y = 0. + +Lemma ortho_sym: forall x y, orthogonal x y <-> orthogonal y x. +Proof. by move=> x y; apply:fsym_f0. Qed. + +Theorem Pythagore: forall u v, orthogonal u v -> f (u+v) (u+v) = f u u + f v v. +Proof. +move => u v Huv; case:(ortho_sym u v ) => Hvu _. +by rewrite !bilin1 !bilin2 Huv (Hvu Huv) add0r addr0. +Qed. + +Lemma orthoD : forall u v w , orthogonal u v -> orthogonal u w -> orthogonal u (v + w). +Proof. +by move => u v w Huv Huw; rewrite /orthogonal bilin1 Huv Huw add0r. +Qed. + +Lemma orthoZ: forall u v a, orthogonal u v -> orthogonal (a *: u) v. +Proof. by move => u v a Huv; rewrite /orthogonal bilina1 Huv mulr0. Qed. + +Variable x:V. + +Definition alpha : V-> (RVVectType F) := fun y => f y x. + +Definition alpha_lfun := (lfun_of_fun alpha). + +Definition xbar := lker alpha_lfun . + +Lemma alpha_lin: linear alpha. +Proof. by move => a b c; rewrite /alpha bilin2 bilina1. Qed. + + + +Lemma xbarP: forall e1, reflect (orthogonal e1 x ) (e1 \in xbar). +move=> e1; rewrite memv_ker lfun_of_funK //=. + by apply: (iffP eqP). +by apply alpha_lin. +Qed. + + +Lemma dim_xbar :forall vs,(\dim vs ) - 1 <= \dim (vs :&: xbar). +Proof. +move=> vs; rewrite -(addKn 1 (\dim (vs :&: xbar))) addnC leq_sub2r //. +have H :\dim (alpha_lfun @: vs )<= 1 by rewrite -(dimR F) -dimvf dimvS // subvf. +by rewrite -(limg_ker_dim alpha_lfun vs)(leq_add (leqnn (\dim(vs :&: xbar)))). +Qed. + +(* to be improved*) +Lemma xbar_eqvs: forall vs, (forall v , v \in vs -> orthogonal v x )-> \dim (vs :&: xbar)= (\dim vs ). +move=> vs Hvs. +rewrite -(limg_ker_dim alpha_lfun vs). +suff-> : \dim (alpha_lfun @: vs) = 0%nat by rewrite addn0. +apply/eqP; rewrite dimv_eq0; apply /vspaceP => w. +rewrite memv0;apply/memv_imgP. +case e: (w==0). + exists 0; split ;first by rewrite mem0v. + apply sym_eq; rewrite (eqP e). + rewrite (lfun_of_funK alpha_lin 0). + rewrite /alpha_lfun /alpha /=. + by move:(bilina1 f 0 x x); rewrite scale0r mul0r. +move/eqP:e =>H2;case=> x0 [Hx0 Hw]. +apply H2;rewrite Hw;move: (Hvs x0 Hx0). +rewrite /orthogonal. +by rewrite (lfun_of_funK alpha_lin x0). +Qed. + + +End orthogonal. + +Definition quadraticf (Q: V -> F) := + (forall x a, Q (a *: x) = a ^+ 2 * (Q x))%R * + (forall x y, Q (x + y) = Q x + Q y + f x y)%R : Prop. +Variable Q : V -> F. +Hypothesis quadQ : quadraticf Q. +Import GRing.Theory. + + +Lemma f2Q: forall x, Q x + Q x = f x x. +Proof. +move=> x; apply:(@addrI _ (Q x + Q x)). +rewrite !addrA -quadQ -[x + x](scaler_nat 2) quadQ. +by rewrite -mulrA !mulr_natl -addrA. +Qed. + +End LinearForm. diff --git a/mathcomp/attic/galgebra.v b/mathcomp/attic/galgebra.v new file mode 100644 index 0000000..411fb6a --- /dev/null +++ b/mathcomp/attic/galgebra.v @@ -0,0 +1,227 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq choice fintype finfun. +Require Import bigop finset ssralg fingroup zmodp matrix vector falgebra. + +(*****************************************************************************) +(* * Finite Group as an algebra *) +(* (galg F gT) == the algebra generated by gT on F *) +(*****************************************************************************) + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Reserved Notation "g %:FG" + (at level 2, left associativity, format "g %:FG"). + +Open Local Scope ring_scope. +Import GRing.Theory. + +Section GroupAlgebraDef. +Variables (F : fieldType) (gT : finGroupType). + +Inductive galg : predArgType := GAlg of {ffun gT -> F}. + +Definition galg_val A := let: GAlg f := A in f. + +Canonical galg_subType := Eval hnf in [newType for galg_val]. +Definition galg_eqMixin := Eval hnf in [eqMixin of galg by <:]. +Canonical galg_eqType := Eval hnf in EqType galg galg_eqMixin. +Definition galg_choiceMixin := [choiceMixin of galg by <:]. +Canonical galg_choiceType := Eval hnf in ChoiceType galg galg_choiceMixin. + +Definition fun_of_galg A (i : gT) := galg_val A i. + +Coercion fun_of_galg : galg >-> Funclass. + +Lemma galgE : forall f, GAlg (finfun f) =1 f. +Proof. by move=> f i; rewrite /fun_of_galg ffunE. Qed. + +Definition injG (g : gT) := GAlg ([ffun k => (k == g)%:R]). +Notation Local "g %:FG" := (injG g). + +Implicit Types v: galg. + +Definition g0 := GAlg 0. +Definition g1 := 1%g %:FG. +Definition opprg v := GAlg (-galg_val v). +Definition addrg v1 v2 := GAlg (galg_val v1 + galg_val v2). +Definition mulvg a v := GAlg ([ffun k => a * galg_val v k]). +Definition mulrg v1 v2 := + GAlg ([ffun g => \sum_(k : gT) (v1 k) * (v2 ((k^-1) * g)%g)]). + +Lemma addrgA : associative addrg. +Proof. +by move=> *; apply: val_inj; apply/ffunP=> ?; rewrite !ffunE addrA. +Qed. +Lemma addrgC : commutative addrg. +Proof. +by move=> *; apply: val_inj; apply/ffunP=> ?; rewrite !ffunE addrC. +Qed. +Lemma addr0g : left_id g0 addrg. +Proof. +by move=> *; apply: val_inj; apply/ffunP=> ?; rewrite !ffunE add0r. +Qed. +Lemma addrNg : left_inverse g0 opprg addrg. +Proof. +by move=> *; apply: val_inj; apply/ffunP=> ?; rewrite !ffunE addNr. +Qed. + +(* abelian group structure *) +Definition gAlgZmodMixin := ZmodMixin addrgA addrgC addr0g addrNg. +Canonical Structure gAlgZmodType := + Eval hnf in ZmodType galg gAlgZmodMixin. + +Lemma GAlg_morph : {morph GAlg: x y / x + y}. +Proof. by move=> f1 f2; apply/eqP. Qed. + +Lemma mulvgA : forall a b v, mulvg a (mulvg b v) = mulvg (a * b) v. +Proof. +by move=> *; apply: val_inj; apply/ffunP=> g; rewrite !ffunE mulrA. +Qed. + +Lemma mulvg1 : forall v, mulvg 1 v = v. +Proof. by move=> v; apply: val_inj; apply/ffunP=> g; rewrite ffunE mul1r. Qed. + +Lemma mulvg_addr : forall a u v, mulvg a (u + v) = (mulvg a u) + (mulvg a v). +Proof. +by move=> *; apply: val_inj; apply/ffunP=> g; rewrite !ffunE mulrDr. +Qed. + +Lemma mulvg_addl : forall u a b, mulvg (a + b) u = (mulvg a u) + (mulvg b u). +Proof. +by move=> *; apply: val_inj; apply/ffunP=> g; rewrite !ffunE mulrDl. +Qed. + +Definition gAlgLmodMixin := LmodMixin mulvgA mulvg1 mulvg_addr mulvg_addl. +Canonical gAlgLmodType := Eval hnf in LmodType F galg gAlgLmodMixin. + +Lemma sum_fgE : forall I r (P : pred I) (E : I -> galg) i, + (\sum_(k <- r | P k) E k) i = \sum_(k <- r | P k) E k i. +Proof. +move=> I r P E i. +by apply: (big_morph (fun A : galg => A i)) => [A B|]; rewrite galgE. +Qed. + +Lemma mulrgA : associative mulrg. +Proof. +move=> x y z; apply: val_inj; apply/ffunP=> g; rewrite !ffunE; symmetry. +rewrite (eq_bigr (fun k => \sum_i x i * (y (i^-1 * k)%g * z (k^-1 * g)%g))) + => [| *]; last by rewrite galgE big_distrl; apply: eq_bigr => *; rewrite mulrA. +rewrite exchange_big /=. +transitivity (\sum_j x j * \sum_i y (j^-1 * i)%g * z (i^-1 * g)%g). + by apply: eq_bigr => i _; rewrite big_distrr /=. +apply: eq_bigr => i _; rewrite galgE (reindex (fun j => (i * j)%g)); last first. + by exists [eta mulg i^-1] => /= j _; rewrite mulgA 1?mulgV 1?mulVg mul1g. +by congr (_ * _); apply: eq_bigr => *; rewrite mulgA mulVg mul1g invMg mulgA. +Qed. + +Lemma mulr1g : left_id g1 mulrg. +Proof. +move=> x; apply: val_inj; apply/ffunP=> g. +rewrite ffunE (bigD1 1%g) //= galgE eqxx invg1. +by rewrite mul1g mul1r big1 1?addr0 // => i Hi; rewrite galgE (negbTE Hi) mul0r. +Qed. + +Lemma mulrg1 : right_id g1 mulrg. +Proof. +move=> x; apply: val_inj; apply/ffunP=> g. +rewrite ffunE (bigD1 g) //= galgE mulVg eqxx mulr1. +by rewrite big1 1?addr0 // => i Hi; rewrite galgE -eq_mulVg1 (negbTE Hi) mulr0. +Qed. + +Lemma mulrg_addl : left_distributive mulrg addrg. +Proof. +move=> x y z; apply: val_inj; apply/ffunP=> g; rewrite !ffunE -big_split /=. +by apply: eq_bigr => i _; rewrite galgE mulrDl. +Qed. + +Lemma mulrg_addr : right_distributive mulrg addrg. +Proof. +move=> x y z; apply: val_inj; apply/ffunP=> g; rewrite !ffunE -big_split /=. +by apply: eq_bigr => i _; rewrite galgE mulrDr. +Qed. + +Lemma nong0g1 : g1 != 0 :> galg. +Proof. +apply/eqP; case. +move/ffunP; move/(_ 1%g); rewrite !ffunE eqxx. +by move/eqP; rewrite oner_eq0. +Qed. + +Definition gAlgRingMixin := + RingMixin mulrgA mulr1g mulrg1 mulrg_addl mulrg_addr nong0g1. +Canonical gAlgRingType := Eval hnf in RingType galg gAlgRingMixin. + +Implicit Types x y : galg. + +Lemma mulg_mulvl : forall a x y, a *: (x * y) = (a *: x) * y. +Proof. +move=> a x y; apply: val_inj; apply/ffunP=> g. +rewrite !ffunE big_distrr /=. +by apply: eq_bigr => i _; rewrite mulrA galgE. +Qed. + +Lemma mulg_mulvr : forall a x y, a *: (x * y) = x * (a *: y). +Proof. +move=> a x y; apply: val_inj; apply/ffunP=> g. +rewrite !ffunE big_distrr /=. +by apply: eq_bigr => i _; rewrite galgE mulrCA. +Qed. + +Canonical gAlgLalgType := Eval hnf in LalgType F galg mulg_mulvl. +Canonical gAlgAlgType := Eval hnf in AlgType F galg mulg_mulvr. + +Lemma injGM : forall g h, (g * h)%g %:FG = (g %:FG) * (h %:FG). +Proof. +move=> g h; apply: val_inj; apply/ffunP=> k. +rewrite !ffunE (bigD1 g) //= !galgE eqxx mul1r. +rewrite big1 1?addr0 => [| i Hi]; last by rewrite !galgE (negbTE Hi) mul0r. +by rewrite -(inj_eq (mulgI (g^-1)%g)) mulgA mulVg mul1g. +Qed. + +Fact gAlg_iso_vect : Vector.axiom #|gT| galg. +Proof. +exists (fun x => \row_(i < #|gT|) x (enum_val i)) => [k x y | ]. + by apply/rowP=> i; rewrite !mxE !galgE !ffunE. +exists (fun x : 'rV[F]_#|gT| => GAlg ([ffun k => (x 0 (enum_rank k))])) => x. + by apply: val_inj; apply/ffunP=> i; rewrite ffunE mxE enum_rankK. +by apply/rowP=> i; rewrite // !mxE galgE enum_valK. +Qed. + +Definition galg_vectMixin := VectMixin gAlg_iso_vect. +Canonical galg_vectType := VectType F galg galg_vectMixin. + +Canonical galg_unitRingType := FalgUnitRingType galg. +Canonical galg_unitAlgFType := [unitAlgType F of galg]. +Canonical gAlgAlgFType := [FalgType F of galg]. + + +Variable G : {group gT}. + +Definition gvspace: {vspace galg} := (\sum_(g in G) <[g%:FG]>)%VS. + +Fact gspace_subproof : has_algid gvspace && (gvspace * gvspace <= gvspace)%VS. +Proof. +apply/andP; split. + apply: has_algid1. + rewrite /gvspace (bigD1 (1)%g) //=. + apply: subv_trans (addvSl _ _). + by apply/vlineP; exists 1; rewrite scale1r. +apply/prodvP=> u v Hu Hv. +case/memv_sumP: Hu => u_ Hu ->; rewrite big_distrl /=. +apply: memv_suml=> i Hi. +case/memv_sumP: Hv => v_ Hv ->; rewrite big_distrr /=. +apply: memv_suml=> j Hj. +rewrite /gvspace (bigD1 (i*j)%g) /=; last by exact: groupM. +apply: subv_trans (addvSl _ _). +case/vlineP: (Hu _ Hi)=> k ->; case/vlineP: (Hv _ Hj)=> l ->. +apply/vlineP; exists (k * l). +by rewrite -scalerAl -scalerAr scalerA injGM. +Qed. + +Definition gaspace : {aspace galg} := ASpace gspace_subproof. + +End GroupAlgebraDef. + +Notation " g %:FG " := (injG _ g). diff --git a/mathcomp/attic/multinom.v b/mathcomp/attic/multinom.v new file mode 100644 index 0000000..b203381 --- /dev/null +++ b/mathcomp/attic/multinom.v @@ -0,0 +1,438 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype. +Require Import tuple finfun bigop ssralg poly generic_quotient bigenough. + +(* We build the ring of multinomials with an arbitrary (countable) *) +(* number of indeterminates. We show it is a ring when the base field *) +(* is a ring, and a commutative ring when the base field is commutative *) + +(* TODO: + - when the base field is an integral domain, so are multinomials (WIP) + - replace the countable type of indeterminates by an arbitrary choice type + - do the theory of symmetric polynomials +*) + + + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Local Open Scope ring_scope. +Local Open Scope quotient_scope. + +Import GRing.Theory BigEnough. + +Module Multinomial. + +Section Multinomial. + +Variable X : countType. + +Section MultinomialRing. + +Variable R : ringType. + +(* Definining the free algebra of multinomial terms *) +Inductive multi_term := +| Coef of R +| Var of X +| Oper of bool & multi_term & multi_term. + +Notation Sum := (Oper false). +Notation Prod := (Oper true). + +(* Encoding to a tree structure in order to recover equality and choice *) +Fixpoint to_tree m : GenTree.tree (X + R) := +match m with +| Coef x => GenTree.Node 0 [:: GenTree.Leaf (inr _ x)] +| Var x => GenTree.Node 0 [:: GenTree.Leaf (inl _ x)] +| Oper b m1 m2 => GenTree.Node (b.+1) [:: to_tree m1; to_tree m2] +end. + +Fixpoint from_tree t := +match t with +| GenTree.Node 0 [:: GenTree.Leaf (inr x)] => Some (Coef x) +| GenTree.Node 0 [:: GenTree.Leaf (inl x)] => Some (Var x) +| GenTree.Node n.+1 [:: t1; t2] => + if (from_tree t1, from_tree t2) is (Some m1, Some m2) + then Some (Oper (n == 1)%N m1 m2) else None +| _ => None +end. + +Lemma to_treeK : pcancel to_tree from_tree. +Proof. by elim=> //=; case=> ? -> ? ->. Qed. + +Definition multi_term_eqMixin := PcanEqMixin to_treeK. +Canonical multi_term_eqType := EqType multi_term multi_term_eqMixin. +Definition multi_term_choiceMixin := PcanChoiceMixin to_treeK. +Canonical multi_term_choiceType := ChoiceType multi_term multi_term_choiceMixin. + +(* counting the variables, in order to know how to interpret multi_term *) +Fixpoint nbvar_term t := + match t with + | Coef _ => 0%N + | Var x => (pickle x).+1 + | Sum u v => maxn (nbvar_term u) (nbvar_term v) + | Prod u v => maxn (nbvar_term u) (nbvar_term v) + end. + +(* Iterated polynomials over a ring *) +Fixpoint multi n := if n is n.+1 then [ringType of {poly multi n}] else R. + +Fixpoint inject n m (p : multi n) {struct m} : multi (m + n) := + if m is m'.+1 return multi (m + n) then (inject m' p)%:P else p. + +Lemma inject_inj : forall i m, injective (@inject i m). +Proof. by move=> i; elim=> //= m IHm p q; move/polyC_inj; move/IHm. Qed. + +Lemma inject0 : forall i m, @inject i m 0 = 0. +Proof. by move=> i; elim=> //= m ->. Qed. + +Lemma inject_eq0 : forall i m p, (@inject i m p == 0) = (p == 0). +Proof. by move=> i m p; rewrite -(inj_eq (@inject_inj i m)) inject0. Qed. + +Lemma size_inject : forall i m p, size (@inject i m.+1 p) = (p != 0 : nat). +Proof. by move=> i m p; rewrite size_polyC inject_eq0. Qed. + +Definition cast_multi i m n Emn : multi i -> multi n := + let: erefl in _ = n' := Emn return _ -> multi n' in inject m. + +Definition multi_var n (i : 'I_n) := cast_multi (subnK (valP i)) 'X. + +Notation "'X_ i" := (multi_var i). + +Lemma inject_is_rmorphism : forall m n, rmorphism (@inject n m). +Proof. +elim=> // m ihm n /=; have ->: inject m = RMorphism (ihm n) by []. +by rewrite -/(_ \o _); apply: rmorphismP. +Qed. +Canonical inject_rmorphism m n := RMorphism (inject_is_rmorphism m n). +Canonical inject_additive m n := Additive (inject_is_rmorphism m n). + +Lemma cast_multi_is_rmorphism i m n Enm : rmorphism (@cast_multi i m n Enm). +Proof. by case: n / Enm; apply: rmorphismP. Qed. +Canonical cast_multi_rmorphism i m n e := + RMorphism (@cast_multi_is_rmorphism i m n e). +Canonical cast_multi_additive i m n e := + Additive (@cast_multi_is_rmorphism i m n e). + +Definition multiC n : R -> multi n := cast_multi (addn0 n). +Lemma multiC_is_rmorphism n : rmorphism (multiC n). +Proof. by rewrite /multiC -[R]/(multi 0); apply: rmorphismP. Qed. +Canonical multiC_rmorphism n := RMorphism (multiC_is_rmorphism n). +Canonical multiC_additive n := Additive (multiC_is_rmorphism n). + +Lemma cast_multi_inj n i i' n' (m1 m2 : multi n) + (p1: (i + n)%N=n') (p2: (i' + n)%N=n') : + cast_multi p1 m1 == cast_multi p2 m2 = (m1 == m2). +Proof. +have := p2; rewrite -{1}[n']p1; move/eqP; rewrite eqn_add2r. +move=> /eqP /= Eii; move:p2; rewrite Eii=> p2 {Eii}. +have <-: p1 = p2; first exact: nat_irrelevance. +apply/idP/idP; last by move/eqP->. +move => Hm {p2}. +have : inject i m1 = inject i m2; last first. + by move/eqP; rewrite (inj_eq (@inject_inj _ _)). +move: Hm; move:(p1); rewrite -p1 => p2. +rewrite (_ : p2 = erefl (i+n)%N); last exact: nat_irrelevance. +by move/eqP. +Qed. + +Lemma Emj_Enk i j k m n : + forall (Emj : (m + i)%N = j) (Enk : (n + j)%N = k), (n + m + i)%N = k. +Proof. by move<-; rewrite addnA. Qed. + +Lemma cast_multi_id n (e : (0 + n)%N = n) m : cast_multi e m = m. +Proof. by rewrite (_ : e = erefl _) //; apply: nat_irrelevance. Qed. + +Lemma cast_multiS n i n' (m : multi n) + (p: (i + n)%N = n') (pS: ((i.+1) + n)%N = n'.+1) : + (cast_multi pS m) = (cast_multi p m)%:P. +Proof. by case: _ / p in pS *; rewrite [pS](nat_irrelevance _ (erefl _)). Qed. + +Lemma injectnm_cast_multi i m n p : + inject (n + m)%N p = + ((@cast_multi (m + i)%N n ((n + m) + i)%N (addnA _ _ _)) \o (inject m)) p. +Proof. +elim: n => [|n /= -> /=]. + by rewrite [addnA 0%N m i](nat_irrelevance _ (erefl _)). +by rewrite cast_multiS; congr (cast_multi _ _)%:P; apply: nat_irrelevance. +Qed. + +Lemma cast_multi_add i j k m n Emj Enk p : + @cast_multi j n k Enk (@cast_multi i m j Emj p) = + @cast_multi i (n + m)%N k (Emj_Enk Emj Enk) p. +Proof. +move: (Emj) (Enk) (Emj_Enk Emj Enk); rewrite -Enk -Emj. +change (addn_rec n (addn_rec m i)) with (n+m+i)%N. +rewrite {-1}[(n+(m+i))%N]addnA=> Emj0 Enk0 Enmi. +have ->: (Emj0 = erefl (m+i)%N); first exact: nat_irrelevance. +have ->: (Enmi = erefl (n+m+i)%N); first exact: nat_irrelevance. +rewrite /= injectnm_cast_multi /=. +by apply/eqP; rewrite cast_multi_inj. +Qed. + +(* Interpretation of a multi_term in iterated polynomials, + for a given number of variables n *) +Fixpoint interp n m : multi n := + match m with + | Coef x => multiC n x + | Var x => let i := pickle x in + (if i < n as b return (i < n) = b -> multi n + then fun iltn => cast_multi (subnK iltn) 'X_(Ordinal (leqnn i.+1)) + else fun _ => 0) (refl_equal (i < n)) + | Sum p q => interp n p + interp n q + | Prod p q => interp n p * interp n q +end. + +Lemma interp_cast_multi n n' m (nltn' : n <= n') : + nbvar_term m <= n -> interp n' m = cast_multi (subnK nltn') (interp n m). +Proof. +move=> dmltn; have dmltn' := (leq_trans dmltn nltn'). +elim: m nltn' dmltn dmltn'. ++ move=> a /= nltn' dmltn dmltn'. + apply/eqP; rewrite /multiC. + by rewrite cast_multi_add /= cast_multi_inj. ++ move=> N /= nltn' dmltn dmltn'. + move: (refl_equal (_ N < n')) (refl_equal (_ N < n)). + rewrite {2 3}[_ N < n]dmltn {2 3}[_ N < n']dmltn' => Nn' Nn. + by apply/eqP; rewrite cast_multi_add cast_multi_inj. +move=> [] m1 Hm1 m2 Hm2 nltn' /=; +rewrite !geq_max => /andP [dm1n dm1n'] /andP [dm2n dm2n']; +by rewrite (Hm1 nltn') // (Hm2 nltn') // (rmorphM, rmorphD). +Qed. + +(* identification of to multi_terms modulo equality of iterated polynomials *) +Definition equivm m1 m2 := let n := maxn (nbvar_term m1) (nbvar_term m2) in + interp n m1 == interp n m2. + +(* it works even for a bigger n *) +Lemma interp_gtn n m1 m2 : maxn (nbvar_term m1) (nbvar_term m2) <= n -> + equivm m1 m2 = (interp n m1 == interp n m2). +Proof. +move=> hn; rewrite !(interp_cast_multi hn) ?leq_max ?leqnn ?orbT //. +by rewrite cast_multi_inj. +Qed. + +Lemma equivm_refl : reflexive equivm. Proof. by move=> x; rewrite /equivm. Qed. + +Lemma equivm_sym : symmetric equivm. +Proof. by move=> x y; rewrite /equivm eq_sym maxnC. Qed. + +Lemma equivm_trans : transitive equivm. +Proof. +move=> x y z; pose_big_enough n. + by rewrite !(@interp_gtn n) => // /eqP-> /eqP->. +by close. +Qed. + +(* equivm is an equivalence *) +Canonical equivm_equivRel := EquivRel equivm + equivm_refl equivm_sym equivm_trans. + +(* we quotient by the equivalence *) +Definition multinom := {eq_quot equivm}. +Definition multinom_of of phant X & phant R := multinom. + +Local Notation "{ 'multinom' R }" := (multinom_of (Phant X) (Phant R)) + (at level 0, format "{ 'multinom' R }"). +(* We recover a lot of structure *) +Canonical multinom_quotType := [quotType of multinom]. +Canonical multinom_eqType := [eqType of multinom]. +Canonical multinom_eqQuotType := [eqQuotType equivm of multinom]. +Canonical multinom_choiceType := [choiceType of multinom]. +Canonical multinom_of_quotType := [quotType of {multinom R}]. +Canonical multinom_of_eqType := [eqType of {multinom R}]. +Canonical multinom_of_eqQuotType := [eqQuotType equivm of {multinom R}]. +Canonical multinom_of_choiceType := [choiceType of {multinom R}]. + +Lemma eqm_interp n m1 m2 : maxn (nbvar_term m1) (nbvar_term m2) <= n -> + (interp n m1 == interp n m2) = (m1 == m2 %[mod {multinom R}]). +Proof. by move=> hn; rewrite eqmodE /= -interp_gtn. Qed. + +Definition cstm := lift_embed {multinom R} Coef. +Notation "c %:M" := (cstm c) (at level 2, format "c %:M"). +Canonical pi_cstm_morph := PiEmbed cstm. + +Definition varm := lift_embed {multinom R} Var. +Notation "n %:X" := (varm n) (at level 2, format "n %:X"). +Canonical pi_varm_morph := PiEmbed varm. + +(* addition is defined by lifting Sum *) +Definition addm := lift_op2 {multinom R} Sum. +Lemma pi_addm : {morph \pi : x y / Sum x y >-> addm x y}. +Proof. +move=> x y /=; unlock addm; apply/eqmodP => /=. +pose_big_enough n. + rewrite (@interp_gtn n) //=; apply/eqP; congr (_ + _); + by apply/eqP; rewrite eqm_interp // reprK. +by close. +Qed. +Canonical pi_addm_morph := PiMorph2 pi_addm. + +Definition Opp := Prod (Coef (-1)). +Definition oppm := lift_op1 {multinom R} Opp. +Lemma pi_oppm : {morph \pi : x / Opp x >-> oppm x}. +Proof. +move=> x; unlock oppm; apply/eqmodP => /=. +rewrite /equivm /= !max0n; apply/eqP; congr (_ * _). +by apply/eqP; rewrite eqm_interp ?reprK. +Qed. +Canonical pi_oppm_morph := PiMorph1 pi_oppm. + +(* addition is defined by lifting Prod *) +Definition mulm := lift_op2 {multinom R} Prod. +Lemma pi_mulm : {morph \pi : x y / Prod x y >-> mulm x y}. +Proof. +move=> x y; unlock mulm; apply/eqP; set x' := repr _; set y' := repr _. +rewrite -(@eqm_interp (nbvar_term (Sum (Sum x y) (Sum x' y')))) /=. + apply/eqP; congr (_ * _); apply/eqP; + by rewrite eqm_interp ?reprK // !(geq_max, leq_max, leqnn, orbT). +by rewrite maxnC. +Qed. +Canonical pi_mulm_morph := PiMorph2 pi_mulm. + +(* Ring properties are obtained from iterated polynomials *) +Lemma addmA : associative addm. +Proof. +elim/quotW=> x; elim/quotW=> y; elim/quotW=> z; apply/eqP. +by rewrite !piE /equivm /= addrA. +Qed. + +Lemma addmC : commutative addm. +Proof. +by elim/quotW=> x; elim/quotW=> y; apply/eqP; rewrite !piE /equivm /= addrC. +Qed. + +Lemma add0m : left_id 0%:M addm. +Proof. by elim/quotW=> x; apply/eqP; rewrite piE /equivm /= rmorph0 add0r. Qed. + +Lemma addmN : left_inverse 0%:M oppm addm. +Proof. +elim/quotW=> x; apply/eqP; rewrite piE /equivm /=. +by rewrite !rmorph0 rmorphN rmorph1 mulN1r addNr. +Qed. + +Definition multinom_zmodMixin := ZmodMixin addmA addmC add0m addmN. +Canonical multinom_zmodType := ZmodType multinom multinom_zmodMixin. +Canonical multinom_of_zmodType := ZmodType {multinom R} multinom_zmodMixin. + +Lemma mulmA : associative mulm. +Proof. +elim/quotW=> x; elim/quotW=> y; elim/quotW=> z; apply/eqP. +by rewrite piE /equivm /= mulrA. +Qed. + +Lemma mul1m : left_id 1%:M mulm. +Proof. by elim/quotW=> x; apply/eqP; rewrite piE /equivm /= rmorph1 mul1r. Qed. + +Lemma mulm1 : right_id 1%:M mulm. +Proof. +elim/quotW=> x; rewrite !piE /=; apply/eqmodP; rewrite /= /equivm /=. +by rewrite rmorph1 mulr1. +Qed. + +Lemma mulm_addl : left_distributive mulm addm. +Proof. +elim/quotW=> x; elim/quotW=> y; elim/quotW=> z; apply/eqP. +by rewrite !piE /equivm /= mulrDl. +Qed. + +Lemma mulm_addr : right_distributive mulm addm. +Proof. +elim/quotW=> x; elim/quotW=> y; elim/quotW=> z; apply/eqP. +by rewrite !piE /equivm /= mulrDr. +Qed. + +Lemma nonzero1m : 1%:M != 0%:M. +Proof. by rewrite piE /equivm /= rmorph1 rmorph0 oner_neq0. Qed. + +Definition multinom_ringMixin := RingMixin mulmA mul1m mulm1 mulm_addl mulm_addr nonzero1m. +Canonical multinom_ringType := RingType multinom multinom_ringMixin. +Canonical multinom_of_ringType := RingType {multinom R} multinom_ringMixin. + +End MultinomialRing. + +Notation "{ 'multinom' R }" := (@multinom_of _ (Phant X) (Phant R)) + (at level 0, format "{ 'multinom' R }"). + +Notation "c %:M" := (cstm c) (at level 2, format "c %:M"). +Notation "n %:X" := (varm n) (at level 2, format "n %:X"). + +Section MultinomialComRing. + +Variable R : comRingType. + +Lemma mul_multiC n : commutative (@GRing.mul (multi R n)). +Proof. +suff [M IH_CR] : {CR : comRingType | [ringType of CR] = multi R n}. + by case: _ / IH_CR => x y; rewrite mulrC. +elim: n => [|n [CR IH_CR]] //=; first by exists R. +by exists [comRingType of {poly CR}]; rewrite -IH_CR. +Qed. + +Lemma mulmC : commutative (@mulm R). +Proof. +elim/quotW=> x; elim/quotW=> y; apply/eqP. +by rewrite piE /equivm /= mul_multiC. +Qed. + +(* if R is commutative, so is {multinom R} *) +Canonical multinom_comRing := Eval hnf in ComRingType (@multinom R) mulmC. +Canonical multinom_of_comRing := Eval hnf in ComRingType {multinom R} mulmC. + +End MultinomialComRing. + +Section MultinomialIdomain. + +Variable R : idomainType. + +(* if R is an integral domain, {multinom R} should also be one, + but the developpment is unfinished *) +Lemma multi_unitClass n : GRing.UnitRing.class_of (multi R n). +Proof. +suff [D IH_D] : {D : idomainType | [ringType of D] = multi R n}. + by case: _ / IH_D; case: D => [sort [[[rc /= _ um _ _]]]]; exists rc. +elim: n => [|n [D IH_D]] //=; first by exists R. +by exists [idomainType of {poly D}]; case: _ / IH_D. +Qed. + +Canonical multi_unitRing n := GRing.UnitRing.Pack + (multi_unitClass n) (multi R n). + +(* Definition Unit (m : multi_term R) := *) +(* let n := nbvar_term m in interp n m \in GRing.unit. *) +(* Definition unitm := lift_fun1 {multinom R} Unit. *) +(* Lemma pi_unitm : {mono \pi : x / Unit x >-> unitm x}. *) +(* Proof. *) +(* move=> x; unlock unitm; rewrite /Unit /=. *) +(* Admitted. *) +(* Canonical pi_unitm_morph := PiMono1 pi_unitm. *) + +Lemma multi_idomain n : GRing.IntegralDomain.axiom (multi R n). +Proof. +suff [D IH_D] : {D : idomainType | [ringType of D] = multi R n}. + by case: _ / IH_D => x y /eqP; rewrite mulf_eq0. +elim: n => [|n [D IH_D]] //=; first by exists R. +by exists [idomainType of {poly D}]; rewrite -IH_D. +Qed. + +Lemma multinom_idomain : GRing.IntegralDomain.axiom [ringType of multinom R]. +Proof. +elim/quotW=> x; elim/quotW=> y /eqP; rewrite -[_ * _]pi_mulm !piE. +pose_big_enough n. + by rewrite !(@interp_gtn _ n) //= !rmorph0 => /eqP /multi_idomain. +by close. +Qed. + +(* Work in progress *) + +End MultinomialIdomain. + +End Multinomial. +End Multinomial. + + + + diff --git a/mathcomp/attic/mxtens.v b/mathcomp/attic/mxtens.v new file mode 100644 index 0000000..c52039f --- /dev/null +++ b/mathcomp/attic/mxtens.v @@ -0,0 +1,312 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq choice fintype. +Require Import bigop ssralg matrix zmodp div. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Import GRing.Theory. +Local Open Scope nat_scope. +Local Open Scope ring_scope. + +Section ExtraBigOp. + +Lemma sumr_add : forall (R : ringType) m n (F : 'I_(m + n) -> R), + \sum_(i < m + n) F i = \sum_(i < m) F (lshift _ i) + + \sum_(i < n) F (rshift _ i). +Proof. +move=> R; elim=> [|m ihm] n F. + rewrite !big_ord0 add0r; apply: congr_big=> // [[i hi]] _. + by rewrite /rshift /=; congr F; apply: val_inj. +rewrite !big_ord_recl ihm -addrA. +congr (_ + _); first by congr F; apply: val_inj. +congr (_ + _); by apply: congr_big=> // i _ /=; congr F; apply: val_inj. +Qed. + +Lemma mxtens_index_proof m n (ij : 'I_m * 'I_n) : ij.1 * n + ij.2 < m * n. +Proof. +case: m ij=> [[[] //]|] m ij; rewrite mulSn addnC -addSn leq_add //. +by rewrite leq_mul2r; case: n ij=> // n ij; rewrite leq_ord orbT. +Qed. + +Definition mxtens_index m n ij := Ordinal (@mxtens_index_proof m n ij). + +Lemma mxtens_index_proof1 m n (k : 'I_(m * n)) : k %/ n < m. +Proof. by move: m n k=> [_ [] //|m] [|n] k; rewrite ?divn0 // ltn_divLR. Qed. +Lemma mxtens_index_proof2 m n (k : 'I_(m * n)) : k %% n < n. +Proof. by rewrite ltn_mod; case: n k=> //; rewrite muln0=> [] []. Qed. + +Definition mxtens_unindex m n k := + (Ordinal (@mxtens_index_proof1 m n k), Ordinal (@mxtens_index_proof2 m n k)). + +Implicit Arguments mxtens_index [[m] [n]]. +Implicit Arguments mxtens_unindex [[m] [n]]. + +Lemma mxtens_indexK m n : cancel (@mxtens_index m n) (@mxtens_unindex m n). +Proof. +case: m=> [[[] //]|m]; case: n=> [[_ [] //]|n]. +move=> [i j]; congr (_, _); apply: val_inj=> /=. + by rewrite divnMDl // divn_small. +by rewrite modnMDl // modn_small. +Qed. + +Lemma mxtens_unindexK m n : cancel (@mxtens_unindex m n) (@mxtens_index m n). +Proof. +case: m=> [[[] //]|m]. case: n=> [|n] k. + by suff: False by []; move: k; rewrite muln0=> [] []. +by apply: val_inj=> /=; rewrite -divn_eq. +Qed. + +CoInductive is_mxtens_index (m n : nat) : 'I_(m * n) -> Type := + IsMxtensIndex : forall (i : 'I_m) (j : 'I_n), + is_mxtens_index (mxtens_index (i, j)). + +Lemma mxtens_indexP (m n : nat) (k : 'I_(m * n)) : is_mxtens_index k. +Proof. by rewrite -[k]mxtens_unindexK; constructor. Qed. + +Lemma mulr_sum (R : ringType) m n (Fm : 'I_m -> R) (Fn : 'I_n -> R) : + (\sum_(i < m) Fm i) * (\sum_(i < n) Fn i) + = \sum_(i < m * n) ((Fm (mxtens_unindex i).1) * (Fn (mxtens_unindex i).2)). +Proof. +rewrite mulr_suml; transitivity (\sum_i (\sum_(j < n) Fm i * Fn j)). + by apply: eq_big=> //= i _; rewrite -mulr_sumr. +rewrite pair_big; apply: reindex=> //=. +by exists mxtens_index=> i; rewrite (mxtens_indexK, mxtens_unindexK). +Qed. + +End ExtraBigOp. + +Section ExtraMx. + +Lemma castmx_mul (R : ringType) + (m m' n p p': nat) (em : m = m') (ep : p = p') + (M : 'M[R]_(m, n)) (N : 'M[R]_(n, p)) : + castmx (em, ep) (M *m N) = castmx (em, erefl _) M *m castmx (erefl _, ep) N. +Proof. by case: m' / em; case: p' / ep. Qed. + +Lemma mulmx_cast (R : ringType) + (m n n' p p' : nat) (en : n' = n) (ep : p' = p) + (M : 'M[R]_(m, n)) (N : 'M[R]_(n', p')) : + M *m (castmx (en, ep) N) = + (castmx (erefl _, (esym en)) M) *m (castmx (erefl _, ep) N). +Proof. by case: n / en in M *; case: p / ep in N *. Qed. + +Lemma castmx_row (R : Type) (m m' n1 n2 n1' n2' : nat) + (eq_n1 : n1 = n1') (eq_n2 : n2 = n2') (eq_n12 : (n1 + n2 = n1' + n2')%N) + (eq_m : m = m') (A1 : 'M[R]_(m, n1)) (A2 : 'M_(m, n2)) : + castmx (eq_m, eq_n12) (row_mx A1 A2) = + row_mx (castmx (eq_m, eq_n1) A1) (castmx (eq_m, eq_n2) A2). +Proof. +case: _ / eq_n1 in eq_n12 *; case: _ / eq_n2 in eq_n12 *. +by case: _ / eq_m; rewrite castmx_id. +Qed. + +Lemma castmx_col (R : Type) (m m' n1 n2 n1' n2' : nat) + (eq_n1 : n1 = n1') (eq_n2 : n2 = n2') (eq_n12 : (n1 + n2 = n1' + n2')%N) + (eq_m : m = m') (A1 : 'M[R]_(n1, m)) (A2 : 'M_(n2, m)) : + castmx (eq_n12, eq_m) (col_mx A1 A2) = + col_mx (castmx (eq_n1, eq_m) A1) (castmx (eq_n2, eq_m) A2). +Proof. +case: _ / eq_n1 in eq_n12 *; case: _ / eq_n2 in eq_n12 *. +by case: _ / eq_m; rewrite castmx_id. +Qed. + +Lemma castmx_block (R : Type) (m1 m1' m2 m2' n1 n2 n1' n2' : nat) + (eq_m1 : m1 = m1') (eq_n1 : n1 = n1') (eq_m2 : m2 = m2') (eq_n2 : n2 = n2') + (eq_m12 : (m1 + m2 = m1' + m2')%N) (eq_n12 : (n1 + n2 = n1' + n2')%N) + (ul : 'M[R]_(m1, n1)) (ur : 'M[R]_(m1, n2)) + (dl : 'M[R]_(m2, n1)) (dr : 'M[R]_(m2, n2)) : + castmx (eq_m12, eq_n12) (block_mx ul ur dl dr) = + block_mx (castmx (eq_m1, eq_n1) ul) (castmx (eq_m1, eq_n2) ur) + (castmx (eq_m2, eq_n1) dl) (castmx (eq_m2, eq_n2) dr). +Proof. +case: _ / eq_m1 in eq_m12 *; case: _ / eq_m2 in eq_m12 *. +case: _ / eq_n1 in eq_n12 *; case: _ / eq_n2 in eq_n12 *. +by rewrite !castmx_id. +Qed. + +End ExtraMx. + +Section MxTens. + +Variable R : ringType. + +Definition tensmx {m n p q : nat} + (A : 'M_(m, n)) (B : 'M_(p, q)) : 'M[R]_(_,_) := nosimpl + (\matrix_(i, j) (A (mxtens_unindex i).1 (mxtens_unindex j).1 + * B (mxtens_unindex i).2 (mxtens_unindex j).2)). + +Notation "A *t B" := (tensmx A B) + (at level 40, left associativity, format "A *t B"). + +Lemma tensmxE {m n p q} (A : 'M_(m, n)) (B : 'M_(p, q)) i j k l : + (A *t B) (mxtens_index (i, j)) (mxtens_index (k, l)) = A i k * B j l. +Proof. by rewrite !mxE !mxtens_indexK. Qed. + +Lemma tens0mx {m n p q} (M : 'M[R]_(p,q)) : (0 : 'M_(m,n)) *t M = 0. +Proof. by apply/matrixP=> i j; rewrite !mxE mul0r. Qed. + +Lemma tensmx0 {m n p q} (M : 'M[R]_(m,n)) : M *t (0 : 'M_(p,q)) = 0. +Proof. by apply/matrixP=> i j; rewrite !mxE mulr0. Qed. + +Lemma tens_scalar_mx (m n : nat) (c : R) (M : 'M_(m,n)): + c%:M *t M = castmx (esym (mul1n _), esym (mul1n _)) (c *: M). +Proof. +apply/matrixP=> i j. +case: (mxtens_indexP i)=> i0 i1; case: (mxtens_indexP j)=> j0 j1. +rewrite tensmxE [i0]ord1 [j0]ord1 !castmxE !mxE /= mulr1n. +by congr (_ * M _ _); apply: val_inj. +Qed. + +Lemma tens_scalar1mx (m n : nat) (M : 'M_(m,n)) : + 1 *t M = castmx (esym (mul1n _), esym (mul1n _)) M. +Proof. by rewrite tens_scalar_mx scale1r. Qed. + +Lemma tens_scalarN1mx (m n : nat) (M : 'M_(m,n)) : + (-1) *t M = castmx (esym (mul1n _), esym (mul1n _)) (-M). +Proof. by rewrite [-1]mx11_scalar /= tens_scalar_mx !mxE scaleNr scale1r. Qed. + +Lemma trmx_tens {m n p q} (M :'M[R]_(m,n)) (N : 'M[R]_(p,q)) : + (M *t N)^T = M^T *t N^T. +Proof. by apply/matrixP=> i j; rewrite !mxE. Qed. + +Lemma tens_col_mx {m n p q} (r : 'rV[R]_n) + (M :'M[R]_(m, n)) (N : 'M[R]_(p, q)) : + (col_mx r M) *t N = + castmx (esym (mulnDl _ _ _), erefl _) (col_mx (r *t N) (M *t N)). +Proof. +apply/matrixP=> i j. +case: (mxtens_indexP i)=> i0 i1; case: (mxtens_indexP j)=> j0 j1. +rewrite !tensmxE castmxE /= cast_ord_id esymK !mxE /=. +case: splitP=> i0' /= hi0'; case: splitP=> k /= hk. ++ case: (mxtens_indexP k) hk=> k0 k1 /=; rewrite tensmxE. + move=> /(f_equal (edivn^~ p)); rewrite !edivn_eq // => [] [h0 h1]. + by congr (r _ _ * N _ _); apply:val_inj; rewrite /= -?h0 ?h1. ++ move: hk (ltn_ord i1); rewrite hi0'. + by rewrite [i0']ord1 mul0n mul1n add0n ltnNge=> ->; rewrite leq_addr. ++ move: (ltn_ord k); rewrite -hk hi0' ltnNge {1}mul1n. + by rewrite mulnDl {1}mul1n -addnA leq_addr. +case: (mxtens_indexP k) hk=> k0 k1 /=; rewrite tensmxE. +rewrite hi0' mulnDl -addnA=> /addnI. + move=> /(f_equal (edivn^~ p)); rewrite !edivn_eq // => [] [h0 h1]. +by congr (M _ _ * N _ _); apply:val_inj; rewrite /= -?h0 ?h1. +Qed. + +Lemma tens_row_mx {m n p q} (r : 'cV[R]_m) (M :'M[R]_(m,n)) (N : 'M[R]_(p,q)) : + (row_mx r M) *t N = + castmx (erefl _, esym (mulnDl _ _ _)) (row_mx (r *t N) (M *t N)). +Proof. +rewrite -[_ *t _]trmxK trmx_tens tr_row_mx tens_col_mx. +apply/eqP; rewrite -(can2_eq (castmxKV _ _) (castmxK _ _)); apply/eqP. +by rewrite trmx_cast castmx_comp castmx_id tr_col_mx -!trmx_tens !trmxK. +Qed. + +Lemma tens_block_mx {m n p q} + (ul : 'M[R]_1) (ur : 'rV[R]_n) (dl : 'cV[R]_m) + (M :'M[R]_(m,n)) (N : 'M[R]_(p,q)) : + (block_mx ul ur dl M) *t N = + castmx (esym (mulnDl _ _ _), esym (mulnDl _ _ _)) + (block_mx (ul *t N) (ur *t N) (dl *t N) (M *t N)). +Proof. +rewrite !block_mxEv tens_col_mx !tens_row_mx -!cast_col_mx castmx_comp. +by congr (castmx (_,_)); apply nat_irrelevance. +Qed. + + +Fixpoint ntensmx_rec {m n} (A : 'M_(m,n)) k : 'M_(m ^ k.+1,n ^ k.+1) := + if k is k'.+1 then (A *t (ntensmx_rec A k')) else A. + +Definition ntensmx {m n} (A : 'M_(m, n)) k := nosimpl + (if k is k'.+1 return 'M[R]_(m ^ k,n ^ k) then ntensmx_rec A k' else 1). + +Notation "A ^t k" := (ntensmx A k) + (at level 39, left associativity, format "A ^t k"). + +Lemma ntensmx0 : forall {m n} (A : 'M_(m,n)) , A ^t 0 = 1. +Proof. by []. Qed. + +Lemma ntensmx1 : forall {m n} (A : 'M_(m,n)) , A ^t 1 = A. +Proof. by []. Qed. + +Lemma ntensmx2 : forall {m n} (A : 'M_(m,n)) , A ^t 2 = A *t A. +Proof. by []. Qed. + +Lemma ntensmxSS : forall {m n} (A : 'M_(m,n)) k, A ^t k.+2 = A *t A ^t k.+1. +Proof. by []. Qed. + +Definition ntensmxS := (@ntensmx1, @ntensmx2, @ntensmxSS). + +End MxTens. + +Notation "A *t B" := (tensmx A B) + (at level 40, left associativity, format "A *t B"). + +Notation "A ^t k" := (ntensmx A k) + (at level 39, left associativity, format "A ^t k"). + +Section MapMx. +Variables (aR rR : ringType). +Hypothesis f : {rmorphism aR -> rR}. +Local Notation "A ^f" := (map_mx f A) : ring_scope. + +Variables m n p q: nat. +Implicit Type A : 'M[aR]_(m, n). +Implicit Type B : 'M[aR]_(p, q). + +Lemma map_mxT A B : (A *t B)^f = A^f *t B^f :> 'M_(m*p, n*q). +Proof. by apply/matrixP=> i j; rewrite !mxE /= rmorphM. Qed. + +End MapMx. + +Section Misc. + +Lemma tensmx_mul (R : comRingType) m n p q r s + (A : 'M[R]_(m,n)) (B : 'M[R]_(p,q)) (C : 'M[R]_(n, r)) (D : 'M[R]_(q, s)) : + (A *t B) *m (C *t D) = (A *m C) *t (B *m D). +Proof. +apply/matrixP=> /= i j. +case (mxtens_indexP i)=> [im ip] {i}; case (mxtens_indexP j)=> [jr js] {j}. +rewrite !mxE !mxtens_indexK mulr_sum; apply: congr_big=> // k _. +by rewrite !mxE !mxtens_indexK mulrCA !mulrA [C _ _ * A _ _]mulrC. +Qed. + +(* Todo : move to div ? *) +Lemma eq_addl_mul q q' m m' d : m < d -> m' < d -> + (q * d + m == q' * d + m')%N = ((q, m) == (q', m')). +Proof. +move=> lt_md lt_m'd; apply/eqP/eqP; last by move=> [-> ->]. +by move=> /(f_equal (edivn^~ d)); rewrite !edivn_eq. +Qed. + +Lemma tensmx_unit (R : fieldType) m n (A : 'M[R]_m%N) (B : 'M[R]_n%N) : + m != 0%N -> n != 0%N -> A \in unitmx -> B \in unitmx -> (A *t B) \in unitmx. +Proof. +move: m n A B => [|m] [|n] // A B _ _ uA uB. +suff : (A^-1 *t B^-1) *m (A *t B) = 1 by case/mulmx1_unit. +rewrite tensmx_mul !mulVmx //; apply/matrixP=> /= i j. +rewrite !mxE /=; symmetry; rewrite -natrM -!val_eqE /=. +rewrite {1}(divn_eq i n.+1) {1}(divn_eq j n.+1). +by rewrite eq_addl_mul ?ltn_mod // xpair_eqE mulnb. +Qed. + + +Lemma tens_mx_scalar : forall (R : comRingType) + (m n : nat) (c : R) (M : 'M[R]_(m,n)), + M *t c%:M = castmx (esym (muln1 _), esym (muln1 _)) (c *: M). +Proof. +move=> R0 m n c M; apply/matrixP=> i j. +case: (mxtens_indexP i)=> i0 i1; case: (mxtens_indexP j)=> j0 j1. +rewrite tensmxE [i1]ord1 [j1]ord1 !castmxE !mxE /= mulr1n mulrC. +by congr (_ * M _ _); apply: val_inj=> /=; rewrite muln1 addn0. +Qed. + +Lemma tensmx_decr : forall (R : comRingType) m n (M :'M[R]_m) (N : 'M[R]_n), + M *t N = (M *t 1%:M) *m (1%:M *t N). +Proof. by move=> R0 m n M N; rewrite tensmx_mul mul1mx mulmx1. Qed. + +Lemma tensmx_decl : forall (R : comRingType) m n (M :'M[R]_m) (N : 'M[R]_n), + M *t N = (1%:M *t N) *m (M *t 1%:M). +Proof. by move=> R0 m n M N; rewrite tensmx_mul mul1mx mulmx1. Qed. + +End Misc. diff --git a/mathcomp/attic/quote.v b/mathcomp/attic/quote.v new file mode 100644 index 0000000..bde7fac --- /dev/null +++ b/mathcomp/attic/quote.v @@ -0,0 +1,365 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq. + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Structure tProp := TProp {tProp_statement :> Prop; _ : tProp_statement}. +Lemma claim : forall tP : tProp, tP. Proof. by case. Qed. +Hint Resolve claim. + +Canonical Structure True_tProp := TProp Logic.I. +Canonical Structure eq_tProp T (x : T) := TProp (erefl x). +Canonical Structure true_tProp := @TProp true (erefl _). +Canonical Structure and_tProp (P Q : tProp) := + TProp (conj (claim P) (claim Q)). + +Structure postProp (P : Prop) := PostProp {postProp_statement :> tProp; _ : P}. +Canonical Structure tProp_postProp P claimP pP := + PostProp (@TProp P claimP) (claim pP). + +Delimit Scope n_ary_op_scope with QOP. +Delimit Scope quote_scope with QT. + +Fixpoint n_ary n T := if n is n'.+1 then T -> n_ary n' T else T. +Notation "n .-ary" := (n_ary n) (at level 2, format "n .-ary") : type_scope. + +Module Quotation. + +CoInductive n_ary_op T := NaryOp n of n.-ary T. +Notation "f / n" := (@NaryOp _ n f) : n_ary_op_scope. +Definition bind_op T R (op : n_ary_op T) ifun : R := + let: NaryOp n f := op in ifun n f. +Definition arity T op := @bind_op T nat op (fun n _ => n). + +Structure type := Pack {sort :> Type; sym; _ : sym -> n_ary_op sort}. +Notation QuoteType sf := (Pack sf%QOP). +Definition symop T := let: Pack _ _ ops := T return sym T -> n_ary_op T in ops. + +Inductive term S := Var of nat | App of S & seq (term S). + +Lemma term_ind' : forall S (P : term S -> Type), + (forall i, P (Var S i)) -> + (forall s a, foldr prod True (map P a) -> P (App s a)) -> + (forall t, P t). +Proof. +move=> S P P_V P_A; pose fix sz (t : term S) := + if t is App _ a then (foldr maxn 0 (map sz a)).+1 else 0. +move=> t; elim: {t}(sz t) {-2}t (leqnn (sz t)) => [|n IHn] [i | s a] //=. +rewrite ltnS => sz_a; apply: P_A; elim: a sz_a => //= t a IHa. +by rewrite geq_max; case/andP; move/IHn=> Pt; move/IHa. +Qed. + +Bind Scope quote_scope with term. +Notation "''K_' i" := (Var _ i) + (at level 8, i at level 2, format "''K_' i") : quote_scope. +Notation "''[' s x1 .. xn ]" := (App s (x1%QT :: .. [:: xn%QT] ..)) + (at level 0, s at level 2, x1, xn at level 8, + format "''[' '[hv' s x1 .. xn ']' ]") : quote_scope. +Notation "''[' s ]" := (App s [::]) + (at level 0, s at level 2, format "''[' s ]") : quote_scope. + +Section OneType. + +Variable T : type. +Implicit Type P : Prop. +Implicit Type tP : tProp. + +Definition Env := @id (seq T). + +Fixpoint lookup i e : option T := + if i is i'.+1 then lookup i' (behead e) else ohead e. + +Definition interp_app (iarg : term (sym T) -> option T) := + fix loop a n {struct a} : n.-ary T -> option T := + if n is n'.+1 return n.-ary T -> option T + then fun f => if a is t :: a' then obind (loop a' n' \o f) (iarg t) else None + else fun x => if a is [::] then Some x else None. + +Fixpoint interp e t := match t with + | Var i => lookup i e + | App s a => bind_op (symop s) (interp_app (interp e) a) + end. + +Fixpoint wf (t : term (sym T)) := + match t with + | App s a => let: NaryOp n _ := symop s in (n == size a) && all wf a + | Var _ => true + end. + +Fixpoint eval x0 e t := + match t with + | Var i => nth x0 e i + | App s a => + odflt x0 (bind_op (symop s) (interp_app (fun x => Some (eval x0 e x)) a)) + end. + +Lemma interp_wf_eval : forall y0 e t y, + interp e t = Some y -> wf t /\ eval y0 e t = y. +Proof. +move=> y0 e t; elim/term_ind': t => [i|s a IHa] y /=. + by elim: i e => [|i IHi] [|z e] //=; [case | elim: i {IHi} | exact: IHi]. +case: symop => /= n x1. +elim: n x1 a IHa => [|n IHn] x1 [|f a] //=; first by move=> _ []. +case: (interp e f) => //= x []; case/(_ x)=> // -> ->; exact: IHn. +Qed. + +Definition var_val := @id T. +Definition op_val := var_val. + +Structure form e t P := Form {fval; _ : P -> interp e t = Some fval}. +Lemma formP : forall e t tP f, interp e t = Some (@fval e t tP f). +Proof. by move=> e t tP [x <-]. Qed. + +Structure store i x P := Store {stval; _ : P -> lookup i stval = Some x}. +Canonical Structure head_store x e := + @Store 0 x True (Env (x :: Env e)) (fun _ => erefl _). +Lemma tail_store_subproof : forall i x y e tP s, + e = @stval i x tP s -> lookup i.+1 (y :: e) = Some x. +Proof. by move=> i x y _ tP [e /= <- //] ->. Qed. +Canonical Structure tail_store i x y e tP s := + Store (@tail_store_subproof i x y e tP s). + +Lemma var_form_subproof : forall i x P (s : store i x P), + P -> interp (stval s) 'K_i = Some (var_val x). +Proof. by move=> i x P []. Qed. +Canonical Structure var_form i x P s := Form (@var_form_subproof i x P s). + +Lemma op_form_subproof : forall e t tP (f : form e t tP) x, + x = @fval e t tP f -> interp e t = Some (op_val x). +Proof. by move=> e t tP f _ ->; exact: formP. Qed. + +Canonical Structure op_form e t tP f x := + Form (@op_form_subproof e t tP f x). + +Section OpForm. + +Variables (s : sym T) (e : seq T). + +Fixpoint OpForm_type a xa fa n := + if n is n'.+1 then + forall x t tP f, OpForm_type (t :: a) (x :: xa) (@fval e t tP f :: fa) n' + else form e (App s (rev a)) (map op_val (rev xa) = rev fa). + +Definition OpForm_rechyp a (xa fa : seq T) n (x : n.-ary T) := + forall a', map op_val (rev xa) = rev fa -> + interp e (App s (catrev a' a)) = interp_app (interp e) a' x. + +Definition OpForm_rectype a xa fa n (x : n.-ary T) := + OpForm_rechyp a xa fa x -> OpForm_type a xa fa n. + +Definition OpForm_basetype P x a := + (P -> interp e (App s a) = Some x) -> form e (App s a) P. + +Lemma OpForm_recproof : forall a xa fa n (x1 : n.+1.-ary T), + forall x t tP f, OpForm_rechyp a xa fa x1 -> + OpForm_rechyp (t :: a) (x :: xa) (@fval e t tP f :: fa) (x1 x). +Proof. +move=> a xa fa n x1 x t tP f IHx a'; move/(_ (t :: a')): IHx => /=. +rewrite !map_id (formP f) /= => IHx; case/(can_inj (@revK _)) => -> eq_xa. +by rewrite {}IHx ?eq_xa. +Qed. + +Fixpoint OpForm_rec a xa fa n : forall x, @OpForm_rectype a xa fa n x := + if n is _.+1 return forall x, @OpForm_rectype a xa fa n x then + fun _ IHx _ _ _ _ => OpForm_rec (OpForm_recproof IHx) else + fun x IHx => + (if rev a is (t :: a') as rev_a return OpForm_basetype _ _ rev_a then + fun IHx => Form IHx else fun IHx => Form IHx) (IHx [::]). + +Lemma OpForm_subproof : bind_op (symop s) (OpForm_rechyp [::] [::] [::]). +Proof. by case def_s: (symop s) => [n x] a _; rewrite /= def_s. Qed. + +Definition OpForm := + (let: (op/n)%QOP as op_n := symop s + return (bind_op op_n _ : Prop) -> @OpForm_type _ _ _ (arity op_n) in + @OpForm_rec _ _ _ n op) + OpForm_subproof. + +End OpForm. + +Section GenSimp. + +Variable simp : seq T -> term (sym T) -> option T. + +Definition simp_axiom := forall e t x y, + interp e t = Some x -> simp e t = Some y -> x = y. + +Hypothesis simpP : simp_axiom. + +Structure closed := Closed {closed_val :> seq T}. +Canonical Structure head_closed := Closed (Env [::]). +Canonical Structure tail_closed x (ce : closed) := Closed (x :: ce). +Inductive close : seq T -> Prop := Close (ce : closed) : close ce. +Canonical Structure close_tProp ce := TProp (Close ce). + +Lemma simp_form : forall e t y ptP, + forall f : form (Env e) t + (@postProp_statement (close (Env e) /\ simp e t = Some y) ptP), + fval f = y. +Proof. +move=> e t y [tP [_ def_y]] [x /= def_x]; apply: simpP def_y; exact: def_x. +Qed. + +End GenSimp. + +Definition Econs := Cons. +Definition Etag of nat := @idfun. +Definition Enil := Nil. + +Fixpoint simp_env {T'} e i := + if e is x :: e' then omap (Econs (Etag i x)) (simp_env e' i.+1) + else Some (Enil T'). + +Notation "' 'K_' i := x" := (Etag i x) + (at level 200, format "' 'K_' i := x") : quote_tag_scope. +Arguments Scope Econs [type_scope quote_tag_scope _]. + +Notation "[ 'env' d1 ; .. ; d_n ]" := (Econs d1 .. (Econs d_n (Enil _)) ..) + (at level 0, format "[ 'env' '[' d1 ; '/' .. ; '/' d_n ] ']'") + : quote_scope. + +Notation "[ 'env' ]" := (Enil _) + (at level 0, format "[ 'env' ]") : quote_scope. + +Lemma unquote_default : false -> T. Proof. by []. Qed. +Definition unquote e t := + if interp e t is Some x as ox return ox -> T then fun _ => x else + unquote_default. + +Arguments Scope unquote [quote_scope quote_scope _]. + +Lemma end_unquote : true. Proof. by []. Qed. +Definition simp_quote e t := + obind (fun e' => + (if interp e' t as b return (b -> _) -> _ then + fun wf_t' => Some (unquote (wf_t' end_unquote)) + else fun _ => None) id) + (simp_env e 0). + +Lemma simp_quoteP : simp_axiom simp_quote. +Proof. +rewrite /simp_quote => e t x y def_x. +suff ->: simp_env e 0 = Some e by rewrite /unquote /= def_x; case. +by elim: e {def_x} 0 => //= z e IHe i; rewrite IHe. +Qed. + +Definition quote := simp_form simp_quoteP. + +End OneType. + +End Quotation. + +Canonical Structure Quotation.head_store. +Canonical Structure Quotation.tail_store. +Canonical Structure Quotation.var_form. +Canonical Structure Quotation.op_form. +Canonical Structure Quotation.head_closed. +Canonical Structure Quotation.tail_closed. +Canonical Structure Quotation.close_tProp. + +Notation QuoteType sf := (Quotation.Pack sf%QOP). +Notation "f / n" := (@Quotation.NaryOp _ n f) : n_ary_op_scope. + +Notation OpForm := Quotation.OpForm. + +Notation "''K_' i" := (Quotation.Var _ i) + (at level 8, i at level 2, format "''K_' i") : quote_scope. +Notation "''[' s x1 .. xn ]" := + (Quotation.App s (x1%QT :: .. [:: xn%QT] ..)) + (at level 0, s at level 2, x1, xn at level 8, + format "''[' s '[hv' x1 '/' .. '/' xn ']' ]") : quote_scope. +Notation "''[' s ]" := (Quotation.App s [::]) + (at level 0, s at level 2, format "''[' s ]") : quote_scope. +Notation "' 'K_' i := x" := (Quotation.Etag i x) + (at level 200, format "' 'K_' i := x") : quote_tag_scope. +Arguments Scope Quotation.Econs [type_scope quote_tag_scope _]. +Notation "[ 'env' d1 ; .. ; d_n ]" := + (Quotation.Econs d1 .. (Quotation.Econs d_n (Quotation.Enil _)) ..) + (at level 0, format "[ 'env' '[' d1 ; '/' .. ; '/' d_n ] ']'") + : quote_scope. +Notation "[ 'env' ]" := (Quotation.Enil _) + (at level 0, format "[ 'env' ]") : quote_scope. + +Arguments Scope Quotation.unquote [_ quote_scope quote_scope _]. +Notation unquote e t := (@Quotation.unquote _ e t%QT _). + +CoInductive bool_sym := bTrue | bAnd. +Canonical Structure bool_quoteType := + QuoteType (fun s => match s with bTrue => true/0 | bAnd => andb/2 end). +Canonical Structure and_form := Eval hnf in OpForm bAnd. +Canonical Structure true_form := Eval hnf in OpForm bTrue. + +Lemma try_bquote : forall b1 b2 b3, + false && b1 && (b2 && true && b3) && (b2 && b1 && b2) = false && b2. +Proof. +move=> b1 b2 b3. +Time rewrite Quotation.quote. +Time rewrite !Quotation.quote. +by []. +Qed. + +Fixpoint bstore s bt := match bt with +| 'K_i => set_nth false s i true +| '[bAnd t1 t2] => bstore (bstore s t1) t2 +| _ => s +end%QT. + +Fixpoint bread ot i s := match s with +| [::] => odflt '[bTrue] ot +| true :: s' => bread (Some (oapp (fun t => '[bAnd t 'K_i]) 'K_i ot)) i.+1 s' +| false :: s' => bread ot i.+1 s' +end%QT. + +Fixpoint bnormed t i := match t with +| '[bAnd t' 'K_j] => bnormed t' 1 +| 'K_j => i > 0 +| '[bTrue] => i == 0 +| _ => false +end%QT. + +Definition bsimp_fn e t := + if bnormed t 0 then None else + Quotation.interp e (bread None 0 (bstore [::] t)). + +Lemma bsimpP : Quotation.simp_axiom bsimp_fn. +Proof. +pose oand ob1 ob2 := obind (fun b1 => omap (andb b1) ob2) ob1. +have [oaC oaA oaI]: [/\ commutative oand, associative oand & idempotent oand]. + by split; do 6?case=> //. +have oa1: left_id (Some true) oand by case=> [[]|]. +rewrite /bsimp_fn => e t b b'; case: bnormed => //=. +set ie := Quotation.interp e; set s := [::] => def_b. +pose ir j s := ie (bread None j s). +suff{b'} storeP: ir 0 (bstore s t) = oand (ir 0 s) (Some b). + by rewrite [ie _]storeP => [[]]. +elim/Quotation.term_ind': t s => [i | op a IHa] /= s in b def_b *; last first. + case: op def_b; first by case: a {IHa} => //= <-; rewrite oaC oa1. + case: a IHa => //= t1; rewrite /ie /= -/ie; case: (ie _) => //= b1 [] //= t2. + case: (ie t2) => //= b2 [] //= [IHb1 [IHb2 _]] [<-]. + by rewrite (IHb2 _ b2) // (IHb1 _ b1) // -oaA. +have irT: forall s' j, ir j (true :: s') = oand (ie 'K_j)%QT (ir j.+1 s'). + rewrite /ir /= => s' j; move: s' j ('K_j)%QT. + by elim=> [|[|] s' IHs] j u; first 1 [rewrite oaC oa1] || rewrite !IHs -?oaA. +rewrite -{}def_b -{2}[i]addn0; elim: i 0 s => [|i IHi] j. + case=> [|bj s]; first by rewrite oa1. + by case: bj; rewrite !irT oaC // -oaA oaI. +rewrite addSnnS; case=> [|[|] s]; last exact: IHi. + by rewrite /= -set_nth_nil [ir _ _]IHi. +by rewrite !irT IHi oaA. +Qed. + +Definition bsimp := Quotation.simp_form bsimpP. + +Lemma try_bsimp : forall b1 b2 b3, + true && b1 && (b2 && b3) && (b2 && b1 && b2) = b1 && b2 && true && b3. +Proof. +move=> b1 b2 b3. +Time rewrite bsimp. +Time rewrite !bsimp. +by []. +Qed. +Print try_bsimp. + + diff --git a/mathcomp/attic/tutorial.v b/mathcomp/attic/tutorial.v new file mode 100644 index 0000000..3326c90 --- /dev/null +++ b/mathcomp/attic/tutorial.v @@ -0,0 +1,296 @@ +(* (c) Copyright Microsoft Corporation and Inria. All rights reserved. *) +Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq. + + +Section HilbertSaxiom. + +Variables A B C : Prop. + +Lemma HilbertS : (A -> B -> C) -> (A -> B) -> A -> C. +Proof. +move=> hAiBiC hAiB hA. +move: hAiBiC. +apply. + by []. +by apply: hAiB. +Qed. + +Hypotheses (hAiBiC : A -> B -> C) (hAiB : A -> B) (hA : A). + +Lemma HilbertS2 : C. +Proof. +apply: hAiBiC; first by apply: hA. +exact: hAiB. +Qed. + +Check (hAiB hA). + +Lemma HilbertS3 : C. +Proof. by apply: hAiBiC; last exact: hAiB. Qed. + +Lemma HilbertS4 : C. +Proof. exact: (hAiBiC _ (hAiB _)). Qed. + +Lemma HilbertS5 : C. +Proof. exact: hAiBiC (hAiB _). Qed. + +Lemma HilbertS6 : C. +Proof. exact HilbertS5. Qed. + +End HilbertSaxiom. + + + +Section Symmetric_Conjunction_Disjunction. + +Print bool. + +Lemma andb_sym : forall A B : bool, A && B -> B && A. +Proof. +case. + by case. +by []. +Qed. + +Lemma andb_sym2 : forall A B : bool, A && B -> B && A. +Proof. by case; case. Qed. + +Lemma andb_sym3 : forall A B : bool, A && B -> B && A. +Proof. by do 2! case. Qed. + +Variables (C D : Prop) (hC : C) (hD : D). +Check (and C D). +Print and. +Check conj. +Check (conj hC hD). + +Lemma and_sym : forall A B : Prop, A /\ B -> B /\ A. +Proof. by move=> A1 B []. Qed. + +Print or. + +Check or_introl. + +Lemma or_sym : forall A B : Prop, A \/ B -> B \/ A. +Proof. by move=> A B [hA | hB]; [apply: or_intror | apply: or_introl]. Qed. + +Lemma or_sym2 : forall A B : bool, A \/ B -> B \/ A. +Proof. by move=> [] [] AorB; apply/orP; move/orP : AorB. Qed. + +End Symmetric_Conjunction_Disjunction. + + + +Section R_sym_trans. + +Variables (D : Type) (R : D -> D -> Prop). + +Hypothesis R_sym : forall x y, R x y -> R y x. + +Hypothesis R_trans : forall x y z, R x y -> R y z -> R x z. + +Lemma refl_if : forall x : D, (exists y, R x y) -> R x x. +Proof. +move=> x [y Rxy]. +exact: R_trans (R_sym _ y _). +Qed. + +End R_sym_trans. + + + +Section Smullyan_drinker. + +Variables (D : Type) (P : D -> Prop). +Hypotheses (d : D) (EM : forall A, A \/ ~A). + +Lemma drinker : exists x, P x -> forall y, P y. +Proof. +(* case: (EM (exists y, ~P y)) => [[y notPy]| nonotPy] *) +have [[y notPy]| nonotPy] := EM (exists y, ~P y); first by exists y. +exists d => _ y; case: (EM (P y)) => // notPy. +by case: nonotPy; exists y. +Qed. + +End Smullyan_drinker. + + + +Section Equality. + +Variable f : nat -> nat. +Hypothesis f00 : f 0 = 0. + +Lemma fkk : forall k, k = 0 -> f k = k. +Proof. by move=> k k0; rewrite k0. Qed. + +Lemma fkk2 : forall k, k = 0 -> f k = k. +Proof. by move=> k ->. Qed. + +Variable f10 : f 1 = f 0. + +Lemma ff10 : f (f 1) = 0. +Proof. by rewrite f10 f00. Qed. + +Variables (D : eqType) (x y : D). + +Lemma eq_prop_bool : x = y -> x == y. +Proof. by move/eqP. Qed. + +Lemma eq_bool_prop : x == y -> x = y. +Proof. by move/eqP. Qed. + +End Equality. + + + +Section Using_Definition. + +Variable U : Type. + +Definition set := U -> Prop. + +Definition subset (A B : set) := forall x, A x -> B x. + +Definition transitive (T : Type) (R : T -> T -> Prop) := + forall x y z, R x y -> R y z -> R x z. + +Lemma subset_trans : transitive set subset. +Proof. +rewrite /transitive /subset => x y z subxy subyz t xt. +by apply: subyz; apply: subxy. +Qed. + +Lemma subset_trans2 : transitive set subset. +Proof. +move=> x y z subxy subyz t. +by move/subxy; move/subyz. +Qed. + +End Using_Definition. + + +Section Basic_ssrnat. + + +Lemma three : S (S (S O)) = 3 /\ 3 = 0.+1.+1.+1. +Proof. by []. Qed. + +Lemma concrete_plus : plus 16 64 = 80. +Proof. (*simpl.*) by []. Qed. + +Lemma concrete_addn : 16 + 64 = 80. +Proof. (*simpl.*) by []. Qed. + +Lemma concrete_le : le 1 3. +Proof. by apply: (Le.le_trans _ 2); apply: Le.le_n_Sn. Qed. + +Lemma concrete_big_le : le 16 64. +Proof. by auto 47 with arith. Qed. + +Lemma concrete_big_leq : 0 <= 51. +Proof. by []. Qed. + +Lemma semi_concrete_leq : forall n m, n <= m -> 51 + n <= 51 + m. +Proof. by []. Qed. + +Lemma concrete_arith : (50 < 100) && (3 + 4 < 3 * 4 <= 17 - 2). +Proof. by []. Qed. + +Lemma plus_com : forall m1 n1, n1 + m1 = m1 + n1. +Proof. +by elim=> [| n IHn m]; [elim | rewrite -[n.+1 + m]/(n + m).+1 -IHn; elim: m]. +Qed. + +End Basic_ssrnat. + + +Section Euclidean_division. + + +Set Implicit Arguments. +Unset Strict Implicit. +Unset Printing Implicit Defensive. + +Definition edivn_rec d := fix loop (m q : nat) {struct m} := + if m - d is m'.+1 then loop m' q.+1 else (q, m). + +Definition edivn m d := if d is d'.+1 then edivn_rec d' m 0 else (0, m). + +CoInductive edivn_spec (m d : nat) : nat * nat -> Type := + EdivnSpec q r of m = q * d + r & (d > 0) ==> (r < d) : edivn_spec m d (q, r). + +Lemma edivnP : forall m d, edivn_spec m d (edivn m d). +Proof. +move=> m [|d] //=; rewrite -{1}[m]/(0 * d.+1 + m). +elim: m {-2}m 0 (leqnn m) => [|n IHn] [|m] q //=; rewrite ltnS => le_mn. +rewrite subn_if_gt; case: ltnP => // le_dm. +rewrite -{1}(subnKC le_dm) -addSn addnA -mulSnr; apply: IHn. +apply: leq_trans le_mn; exact: leq_subr. +Qed. + +Lemma edivn_eq : forall d q r, r < d -> edivn (q * d + r) d = (q, r). +Proof. +move=> d q r lt_rd; have d_gt0: 0 < d by exact: leq_trans lt_rd. +case: edivnP lt_rd => q' r'; rewrite d_gt0 /=. +wlog: q q' r r' / q <= q' by case (ltnP q q'); last symmetry; eauto. +rewrite leq_eqVlt; case: eqP => [-> _|_] /=; first by move/addnI->. +rewrite -(leq_pmul2r d_gt0); move/leq_add=> Hqr Eqr _; move/Hqr {Hqr}. +by rewrite addnS ltnNge mulSn -addnA Eqr addnCA addnA leq_addr. +Qed. + +CoInductive edivn_spec_right : nat -> nat -> nat * nat -> Type := + EdivnSpec_right m d q r of m = q * d + r & (d > 0) ==> (r < d) : + edivn_spec_right m d (q, r). + +CoInductive edivn_spec_left (m d : nat)(qr : nat * nat) : Type := +EdivnSpec_left of m = (fst qr) * d + (snd qr) & (d > 0) ==> (snd qr < d) : + edivn_spec_left m d qr. + + +Lemma edivnP_left : forall m d, edivn_spec_left m d (edivn m d). +Proof. +move=> m [|d] //=; rewrite -{1}[m]/(0 * d.+1 + m). +elim: m {-2}m 0 (leqnn m) => [|n IHn] [|m] q //=; rewrite ltnS => le_mn. +rewrite subn_if_gt; case: ltnP => // le_dm. +rewrite -{1}(subnKC le_dm) -addSn addnA -mulSnr; apply: IHn. +apply: leq_trans le_mn; exact: leq_subr. +Qed. + +Lemma edivnP_right : forall m d, edivn_spec_right m d (edivn m d). +Proof. +move=> m [|d] //=; rewrite -{1}[m]/(0 * d.+1 + m). +elim: m {-2}m 0 (leqnn m) => [|n IHn] [|m] q //=; rewrite ltnS => le_mn. +rewrite subn_if_gt; case: ltnP => // le_dm. +rewrite -{1}(subnKC le_dm) -addSn addnA -mulSnr; apply: IHn. +apply: leq_trans le_mn; exact: leq_subr. +Qed. + +Lemma edivn_eq_right : forall d q r, r < d -> edivn (q * d + r) d = (q, r). +Proof. +move=> d q r lt_rd; have d_gt0: 0 < d by exact: leq_trans lt_rd. +set m := q * d + r; have: m = q * d + r by []. +set d' := d; have: d' = d by []. +case: (edivnP_right m d') => {m d'} m d' q' r' -> lt_r'd' d'd q'd'r'. +move: q'd'r' lt_r'd' lt_rd; rewrite d'd d_gt0 {d'd m} /=. +wlog: q q' r r' / q <= q' by case (ltnP q q'); last symmetry; eauto. +rewrite leq_eqVlt; case: eqP => [-> _|_] /=; first by move/addnI->. +rewrite -(leq_pmul2r d_gt0); move/leq_add=> Hqr Eqr _; move/Hqr {Hqr}. +by rewrite addnS ltnNge mulSn -addnA -Eqr addnCA addnA leq_addr. +Qed. + + +Lemma edivn_eq_left : forall d q r, r < d -> edivn (q * d + r) d = (q, r). +Proof. +move=> d q r lt_rd; have d_gt0: 0 < d by exact: leq_trans lt_rd. +case: (edivnP_left (q * d + r) d) lt_rd; rewrite d_gt0 /=. +set q':= (edivn (q * d + r) d).1; set r':= (edivn (q * d + r) d).2. +rewrite (surjective_pairing (edivn (q * d + r) d)) -/q' -/r'. +wlog: q r q' r' / q <= q' by case (ltnP q q'); last symmetry; eauto. +rewrite leq_eqVlt; case: eqP => [-> _|_] /=; first by move/addnI->. +rewrite -(leq_pmul2r d_gt0); move/leq_add=> Hqr Eqr _; move/Hqr {Hqr}. +by rewrite addnS ltnNge mulSn -addnA Eqr addnCA addnA leq_addr. +Qed. + + +End Euclidean_division.
\ No newline at end of file |
